@casekit/orm2-cli 0.0.0-20250331202540 → 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/build/cli.js +1 -2
  2. package/build/commands/db-drop/handler.js +0 -3
  3. package/build/commands/db-drop.test.js +1 -0
  4. package/build/commands/db-pull/handler.js +21 -8
  5. package/build/commands/db-pull/options.d.ts +5 -0
  6. package/build/commands/db-pull/options.js +5 -0
  7. package/build/commands/db-pull/util/relationNames.d.ts +3 -0
  8. package/build/commands/db-pull/util/relationNames.js +14 -0
  9. package/build/commands/db-pull/util/relationNames.test.js +61 -0
  10. package/build/commands/db-pull/util/renderDefault.d.ts +3 -0
  11. package/build/commands/db-pull/util/renderDefault.js +46 -0
  12. package/build/commands/db-pull/util/renderDefault.test.d.ts +1 -0
  13. package/build/commands/db-pull/util/renderDefault.test.js +67 -0
  14. package/build/commands/db-pull/util/renderFieldDefinition.d.ts +2 -0
  15. package/build/commands/db-pull/util/renderFieldDefinition.js +50 -0
  16. package/build/commands/db-pull/util/renderFieldDefinition.test.d.ts +1 -0
  17. package/build/commands/db-pull/util/renderFieldDefinition.test.js +182 -0
  18. package/build/commands/db-pull/util/renderModel.basic.test.d.ts +1 -0
  19. package/build/commands/db-pull/util/renderModel.basic.test.js +169 -0
  20. package/build/commands/db-pull/util/renderModel.constraints.test.d.ts +1 -0
  21. package/build/commands/db-pull/util/renderModel.constraints.test.js +677 -0
  22. package/build/commands/db-pull/util/renderModel.d.ts +2 -0
  23. package/build/commands/db-pull/util/renderModel.defaultValues.test.d.ts +1 -0
  24. package/build/commands/db-pull/util/renderModel.defaultValues.test.js +518 -0
  25. package/build/commands/db-pull/util/renderModel.js +88 -0
  26. package/build/commands/db-pull/util/renderModel.relations.test.d.ts +1 -0
  27. package/build/commands/db-pull/util/renderModel.relations.test.js +880 -0
  28. package/build/commands/db-pull/util/renderModel.types.test.d.ts +1 -0
  29. package/build/commands/db-pull/util/renderModel.types.test.js +703 -0
  30. package/build/commands/db-pull/util/renderRelations.d.ts +2 -0
  31. package/build/commands/db-pull/util/renderRelations.js +55 -0
  32. package/build/commands/db-pull/util/renderRelations.test.d.ts +1 -0
  33. package/build/commands/db-pull/util/renderRelations.test.js +165 -0
  34. package/build/commands/db-pull/util/renderType.d.ts +6 -0
  35. package/build/commands/db-pull/util/renderType.js +55 -0
  36. package/build/commands/db-pull/util/renderType.test.d.ts +1 -0
  37. package/build/commands/db-pull/util/renderType.test.js +46 -0
  38. package/build/commands/db-pull.d.ts +10 -0
  39. package/build/commands/db-pull.test.js +625 -0
  40. package/build/commands/db-push/handler.js +0 -3
  41. package/build/commands/init/handler.js +16 -3
  42. package/build/commands/init/util/generateConfigFile.js +2 -3
  43. package/build/commands/init/util/generateDbFile.js +13 -24
  44. package/build/commands/init/util/generateModelsFile.d.ts +1 -1
  45. package/build/commands/init/util/generateModelsFile.js +6 -2
  46. package/build/commands/init.test.js +19 -31
  47. package/build/types.d.ts +2 -2
  48. package/build/util/createOrOverwriteFile.d.ts +1 -1
  49. package/build/util/createOrOverwriteFile.js +1 -1
  50. package/build/util/loadConfig.js +5 -1
  51. package/package.json +26 -25
  52. package/build/commands/generate-model/handler.d.ts +0 -3
  53. package/build/commands/generate-model/handler.js +0 -10
  54. package/build/commands/generate-model/options.d.ts +0 -18
  55. package/build/commands/generate-model/options.js +0 -18
  56. package/build/commands/generate-model/util/generateModelFile.d.ts +0 -3
  57. package/build/commands/generate-model/util/generateModelFile.js +0 -59
  58. package/build/commands/generate-model/util/generateModelFile.test.js +0 -67
  59. package/build/commands/generate-model/util/regenerateModelsFile.d.ts +0 -2
  60. package/build/commands/generate-model/util/regenerateModelsFile.js +0 -50
  61. package/build/commands/generate-model.d.ts +0 -40
  62. package/build/commands/generate-model.js +0 -8
  63. package/build/commands/generate-model.test.js +0 -55
  64. /package/build/commands/{generate-model/util/generateModelFile.test.d.ts → db-pull/util/relationNames.test.d.ts} +0 -0
  65. /package/build/commands/{generate-model.test.d.ts → db-pull.test.d.ts} +0 -0
