codegen.test.ts86 lines · main
| 1 | import { test } from 'node:test'; |
| 2 | import { strict as assert } from 'node:assert'; |
| 3 | |
| 4 | import { generate, type SchemaSnapshot } from './codegen.js'; |
| 5 | |
| 6 | test('generate emits dataModel.d.ts with Doc<T> for each table', () => { |
| 7 | const snapshot: SchemaSnapshot = { |
| 8 | version: 1, |
| 9 | tables: { |
| 10 | notes: { |
| 11 | columns: { |
| 12 | id: { sqlType: 'text', nullable: false, primaryKey: true, unique: false }, |
| 13 | body: { sqlType: 'text', nullable: false, primaryKey: false, unique: false }, |
| 14 | archived: { sqlType: 'boolean', nullable: true, primaryKey: false, unique: false }, |
| 15 | }, |
| 16 | indexes: [], |
| 17 | }, |
| 18 | }, |
| 19 | }; |
| 20 | const out = generate(snapshot, []); |
| 21 | const dm = out.get('briven/_generated/dataModel.d.ts'); |
| 22 | assert.ok(dm, 'dataModel.d.ts must be emitted'); |
| 23 | assert.match(dm, /export interface Notes \{/); |
| 24 | assert.match(dm, /id: string;/); |
| 25 | assert.match(dm, /body: string;/); |
| 26 | assert.match(dm, /archived: boolean \| null;/); |
| 27 | assert.match(dm, /export type Doc<T extends keyof Tables> = Tables\[T\];/); |
| 28 | }); |
| 29 | |
| 30 | test('generate emits api.ts with imports + typed api object', () => { |
| 31 | const snapshot: SchemaSnapshot = { version: 1, tables: {} }; |
| 32 | const out = generate(snapshot, ['listNotes.ts', 'createNote.ts']); |
| 33 | const api = out.get('briven/_generated/api.ts'); |
| 34 | assert.ok(api, 'api.ts must be emitted'); |
| 35 | assert.match(api, /import listNotes from '\.\.\/functions\/listNotes\.js';/); |
| 36 | assert.match(api, /import createNote from '\.\.\/functions\/createNote\.js';/); |
| 37 | assert.match(api, /export const api = \{/); |
| 38 | assert.match(api, / {2}listNotes,/); |
| 39 | assert.match(api, / {2}createNote,/); |
| 40 | }); |
| 41 | |
| 42 | test('generate maps every supported sql type to TS', () => { |
| 43 | const snapshot: SchemaSnapshot = { |
| 44 | version: 1, |
| 45 | tables: { |
| 46 | t: { |
| 47 | columns: { |
| 48 | a: { sqlType: 'text', nullable: false, primaryKey: true, unique: false }, |
| 49 | b: { sqlType: 'integer', nullable: false, primaryKey: false, unique: false }, |
| 50 | c: { sqlType: 'bigint', nullable: false, primaryKey: false, unique: false }, |
| 51 | d: { sqlType: 'boolean', nullable: false, primaryKey: false, unique: false }, |
| 52 | e: { sqlType: 'timestamptz', nullable: false, primaryKey: false, unique: false }, |
| 53 | f: { sqlType: 'jsonb', nullable: false, primaryKey: false, unique: false }, |
| 54 | g: { sqlType: 'uuid', nullable: false, primaryKey: false, unique: false }, |
| 55 | h: { sqlType: 'varchar(255)', nullable: false, primaryKey: false, unique: false }, |
| 56 | i: { sqlType: 'vector(1536)', nullable: false, primaryKey: false, unique: false }, |
| 57 | }, |
| 58 | indexes: [], |
| 59 | }, |
| 60 | }, |
| 61 | }; |
| 62 | const dm = generate(snapshot, []).get('briven/_generated/dataModel.d.ts')!; |
| 63 | assert.match(dm, /a: string;/); |
| 64 | assert.match(dm, /b: number;/); |
| 65 | assert.match(dm, /c: bigint;/); |
| 66 | assert.match(dm, /d: boolean;/); |
| 67 | assert.match(dm, /e: string;/); |
| 68 | assert.match(dm, /f: unknown;/); |
| 69 | assert.match(dm, /g: string;/); |
| 70 | assert.match(dm, /h: string;/); |
| 71 | assert.match(dm, /i: number\[\];/); |
| 72 | }); |
| 73 | |
| 74 | test('generate always includes a README in _generated', () => { |
| 75 | const out = generate({ version: 1, tables: {} }, []); |
| 76 | const readme = out.get('briven/_generated/README.md'); |
| 77 | assert.ok(readme); |
| 78 | assert.match(readme, /Generated by briven cli\. Do not edit by hand\./); |
| 79 | }); |
| 80 | |
| 81 | test('generate emits empty api object when no functions', () => { |
| 82 | const out = generate({ version: 1, tables: {} }, []); |
| 83 | const api = out.get('briven/_generated/api.ts'); |
| 84 | assert.ok(api); |
| 85 | assert.match(api, /export const api = \{\} as const;/); |
| 86 | }); |