@@ -0,0 +1,880 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { unindent } from "@casekit/unindent";
3
+ import { renderModel } from "./renderModel.js";
4
+ describe("renderModel - relations", () => {
5
+ it("generates N:1 relation from foreign key", async () => {
6
+ const table = {
7
+ schema: "public",
8
+ name: "posts",
9
+ columns: [
10
+ {
11
+ schema: "public",
12
+ table: "posts",
13
+ column: "id",
14
+ ordinalPosition: 1,
15
+ type: "integer",
16
+ default: null,
17
+ nullable: false,
18
+ udtSchema: "pg_catalog",
19
+ udt: "int4",
20
+ elementType: null,
21
+ elementTypeSchema: null,
22
+ cardinality: 0,
23
+ size: null,
24
+ isSerial: false,
25
+ },
26
+ {
27
+ schema: "public",
28
+ table: "posts",
29
+ column: "author_id",
30
+ ordinalPosition: 2,
31
+ type: "integer",
32
+ default: null,
33
+ nullable: false,
34
+ udtSchema: "pg_catalog",
35
+ udt: "int4",
36
+ elementType: null,
37
+ elementTypeSchema: null,
38
+ cardinality: 0,
39
+ size: null,
40
+ isSerial: false,
41
+ },
42
+ ],
43
+ foreignKeys: [
44
+ {
45
+ schema: "public",
46
+ constraintName: "posts_author_id_fkey",
47
+ tableFrom: "posts",
48
+ columnsFrom: ["author_id"],
49
+ tableTo: "users",
50
+ columnsTo: ["id"],
51
+ },
52
+ ],
53
+ primaryKey: null,
54
+ uniqueConstraints: [],
55
+ };
56
+ const result = await renderModel(table, []);
57
+ expect(result.trim()).toBe(unindent `
58
+ import { type ModelDefinition } from "@casekit/orm2";
59
+
60
+ export const posts = {
61
+ fields: {
62
+ id: { type: "integer" },
63
+ authorId: {
64
+ column: "author_id",
65
+ type: "integer",
66
+ references: { model: "users", field: "id" },
67
+ },
68
+ },
69
+ relations: {
70
+ author: {
71
+ type: "N:1",
72
+ model: "users",
73
+ fromField: "authorId",
74
+ toField: "id",
75
+ },
76
+ },
77
+ } as const satisfies ModelDefinition;
78
+ `);
79
+ });
80
+ it("generates 1:N relation for reverse foreign key", async () => {
81
+ const table = {
82
+ schema: "public",
83
+ name: "users",
84
+ columns: [
85
+ {
86
+ schema: "public",
87
+ table: "users",
88
+ column: "id",
89
+ ordinalPosition: 1,
90
+ type: "integer",
91
+ default: null,
92
+ nullable: false,
93
+ udtSchema: "pg_catalog",
94
+ udt: "int4",
95
+ elementType: null,
96
+ elementTypeSchema: null,
97
+ cardinality: 0,
98
+ size: null,
99
+ isSerial: false,
100
+ },
101
+ {
102
+ schema: "public",
103
+ table: "users",
104
+ column: "name",
105
+ ordinalPosition: 2,
106
+ type: "text",
107
+ default: null,
108
+ nullable: false,
109
+ udtSchema: "pg_catalog",
110
+ udt: "text",
111
+ elementType: null,
112
+ elementTypeSchema: null,
113
+ cardinality: 0,
114
+ size: null,
115
+ isSerial: false,
116
+ },
117
+ ],
118
+ foreignKeys: [],
119
+ primaryKey: null,
120
+ uniqueConstraints: [],
121
+ };
122
+ const allTables = [
123
+ table,
124
+ {
125
+ schema: "public",
126
+ name: "posts",
127
+ columns: [
128
+ {
129
+ schema: "public",
130
+ table: "posts",
131
+ column: "author_id",
132
+ ordinalPosition: 1,
133
+ type: "integer",
134
+ default: null,
135
+ nullable: false,
136
+ udtSchema: "pg_catalog",
137
+ udt: "int4",
138
+ elementType: null,
139
+ elementTypeSchema: null,
140
+ cardinality: 0,
141
+ size: null,
142
+ isSerial: false,
143
+ },
144
+ ],
145
+ foreignKeys: [
146
+ {
147
+ schema: "public",
148
+ constraintName: "posts_author_id_fkey",
149
+ tableFrom: "posts",
150
+ columnsFrom: ["author_id"],
151
+ tableTo: "users",
152
+ columnsTo: ["id"],
153
+ },
154
+ ],
155
+ primaryKey: null,
156
+ uniqueConstraints: [],
157
+ },
158
+ ];
159
+ const result = await renderModel(table, allTables);
160
+ expect(result.trim()).toBe(unindent `
161
+ import { type ModelDefinition } from "@casekit/orm2";
162
+
163
+ export const users = {
164
+ fields: {
165
+ id: { type: "integer" },
166
+ name: { type: "text" },
167
+ },
168
+ relations: {
169
+ authorPosts: {
170
+ type: "1:N",
171
+ model: "posts",
172
+ fromField: "id",
173
+ toField: "authorId",
174
+ },
175
+ },
176
+ } as const satisfies ModelDefinition;
177
+ `);
178
+ });
179
+ it("generates N:1 relation with non-id foreign key", async () => {
180
+ const table = {
181
+ schema: "public",
182
+ name: "posts",
183
+ columns: [
184
+ {
185
+ schema: "public",
186
+ table: "posts",
187
+ column: "id",
188
+ ordinalPosition: 1,
189
+ type: "integer",
190
+ default: null,
191
+ nullable: false,
192
+ udtSchema: "pg_catalog",
193
+ udt: "int4",
194
+ elementType: null,
195
+ elementTypeSchema: null,
196
+ cardinality: 0,
197
+ size: null,
198
+ isSerial: false,
199
+ },
200
+ {
201
+ schema: "public",
202
+ table: "posts",
203
+ column: "color_hex",
204
+ ordinalPosition: 2,
205
+ type: "text",
206
+ default: null,
207
+ nullable: true,
208
+ udtSchema: "pg_catalog",
209
+ udt: "text",
210
+ elementType: null,
211
+ elementTypeSchema: null,
212
+ cardinality: 0,
213
+ size: null,
214
+ isSerial: false,
215
+ },
216
+ ],
217
+ foreignKeys: [
218
+ {
219
+ schema: "public",
220
+ constraintName: "posts_color_hex_fkey",
221
+ tableFrom: "posts",
222
+ columnsFrom: ["color_hex"],
223
+ tableTo: "colors",
224
+ columnsTo: ["hex"],
225
+ },
226
+ ],
227
+ primaryKey: null,
228
+ uniqueConstraints: [],
229
+ };
230
+ const result = await renderModel(table, []);
231
+ expect(result.trim()).toBe(unindent `
232
+ import { type ModelDefinition } from "@casekit/orm2";
233
+
234
+ export const posts = {
235
+ fields: {
236
+ id: { type: "integer" },
237
+ colorHex: {
238
+ column: "color_hex",
239
+ type: "text",
240
+ nullable: true,
241
+ references: { model: "colors", field: "hex" },
242
+ },
243
+ },
244
+ relations: {
245
+ colorHex: {
246
+ type: "N:1",
247
+ model: "colors",
248
+ fromField: "colorHex",
249
+ toField: "hex",
250
+ optional: true,
251
+ },
252
+ },
253
+ } as const satisfies ModelDefinition;
254
+ `);
255
+ });
256
+ it("generates relation with custom relation name for non-standard foreign key", async () => {
257
+ const table = {
258
+ schema: "public",
259
+ name: "posts",
260
+ columns: [
261
+ {
262
+ schema: "public",
263
+ table: "posts",
264
+ column: "id",
265
+ ordinalPosition: 1,
266
+ type: "integer",
267
+ default: null,
268
+ nullable: false,
269
+ udtSchema: "pg_catalog",
270
+ udt: "int4",
271
+ elementType: null,
272
+ elementTypeSchema: null,
273
+ cardinality: 0,
274
+ size: null,
275
+ isSerial: false,
276
+ },
277
+ {
278
+ schema: "public",
279
+ table: "posts",
280
+ column: "created_by_user_id",
281
+ ordinalPosition: 2,
282
+ type: "integer",
283
+ default: null,
284
+ nullable: false,
285
+ udtSchema: "pg_catalog",
286
+ udt: "int4",
287
+ elementType: null,
288
+ elementTypeSchema: null,
289
+ cardinality: 0,
290
+ size: null,
291
+ isSerial: false,
292
+ },
293
+ ],
294
+ foreignKeys: [
295
+ {
296
+ schema: "public",
297
+ constraintName: "posts_created_by_user_id_fkey",
298
+ tableFrom: "posts",
299
+ columnsFrom: ["created_by_user_id"],
300
+ tableTo: "users",
301
+ columnsTo: ["id"],
302
+ },
303
+ ],
304
+ primaryKey: null,
305
+ uniqueConstraints: [],
306
+ };
307
+ const result = await renderModel(table, []);
308
+ expect(result.trim()).toBe(unindent `
309
+ import { type ModelDefinition } from "@casekit/orm2";
310
+
311
+ export const posts = {
312
+ fields: {
313
+ id: { type: "integer" },
314
+ createdByUserId: {
315
+ column: "created_by_user_id",
316
+ type: "integer",
317
+ references: { model: "users", field: "id" },
318
+ },
319
+ },
320
+ relations: {
321
+ createdByUser: {
322
+ type: "N:1",
323
+ model: "users",
324
+ fromField: "createdByUserId",
325
+ toField: "id",
326
+ },
327
+ },
328
+ } as const satisfies ModelDefinition;
329
+ `);
330
+ });
331
+ it("generates 1:N relation with custom name for reverse foreign key", async () => {
332
+ const table = {
333
+ schema: "public",
334
+ name: "users",
335
+ columns: [
336
+ {
337
+ schema: "public",
338
+ table: "users",
339
+ column: "id",
340
+ ordinalPosition: 1,
341
+ type: "integer",
342
+ default: null,
343
+ nullable: false,
344
+ udtSchema: "pg_catalog",
345
+ udt: "int4",
346
+ elementType: null,
347
+ elementTypeSchema: null,
348
+ cardinality: 0,
349
+ size: null,
350
+ isSerial: false,
351
+ },
352
+ ],
353
+ foreignKeys: [],
354
+ primaryKey: null,
355
+ uniqueConstraints: [],
356
+ };
357
+ const allTables = [
358
+ table,
359
+ {
360
+ schema: "public",
361
+ name: "posts",
362
+ columns: [
363
+ {
364
+ schema: "public",
365
+ table: "posts",
366
+ column: "created_by_user_id",
367
+ ordinalPosition: 1,
368
+ type: "integer",
369
+ default: null,
370
+ nullable: false,
371
+ udtSchema: "pg_catalog",
372
+ udt: "int4",
373
+ elementType: null,
374
+ elementTypeSchema: null,
375
+ cardinality: 0,
376
+ size: null,
377
+ isSerial: false,
378
+ },
379
+ ],
380
+ foreignKeys: [
381
+ {
382
+ schema: "public",
383
+ constraintName: "posts_created_by_user_id_fkey",
384
+ tableFrom: "posts",
385
+ columnsFrom: ["created_by_user_id"],
386
+ tableTo: "users",
387
+ columnsTo: ["id"],
388
+ },
389
+ ],
390
+ primaryKey: null,
391
+ uniqueConstraints: [],
392
+ },
393
+ ];
394
+ const result = await renderModel(table, allTables);
395
+ expect(result.trim()).toBe(unindent `
396
+ import { type ModelDefinition } from "@casekit/orm2";
397
+
398
+ export const users = {
399
+ fields: {
400
+ id: { type: "integer" },
401
+ },
402
+ relations: {
403
+ createdByUserPosts: {
404
+ type: "1:N",
405
+ model: "posts",
406
+ fromField: "id",
407
+ toField: "createdByUserId",
408
+ },
409
+ },
410
+ } as const satisfies ModelDefinition;
411
+ `);
412
+ });
413
+ it("generates composite foreign key relations", async () => {
414
+ const table = {
415
+ schema: "public",
416
+ name: "employees",
417
+ columns: [
418
+ {
419
+ schema: "public",
420
+ table: "employees",
421
+ column: "id",
422
+ ordinalPosition: 1,
423
+ type: "integer",
424
+ default: null,
425
+ nullable: false,
426
+ udtSchema: "pg_catalog",
427
+ udt: "int4",
428
+ elementType: null,
429
+ elementTypeSchema: null,
430
+ cardinality: 0,
431
+ size: null,
432
+ isSerial: false,
433
+ },
434
+ {
435
+ schema: "public",
436
+ table: "employees",
437
+ column: "company_id",
438
+ ordinalPosition: 2,
439
+ type: "integer",
440
+ default: null,
441
+ nullable: false,
442
+ udtSchema: "pg_catalog",
443
+ udt: "int4",
444
+ elementType: null,
445
+ elementTypeSchema: null,
446
+ cardinality: 0,
447
+ size: null,
448
+ isSerial: false,
449
+ },
450
+ {
451
+ schema: "public",
452
+ table: "employees",
453
+ column: "company_code",
454
+ ordinalPosition: 3,
455
+ type: "text",
456
+ default: null,
457
+ nullable: false,
458
+ udtSchema: "pg_catalog",
459
+ udt: "text",
460
+ elementType: null,
461
+ elementTypeSchema: null,
462
+ cardinality: 0,
463
+ size: null,
464
+ isSerial: false,
465
+ },
466
+ ],
467
+ foreignKeys: [
468
+ {
469
+ schema: "public",
470
+ constraintName: "employees_company_fkey",
471
+ tableFrom: "employees",
472
+ columnsFrom: ["company_id", "company_code"],
473
+ tableTo: "companies",
474
+ columnsTo: ["id", "code"],
475
+ },
476
+ ],
477
+ primaryKey: null,
478
+ uniqueConstraints: [],
479
+ };
480
+ const result = await renderModel(table, []);
481
+ expect(result.trim()).toBe(unindent `
482
+ import { type ModelDefinition } from "@casekit/orm2";
483
+
484
+ export const employees = {
485
+ fields: {
486
+ id: { type: "integer" },
487
+ companyId: { column: "company_id", type: "integer" },
488
+ companyCode: { column: "company_code", type: "text" },
489
+ },
490
+ foreignKeys: [
491
+ {
492
+ fields: ["companyId", "companyCode"],
493
+ references: {
494
+ model: "companies",
495
+ fields: ["id", "code"],
496
+ },
497
+ },
498
+ ],
499
+ relations: {
500
+ companyCompanyCode: {
501
+ type: "N:1",
502
+ model: "companies",
503
+ fromField: ["companyId", "companyCode"],
504
+ toField: ["id", "code"],
505
+ },
506
+ },
507
+ } as const satisfies ModelDefinition;
508
+ `);
509
+ });
510
+ it("generates multiple relations from the same table", async () => {
511
+ const table = {
512
+ schema: "public",
513
+ name: "posts",
514
+ columns: [
515
+ {
516
+ schema: "public",
517
+ table: "posts",
518
+ column: "id",
519
+ ordinalPosition: 1,
520
+ type: "integer",
521
+ default: null,
522
+ nullable: false,
523
+ udtSchema: "pg_catalog",
524
+ udt: "int4",
525
+ elementType: null,
526
+ elementTypeSchema: null,
527
+ cardinality: 0,
528
+ size: null,
529
+ isSerial: false,
530
+ },
531
+ {
532
+ schema: "public",
533
+ table: "posts",
534
+ column: "author_id",
535
+ ordinalPosition: 2,
536
+ type: "integer",
537
+ default: null,
538
+ nullable: false,
539
+ udtSchema: "pg_catalog",
540
+ udt: "int4",
541
+ elementType: null,
542
+ elementTypeSchema: null,
543
+ cardinality: 0,
544
+ size: null,
545
+ isSerial: false,
546
+ },
547
+ {
548
+ schema: "public",
549
+ table: "posts",
550
+ column: "editor_id",
551
+ ordinalPosition: 3,
552
+ type: "integer",
553
+ default: null,
554
+ nullable: true,
555
+ udtSchema: "pg_catalog",
556
+ udt: "int4",
557
+ elementType: null,
558
+ elementTypeSchema: null,
559
+ cardinality: 0,
560
+ size: null,
561
+ isSerial: false,
562
+ },
563
+ {
564
+ schema: "public",
565
+ table: "posts",
566
+ column: "category_id",
567
+ ordinalPosition: 4,
568
+ type: "integer",
569
+ default: null,
570
+ nullable: false,
571
+ udtSchema: "pg_catalog",
572
+ udt: "int4",
573
+ elementType: null,
574
+ elementTypeSchema: null,
575
+ cardinality: 0,
576
+ size: null,
577
+ isSerial: false,
578
+ },
579
+ ],
580
+ foreignKeys: [
581
+ {
582
+ schema: "public",
583
+ constraintName: "posts_author_id_fkey",
584
+ tableFrom: "posts",
585
+ columnsFrom: ["author_id"],
586
+ tableTo: "users",
587
+ columnsTo: ["id"],
588
+ },
589
+ {
590
+ schema: "public",
591
+ constraintName: "posts_editor_id_fkey",
592
+ tableFrom: "posts",
593
+ columnsFrom: ["editor_id"],
594
+ tableTo: "users",
595
+ columnsTo: ["id"],
596
+ },
597
+ {
598
+ schema: "public",
599
+ constraintName: "posts_category_id_fkey",
600
+ tableFrom: "posts",
601
+ columnsFrom: ["category_id"],
602
+ tableTo: "categories",
603
+ columnsTo: ["id"],
604
+ },
605
+ ],
606
+ primaryKey: null,
607
+ uniqueConstraints: [],
608
+ };
609
+ const result = await renderModel(table, []);
610
+ expect(result.trim()).toBe(unindent `
611
+ import { type ModelDefinition } from "@casekit/orm2";
612
+
613
+ export const posts = {
614
+ fields: {
615
+ id: { type: "integer" },
616
+ authorId: {
617
+ column: "author_id",
618
+ type: "integer",
619
+ references: { model: "users", field: "id" },
620
+ },
621
+ editorId: {
622
+ column: "editor_id",
623
+ type: "integer",
624
+ nullable: true,
625
+ references: { model: "users", field: "id" },
626
+ },
627
+ categoryId: {
628
+ column: "category_id",
629
+ type: "integer",
630
+ references: { model: "categories", field: "id" },
631
+ },
632
+ },
633
+ relations: {
634
+ author: {
635
+ type: "N:1",
636
+ model: "users",
637
+ fromField: "authorId",
638
+ toField: "id",
639
+ },
640
+ editor: {
641
+ type: "N:1",
642
+ model: "users",
643
+ fromField: "editorId",
644
+ toField: "id",
645
+ optional: true,
646
+ },
647
+ category: {
648
+ type: "N:1",
649
+ model: "categories",
650
+ fromField: "categoryId",
651
+ toField: "id",
652
+ },
653
+ },
654
+ } as const satisfies ModelDefinition;
655
+ `);
656
+ });
657
+ it("generates 1:N relations for multiple incoming foreign keys", async () => {
658
+ const table = {
659
+ schema: "public",
660
+ name: "users",
661
+ columns: [
662
+ {
663
+ schema: "public",
664
+ table: "users",
665
+ column: "id",
666
+ ordinalPosition: 1,
667
+ type: "integer",
668
+ default: null,
669
+ nullable: false,
670
+ udtSchema: "pg_catalog",
671
+ udt: "int4",
672
+ elementType: null,
673
+ elementTypeSchema: null,
674
+ cardinality: 0,
675
+ size: null,
676
+ isSerial: false,
677
+ },
678
+ ],
679
+ foreignKeys: [],
680
+ primaryKey: null,
681
+ uniqueConstraints: [],
682
+ };
683
+ const allTables = [
684
+ table,
685
+ {
686
+ schema: "public",
687
+ name: "posts",
688
+ columns: [
689
+ {
690
+ schema: "public",
691
+ table: "posts",
692
+ column: "author_id",
693
+ ordinalPosition: 1,
694
+ type: "integer",
695
+ default: null,
696
+ nullable: false,
697
+ udtSchema: "pg_catalog",
698
+ udt: "int4",
699
+ elementType: null,
700
+ elementTypeSchema: null,
701
+ cardinality: 0,
702
+ size: null,
703
+ isSerial: false,
704
+ },
705
+ {
706
+ schema: "public",
707
+ table: "posts",
708
+ column: "editor_id",
709
+ ordinalPosition: 2,
710
+ type: "integer",
711
+ default: null,
712
+ nullable: true,
713
+ udtSchema: "pg_catalog",
714
+ udt: "int4",
715
+ elementType: null,
716
+ elementTypeSchema: null,
717
+ cardinality: 0,
718
+ size: null,
719
+ isSerial: false,
720
+ },
721
+ ],
722
+ foreignKeys: [
723
+ {
724
+ schema: "public",
725
+ constraintName: "posts_author_id_fkey",
726
+ tableFrom: "posts",
727
+ columnsFrom: ["author_id"],
728
+ tableTo: "users",
729
+ columnsTo: ["id"],
730
+ },
731
+ {
732
+ schema: "public",
733
+ constraintName: "posts_editor_id_fkey",
734
+ tableFrom: "posts",
735
+ columnsFrom: ["editor_id"],
736
+ tableTo: "users",
737
+ columnsTo: ["id"],
738
+ },
739
+ ],
740
+ primaryKey: null,
741
+ uniqueConstraints: [],
742
+ },
743
+ {
744
+ schema: "public",
745
+ name: "comments",
746
+ columns: [
747
+ {
748
+ schema: "public",
749
+ table: "comments",
750
+ column: "author_id",
751
+ ordinalPosition: 1,
752
+ type: "integer",
753
+ default: null,
754
+ nullable: false,
755
+ udtSchema: "pg_catalog",
756
+ udt: "int4",
757
+ elementType: null,
758
+ elementTypeSchema: null,
759
+ cardinality: 0,
760
+ size: null,
761
+ isSerial: false,
762
+ },
763
+ ],
764
+ foreignKeys: [
765
+ {
766
+ schema: "public",
767
+ constraintName: "comments_author_id_fkey",
768
+ tableFrom: "comments",
769
+ columnsFrom: ["author_id"],
770
+ tableTo: "users",
771
+ columnsTo: ["id"],
772
+ },
773
+ ],
774
+ primaryKey: null,
775
+ uniqueConstraints: [],
776
+ },
777
+ ];
778
+ const result = await renderModel(table, allTables);
779
+ expect(result.trim()).toBe(unindent `
780
+ import { type ModelDefinition } from "@casekit/orm2";
781
+
782
+ export const users = {
783
+ fields: {
784
+ id: { type: "integer" },
785
+ },
786
+ relations: {
787
+ authorPosts: {
788
+ type: "1:N",
789
+ model: "posts",
790
+ fromField: "id",
791
+ toField: "authorId",
792
+ },
793
+ editorPosts: {
794
+ type: "1:N",
795
+ model: "posts",
796
+ fromField: "id",
797
+ toField: "editorId",
798
+ },
799
+ authorComments: {
800
+ type: "1:N",
801
+ model: "comments",
802
+ fromField: "id",
803
+ toField: "authorId",
804
+ },
805
+ },
806
+ } as const satisfies ModelDefinition;
807
+ `);
808
+ });
809
+ it("handles tables with no relations", async () => {
810
+ const table = {
811
+ schema: "public",
812
+ name: "settings",
813
+ columns: [
814
+ {
815
+ schema: "public",
816
+ table: "settings",
817
+ column: "id",
818
+ ordinalPosition: 1,
819
+ type: "integer",
820
+ default: null,
821
+ nullable: false,
822
+ udtSchema: "pg_catalog",
823
+ udt: "int4",
824
+ elementType: null,
825
+ elementTypeSchema: null,
826
+ cardinality: 0,
827
+ size: null,
828
+ isSerial: false,
829
+ },
830
+ {
831
+ schema: "public",
832
+ table: "settings",
833
+ column: "key",
834
+ ordinalPosition: 2,
835
+ type: "text",
836
+ default: null,
837
+ nullable: false,
838
+ udtSchema: "pg_catalog",
839
+ udt: "text",
840
+ elementType: null,
841
+ elementTypeSchema: null,
842
+ cardinality: 0,
843
+ size: null,
844
+ isSerial: false,
845
+ },
846
+ {
847
+ schema: "public",
848
+ table: "settings",
849
+ column: "value",
850
+ ordinalPosition: 3,
851
+ type: "text",
852
+ default: null,
853
+ nullable: false,
854
+ udtSchema: "pg_catalog",
855
+ udt: "text",
856
+ elementType: null,
857
+ elementTypeSchema: null,
858
+ cardinality: 0,
859
+ size: null,
860
+ isSerial: false,
861
+ },
862
+ ],
863
+ foreignKeys: [],
864
+ primaryKey: null,
865
+ uniqueConstraints: [],
866
+ };
867
+ const result = await renderModel(table, []);
868
+ expect(result.trim()).toBe(unindent `
869
+ import { type ModelDefinition } from "@casekit/orm2";
870
+
871
+ export const settings = {
872
+ fields: {
873
+ id: { type: "integer" },
874
+ key: { type: "text" },
875
+ value: { type: "text" },
876
+ },
877
+ } as const satisfies ModelDefinition;
878
+ `);
879
+ });
880
+ });