@casekit/orm2-config 1.0.0 → 1.0.1

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 (73) hide show
  1. package/{src/index.ts → build/index.d.ts} +1 -7
  2. package/build/index.js +4 -0
  3. package/build/normalize/defaultZodSchema.d.ts +8 -0
  4. package/{src/normalize/defaultZodSchema.ts → build/normalize/defaultZodSchema.js} +28 -20
  5. package/build/normalize/defaultZodSchema.test.d.ts +1 -0
  6. package/{src/normalize/defaultZodSchema.test.ts → build/normalize/defaultZodSchema.test.js} +5 -13
  7. package/build/normalize/getColumns.d.ts +2 -0
  8. package/{src/normalize/getColumns.ts → build/normalize/getColumns.js} +1 -6
  9. package/build/normalize/getColumns.test.d.ts +1 -0
  10. package/{src/normalize/getColumns.test.ts → build/normalize/getColumns.test.js} +4 -17
  11. package/build/normalize/normalizeConfig.d.ts +3 -0
  12. package/{src/normalize/normalizeConfig.ts → build/normalize/normalizeConfig.js} +1 -6
  13. package/build/normalize/normalizeConfig.test.d.ts +1 -0
  14. package/{src/normalize/normalizeConfig.test.ts → build/normalize/normalizeConfig.test.js} +22 -68
  15. package/build/normalize/normalizeField.d.ts +3 -0
  16. package/build/normalize/normalizeField.js +11 -0
  17. package/build/normalize/normalizeField.test.d.ts +1 -0
  18. package/{src/normalize/normalizeField.test.ts → build/normalize/normalizeField.test.js} +3 -8
  19. package/build/normalize/normalizeForeignKeys.d.ts +5 -0
  20. package/build/normalize/normalizeForeignKeys.js +50 -0
  21. package/build/normalize/normalizeForeignKeys.test.d.ts +1 -0
  22. package/{src/normalize/normalizeForeignKeys.test.ts → build/normalize/normalizeForeignKeys.test.js} +7 -26
  23. package/build/normalize/normalizeModel.d.ts +3 -0
  24. package/{src/normalize/normalizeModel.ts → build/normalize/normalizeModel.js} +1 -8
  25. package/build/normalize/normalizeModel.test.d.ts +1 -0
  26. package/{src/normalize/normalizeModel.test.ts → build/normalize/normalizeModel.test.js} +14 -38
  27. package/build/normalize/normalizePrimaryKey.d.ts +3 -0
  28. package/build/normalize/normalizePrimaryKey.js +18 -0
  29. package/build/normalize/normalizePrimaryKey.test.d.ts +1 -0
  30. package/{src/normalize/normalizePrimaryKey.test.ts → build/normalize/normalizePrimaryKey.test.js} +7 -31
  31. package/build/normalize/normalizeRelations.d.ts +3 -0
  32. package/{src/normalize/normalizeRelations.ts → build/normalize/normalizeRelations.js} +12 -34
  33. package/build/normalize/normalizeRelations.test.d.ts +1 -0
  34. package/{src/normalize/normalizeRelations.test.ts → build/normalize/normalizeRelations.test.js} +9 -38
  35. package/build/normalize/normalizeUniqueConstraints.d.ts +5 -0
  36. package/build/normalize/normalizeUniqueConstraints.js +29 -0
  37. package/build/normalize/normalizeUniqueConstraints.test.d.ts +1 -0
  38. package/{src/normalize/normalizeUniqueConstraints.test.ts → build/normalize/normalizeUniqueConstraints.test.js} +15 -46
  39. package/build/normalize/populateField.d.ts +3 -0
  40. package/{src/normalize/populateField.ts → build/normalize/populateField.js} +1 -9
  41. package/build/normalize/populateField.test.d.ts +1 -0
  42. package/build/normalize/populateField.test.js +198 -0
  43. package/build/normalize/populateModels.d.ts +3 -0
  44. package/{src/normalize/populateModels.ts → build/normalize/populateModels.js} +2 -11
  45. package/build/normalize/populateModels.test.d.ts +1 -0
  46. package/{src/normalize/populateModels.test.ts → build/normalize/populateModels.test.js} +11 -32
  47. package/{src/types/NormalizedConfig.ts → build/types/NormalizedConfig.d.ts} +1 -8
  48. package/build/types/NormalizedConfig.js +1 -0
  49. package/{src/types/NormalizedFieldDefinition.ts → build/types/NormalizedFieldDefinition.d.ts} +0 -1
  50. package/build/types/NormalizedFieldDefinition.js +1 -0
  51. package/build/types/NormalizedForeignKeyDefinition.js +1 -0
  52. package/{src/types/NormalizedModelDefinition.ts → build/types/NormalizedModelDefinition.d.ts} +0 -1
  53. package/build/types/NormalizedModelDefinition.js +1 -0
  54. package/build/types/NormalizedPrimaryKey.js +1 -0
  55. package/{src/types/NormalizedRelationDefinition.ts → build/types/NormalizedRelationDefinition.d.ts} +1 -7
  56. package/build/types/NormalizedRelationDefinition.js +1 -0
  57. package/{src/types/NormalizedUniqueConstraintDefinition.ts → build/types/NormalizedUniqueConstraintDefinition.d.ts} +0 -1
  58. package/build/types/NormalizedUniqueConstraintDefinition.js +1 -0
  59. package/{src/types/PopulatedFieldDefinition.ts → build/types/PopulatedFieldDefinition.d.ts} +0 -1
  60. package/build/types/PopulatedFieldDefinition.js +1 -0
  61. package/{src/types/PopulatedModelDefinition.ts → build/types/PopulatedModelDefinition.d.ts} +0 -2
  62. package/build/types/PopulatedModelDefinition.js +1 -0
  63. package/build/util.d.ts +6 -0
  64. package/build/util.js +21 -0
  65. package/package.json +10 -10
  66. package/src/normalize/normalizeField.ts +0 -16
  67. package/src/normalize/normalizeForeignKeys.ts +0 -89
  68. package/src/normalize/normalizePrimaryKey.ts +0 -30
  69. package/src/normalize/normalizeUniqueConstraints.ts +0 -58
  70. package/src/normalize/populateField.test.ts +0 -253
  71. package/src/util.ts +0 -38
  72. /package/{src/types/NormalizedForeignKeyDefinition.ts → build/types/NormalizedForeignKeyDefinition.d.ts} +0 -0
  73. /package/{src/types/NormalizedPrimaryKey.ts → build/types/NormalizedPrimaryKey.d.ts} +0 -0
@@ -1,9 +1,7 @@
1
1
  import { snakeCase } from "es-toolkit";
2
2
  import { describe, expect, test } from "vitest";
3
-
4
3
  import { normalizeForeignKeys } from "./normalizeForeignKeys.js";
5
4
  import { populateModels } from "./populateModels.js";
6
-
7
5
  describe("normalizeForeignKeys", () => {
8
6
  test("normalizes foreign keys defined at the top level", () => {
9
7
  const models = populateModels({
@@ -25,8 +23,7 @@ describe("normalizeForeignKeys", () => {
25
23
  },
26
24
  },
27
25
  });
28
-
29
- expect(normalizeForeignKeys(models, models["post"]!)).toEqual([
26
+ expect(normalizeForeignKeys(models, models["post"])).toEqual([
30
27
  {
31
28
  name: "post_user_id_fkey",
32
29
  fields: ["userId"],
@@ -43,7 +40,6 @@ describe("normalizeForeignKeys", () => {
43
40
  },
44
41
  ]);
45
42
  });
46
-
47
43
  test("normalizes foreign keys defined in foreignKeys array", () => {
48
44
  const models = populateModels({
49
45
  naming: { column: snakeCase },
@@ -70,8 +66,7 @@ describe("normalizeForeignKeys", () => {
70
66
  },
71
67
  },
72
68
  });
73
-
74
- expect(normalizeForeignKeys(models, models["post"]!)).toEqual([
69
+ expect(normalizeForeignKeys(models, models["post"])).toEqual([
75
70
  {
76
71
  name: "post_user_id_fkey",
77
72
  fields: ["userId"],
@@ -88,7 +83,6 @@ describe("normalizeForeignKeys", () => {
88
83
  },
89
84
  ]);
90
85
  });
91
-
92
86
  test("throws error when referenced model doesn't exist", () => {
93
87
  const models = populateModels({
94
88
  naming: { column: snakeCase },
@@ -104,12 +98,8 @@ describe("normalizeForeignKeys", () => {
104
98
  },
105
99
  },
106
100
  });
107
-
108
- expect(() => normalizeForeignKeys(models, models["post"]!)).toThrow(
109
- 'Referenced model "nonexistent" not found in models',
110
- );
101
+ expect(() => normalizeForeignKeys(models, models["post"])).toThrow('Referenced model "nonexistent" not found in models');
111
102
  });
112
-
113
103
  test("respects custom onDelete and onUpdate actions", () => {
114
104
  const models = populateModels({
115
105
  naming: { column: snakeCase },
@@ -135,8 +125,7 @@ describe("normalizeForeignKeys", () => {
135
125
  },
136
126
  },
137
127
  });
138
-
139
- expect(normalizeForeignKeys(models, models["post"]!)).toEqual([
128
+ expect(normalizeForeignKeys(models, models["post"])).toEqual([
140
129
  {
141
130
  name: "post_user_id_fkey",
142
131
  fields: ["userId"],
@@ -153,7 +142,6 @@ describe("normalizeForeignKeys", () => {
153
142
  },
154
143
  ]);
155
144
  });
156
-
157
145
  test("throws error on duplicate foreign keys", () => {
158
146
  const models = populateModels({
159
147
  naming: { column: snakeCase },
@@ -183,12 +171,8 @@ describe("normalizeForeignKeys", () => {
183
171
  },
184
172
  },
185
173
  });
186
-
187
- expect(() => normalizeForeignKeys(models, models["post"]!)).toThrow(
188
- 'Duplicate foreign key defined in model "post"',
189
- );
174
+ expect(() => normalizeForeignKeys(models, models["post"])).toThrow('Duplicate foreign key defined in model "post"');
190
175
  });
191
-
192
176
  test("handles custom foreign key names", () => {
193
177
  const models = populateModels({
194
178
  naming: { column: snakeCase },
@@ -216,8 +200,7 @@ describe("normalizeForeignKeys", () => {
216
200
  },
217
201
  },
218
202
  });
219
-
220
- expect(normalizeForeignKeys(models, models["post"]!)).toEqual([
203
+ expect(normalizeForeignKeys(models, models["post"])).toEqual([
221
204
  {
222
205
  name: "custom_fk_name",
223
206
  fields: ["userId"],
@@ -234,7 +217,6 @@ describe("normalizeForeignKeys", () => {
234
217
  },
235
218
  ]);
236
219
  });
237
-
238
220
  test("handles foreign keys in custom schema", () => {
239
221
  const models = populateModels({
240
222
  naming: { column: snakeCase },
@@ -256,8 +238,7 @@ describe("normalizeForeignKeys", () => {
256
238
  },
257
239
  },
258
240
  });
259
-
260
- expect(normalizeForeignKeys(models, models["post"]!)).toEqual([
241
+ expect(normalizeForeignKeys(models, models["post"])).toEqual([
261
242
  {
262
243
  name: "post_user_id_fkey",
263
244
  fields: ["userId"],
@@ -0,0 +1,3 @@
1
+ import { NormalizedModelDefinition } from "#types/NormalizedModelDefinition.js";
2
+ import { PopulatedModelDefinition } from "#types/PopulatedModelDefinition.js";
3
+ export declare const normalizeModel: (models: Record<string, PopulatedModelDefinition>, model: PopulatedModelDefinition) => NormalizedModelDefinition;
@@ -1,17 +1,10 @@
1
1
  import { mapValues } from "es-toolkit";
2
-
3
- import { NormalizedModelDefinition } from "#types/NormalizedModelDefinition.js";
4
- import { PopulatedModelDefinition } from "#types/PopulatedModelDefinition.js";
5
2
  import { normalizeField } from "./normalizeField.js";
6
3
  import { normalizeForeignKeys } from "./normalizeForeignKeys.js";
7
4
  import { normalizePrimaryKey } from "./normalizePrimaryKey.js";
8
5
  import { normalizeRelations } from "./normalizeRelations.js";
9
6
  import { normalizeUniqueConstraints } from "./normalizeUniqueConstraints.js";
10
-
11
- export const normalizeModel = (
12
- models: Record<string, PopulatedModelDefinition>,
13
- model: PopulatedModelDefinition,
14
- ): NormalizedModelDefinition => {
7
+ export const normalizeModel = (models, model) => {
15
8
  return {
16
9
  name: model.name,
17
10
  schema: model.schema,
@@ -0,0 +1 @@
1
+ export {};
@@ -1,12 +1,9 @@
1
1
  import { snakeCase } from "es-toolkit";
2
2
  import { describe, expect, test } from "vitest";
3
3
  import { ZodType, z } from "zod";
4
-
5
4
  import { sql } from "@casekit/sql";
6
-
7
5
  import { normalizeModel } from "./normalizeModel.js";
8
6
  import { populateModels } from "./populateModels.js";
9
-
10
7
  describe("normalizeModel", () => {
11
8
  test("normalizes complete model definition", () => {
12
9
  const models = populateModels({
@@ -30,7 +27,7 @@ describe("normalizeModel", () => {
30
27
  },
31
28
  createdAt: {
32
29
  type: "timestamp",
33
- default: sql`NOW()`,
30
+ default: sql `NOW()`,
34
31
  provided: true,
35
32
  },
36
33
  },
@@ -66,16 +63,13 @@ describe("normalizeModel", () => {
66
63
  },
67
64
  },
68
65
  });
69
-
70
- const result = normalizeModel(models, models["user"]!);
71
-
66
+ const result = normalizeModel(models, models["user"]);
72
67
  // Test basic model properties
73
68
  expect(result.name).toBe("user");
74
69
  expect(result.schema).toBe("auth");
75
70
  expect(result.table).toBe("user");
76
-
77
71
  // Test fields
78
- expect(result.fields["id"]!).toEqual({
72
+ expect(result.fields["id"]).toEqual({
79
73
  name: "id",
80
74
  column: "id",
81
75
  type: "serial",
@@ -84,8 +78,7 @@ describe("normalizeModel", () => {
84
78
  default: null,
85
79
  provided: false,
86
80
  });
87
-
88
- expect(result.fields["email"]!).toEqual({
81
+ expect(result.fields["email"]).toEqual({
89
82
  name: "email",
90
83
  column: "email",
91
84
  type: "text",
@@ -94,10 +87,8 @@ describe("normalizeModel", () => {
94
87
  default: null,
95
88
  provided: false,
96
89
  });
97
-
98
90
  // Test primary key
99
91
  expect(result.primaryKey).toEqual([{ field: "id", column: "id" }]);
100
-
101
92
  // Test unique constraints
102
93
  expect(result.uniqueConstraints).toEqual([
103
94
  {
@@ -108,9 +99,8 @@ describe("normalizeModel", () => {
108
99
  nullsNotDistinct: false,
109
100
  },
110
101
  ]);
111
-
112
102
  // Test relations
113
- expect(result.relations["posts"]!).toEqual({
103
+ expect(result.relations["posts"]).toEqual({
114
104
  name: "posts",
115
105
  type: "1:N",
116
106
  model: "post",
@@ -124,8 +114,7 @@ describe("normalizeModel", () => {
124
114
  columns: ["author_id"],
125
115
  },
126
116
  });
127
-
128
- expect(result.relations["likedPosts"]!).toEqual({
117
+ expect(result.relations["likedPosts"]).toEqual({
129
118
  name: "likedPosts",
130
119
  type: "N:N",
131
120
  model: "post",
@@ -138,7 +127,6 @@ describe("normalizeModel", () => {
138
127
  },
139
128
  });
140
129
  });
141
-
142
130
  test("normalizes model with column name transformations", () => {
143
131
  const models = populateModels({
144
132
  naming: { column: snakeCase },
@@ -153,16 +141,12 @@ describe("normalizeModel", () => {
153
141
  },
154
142
  },
155
143
  });
156
-
157
- const result = normalizeModel(models, models["userProfile"]!);
158
-
159
- expect(result.fields["firstName"]!.column).toBe("first_name");
160
- expect(result.fields["lastName"]!.column).toBe("last_name");
161
- expect(result.fields["emailAddress"]!.column).toBe("email_address");
162
-
163
- expect(result.uniqueConstraints[0]!.columns).toEqual(["email_address"]);
144
+ const result = normalizeModel(models, models["userProfile"]);
145
+ expect(result.fields["firstName"].column).toBe("first_name");
146
+ expect(result.fields["lastName"].column).toBe("last_name");
147
+ expect(result.fields["emailAddress"].column).toBe("email_address");
148
+ expect(result.uniqueConstraints[0].columns).toEqual(["email_address"]);
164
149
  });
165
-
166
150
  test("normalizes model with custom schema and table names", () => {
167
151
  const models = populateModels({
168
152
  models: {
@@ -175,13 +159,10 @@ describe("normalizeModel", () => {
175
159
  },
176
160
  },
177
161
  });
178
-
179
- const result = normalizeModel(models, models["user"]!);
180
-
162
+ const result = normalizeModel(models, models["user"]);
181
163
  expect(result.schema).toBe("custom_schema");
182
164
  expect(result.table).toBe("custom_table");
183
165
  });
184
-
185
166
  test("normalizes model with composite primary key", () => {
186
167
  const models = populateModels({
187
168
  naming: { column: snakeCase },
@@ -195,15 +176,12 @@ describe("normalizeModel", () => {
195
176
  },
196
177
  },
197
178
  });
198
-
199
- const result = normalizeModel(models, models["orderLine"]!);
200
-
179
+ const result = normalizeModel(models, models["orderLine"]);
201
180
  expect(result.primaryKey).toEqual([
202
181
  { field: "orderId", column: "order_id" },
203
182
  { field: "lineNumber", column: "line_number" },
204
183
  ]);
205
184
  });
206
-
207
185
  test("normalizes model with foreign keys", () => {
208
186
  const models = populateModels({
209
187
  naming: { column: snakeCase },
@@ -228,9 +206,7 @@ describe("normalizeModel", () => {
228
206
  },
229
207
  },
230
208
  });
231
-
232
- const result = normalizeModel(models, models["order"]!);
233
-
209
+ const result = normalizeModel(models, models["order"]);
234
210
  expect(result.foreignKeys).toEqual([
235
211
  {
236
212
  name: "order_customer_id_fkey",
@@ -0,0 +1,3 @@
1
+ import { NormalizedPrimaryKey } from "#types/NormalizedPrimaryKey.js";
2
+ import { PopulatedModelDefinition } from "#types/PopulatedModelDefinition.js";
3
+ export declare const normalizePrimaryKey: (model: PopulatedModelDefinition) => NormalizedPrimaryKey[];
@@ -0,0 +1,18 @@
1
+ export const normalizePrimaryKey = (model) => {
2
+ const fieldLevelPrimaryKey = Object.entries(model.fields)
3
+ .filter(([, field]) => field.primaryKey)
4
+ .map(([name]) => name);
5
+ if (model.primaryKey && fieldLevelPrimaryKey.length > 0) {
6
+ throw new Error(`Model "${model.name}" has primary key fields defined at both the model and field levels.`);
7
+ }
8
+ const fields = model.primaryKey ?? fieldLevelPrimaryKey;
9
+ return fields.map((name) => {
10
+ if (!model.fields[name]) {
11
+ throw new Error(`Primary key field "${name}" does not exist in model "${model.name}".`);
12
+ }
13
+ return {
14
+ field: name,
15
+ column: model.fields[name].column,
16
+ };
17
+ });
18
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,9 +1,7 @@
1
1
  import { snakeCase } from "es-toolkit";
2
2
  import { describe, expect, test } from "vitest";
3
-
4
3
  import { normalizePrimaryKey } from "./normalizePrimaryKey.js";
5
4
  import { populateModels } from "./populateModels.js";
6
-
7
5
  describe("normalizePrimaryKey", () => {
8
6
  test("normalizes field-level primary key", () => {
9
7
  const models = populateModels({
@@ -16,9 +14,7 @@ describe("normalizePrimaryKey", () => {
16
14
  },
17
15
  },
18
16
  });
19
-
20
- const result = normalizePrimaryKey(models["user"]!);
21
-
17
+ const result = normalizePrimaryKey(models["user"]);
22
18
  expect(result).toEqual([
23
19
  {
24
20
  field: "id",
@@ -26,7 +22,6 @@ describe("normalizePrimaryKey", () => {
26
22
  },
27
23
  ]);
28
24
  });
29
-
30
25
  test("normalizes model-level primary key", () => {
31
26
  const models = populateModels({
32
27
  models: {
@@ -40,9 +35,7 @@ describe("normalizePrimaryKey", () => {
40
35
  },
41
36
  },
42
37
  });
43
-
44
- const result = normalizePrimaryKey(models["userRole"]!);
45
-
38
+ const result = normalizePrimaryKey(models["userRole"]);
46
39
  expect(result).toEqual([
47
40
  {
48
41
  field: "userId",
@@ -54,7 +47,6 @@ describe("normalizePrimaryKey", () => {
54
47
  },
55
48
  ]);
56
49
  });
57
-
58
50
  test("throws error when primary key is defined at both levels", () => {
59
51
  const models = populateModels({
60
52
  models: {
@@ -67,12 +59,8 @@ describe("normalizePrimaryKey", () => {
67
59
  },
68
60
  },
69
61
  });
70
-
71
- expect(() => normalizePrimaryKey(models["user"]!)).toThrow(
72
- 'Model "user" has primary key fields defined at both the model and field levels.',
73
- );
62
+ expect(() => normalizePrimaryKey(models["user"])).toThrow('Model "user" has primary key fields defined at both the model and field levels.');
74
63
  });
75
-
76
64
  test("handles column name transformations", () => {
77
65
  const models = populateModels({
78
66
  naming: { column: snakeCase },
@@ -85,9 +73,7 @@ describe("normalizePrimaryKey", () => {
85
73
  },
86
74
  },
87
75
  });
88
-
89
- const result = normalizePrimaryKey(models["user"]!);
90
-
76
+ const result = normalizePrimaryKey(models["user"]);
91
77
  expect(result).toEqual([
92
78
  {
93
79
  field: "userId",
@@ -95,7 +81,6 @@ describe("normalizePrimaryKey", () => {
95
81
  },
96
82
  ]);
97
83
  });
98
-
99
84
  test("handles custom column names", () => {
100
85
  const models = populateModels({
101
86
  models: {
@@ -110,9 +95,7 @@ describe("normalizePrimaryKey", () => {
110
95
  },
111
96
  },
112
97
  });
113
-
114
- const result = normalizePrimaryKey(models["user"]!);
115
-
98
+ const result = normalizePrimaryKey(models["user"]);
116
99
  expect(result).toEqual([
117
100
  {
118
101
  field: "id",
@@ -120,7 +103,6 @@ describe("normalizePrimaryKey", () => {
120
103
  },
121
104
  ]);
122
105
  });
123
-
124
106
  test("throws error for non-existent primary key field in model-level definition", () => {
125
107
  const models = populateModels({
126
108
  models: {
@@ -133,12 +115,8 @@ describe("normalizePrimaryKey", () => {
133
115
  },
134
116
  },
135
117
  });
136
-
137
- expect(() => normalizePrimaryKey(models["user"]!)).toThrow(
138
- 'Primary key field "nonexistent" does not exist in model "user".',
139
- );
118
+ expect(() => normalizePrimaryKey(models["user"])).toThrow('Primary key field "nonexistent" does not exist in model "user".');
140
119
  });
141
-
142
120
  test("handles multiple field-level primary keys", () => {
143
121
  const models = populateModels({
144
122
  models: {
@@ -151,9 +129,7 @@ describe("normalizePrimaryKey", () => {
151
129
  },
152
130
  },
153
131
  });
154
-
155
- const result = normalizePrimaryKey(models["userRole"]!);
156
-
132
+ const result = normalizePrimaryKey(models["userRole"]);
157
133
  expect(result).toEqual([
158
134
  {
159
135
  field: "userId",
@@ -0,0 +1,3 @@
1
+ import { NormalizedRelationDefinition } from "#types/NormalizedRelationDefinition.js";
2
+ import { PopulatedModelDefinition } from "#types/PopulatedModelDefinition.js";
3
+ export declare const normalizeRelations: (models: Record<string, PopulatedModelDefinition>, model: PopulatedModelDefinition) => Record<string, NormalizedRelationDefinition>;
@@ -1,49 +1,25 @@
1
1
  import { mapValues } from "es-toolkit";
2
2
  import { castArray } from "es-toolkit/compat";
3
-
4
- import {
5
- NormalizedManyToManyRelationDefinition,
6
- NormalizedManyToOneRelationDefinition,
7
- NormalizedOneToManyRelationDefinition,
8
- NormalizedRelationDefinition,
9
- } from "#types/NormalizedRelationDefinition.js";
10
- import { PopulatedModelDefinition } from "#types/PopulatedModelDefinition.js";
11
-
12
- const normalizeRelationKeys = (
13
- model: PopulatedModelDefinition,
14
- fields: string | string[],
15
- ) => {
3
+ const normalizeRelationKeys = (model, fields) => {
16
4
  const columns = castArray(fields).map((field) => {
17
5
  if (!model.fields[field]) {
18
- throw new Error(
19
- `Model "${model.name}" has relation with non-existent field "${field}".`,
20
- );
6
+ throw new Error(`Model "${model.name}" has relation with non-existent field "${field}".`);
21
7
  }
22
8
  return model.fields[field].column;
23
9
  });
24
10
  return { fields: castArray(fields), columns };
25
11
  };
26
-
27
- export const normalizeRelations = (
28
- models: Record<string, PopulatedModelDefinition>,
29
- model: PopulatedModelDefinition,
30
- ): Record<string, NormalizedRelationDefinition> => {
12
+ export const normalizeRelations = (models, model) => {
31
13
  return mapValues(model.relations, (relation, name) => {
32
14
  const relatedModel = models[relation.model];
33
15
  if (!relatedModel) {
34
- throw new Error(
35
- `Model "${model.name}" has relation "${name}" that references non-existent model "${relation.model}".`,
36
- );
16
+ throw new Error(`Model "${model.name}" has relation "${name}" that references non-existent model "${relation.model}".`);
37
17
  }
38
-
39
18
  if (relation.type === "N:N") {
40
19
  const joinModel = models[relation.through.model];
41
20
  if (!joinModel) {
42
- throw new Error(
43
- `Model "${model.name}" has relation "${name}" with join model "${relation.through.model}" that does not exist.`,
44
- );
21
+ throw new Error(`Model "${model.name}" has relation "${name}" with join model "${relation.through.model}" that does not exist.`);
45
22
  }
46
-
47
23
  return {
48
24
  name,
49
25
  type: relation.type,
@@ -55,8 +31,9 @@ export const normalizeRelations = (
55
31
  fromRelation: relation.through.fromRelation,
56
32
  toRelation: relation.through.toRelation,
57
33
  },
58
- } satisfies NormalizedManyToManyRelationDefinition;
59
- } else if (relation.type === "1:N") {
34
+ };
35
+ }
36
+ else if (relation.type === "1:N") {
60
37
  return {
61
38
  name,
62
39
  type: relation.type,
@@ -64,8 +41,9 @@ export const normalizeRelations = (
64
41
  table: relatedModel.table,
65
42
  from: normalizeRelationKeys(model, relation.fromField),
66
43
  to: normalizeRelationKeys(relatedModel, relation.toField),
67
- } satisfies NormalizedOneToManyRelationDefinition;
68
- } else {
44
+ };
45
+ }
46
+ else {
69
47
  return {
70
48
  name,
71
49
  type: relation.type,
@@ -74,7 +52,7 @@ export const normalizeRelations = (
74
52
  optional: relation.optional ?? false,
75
53
  from: normalizeRelationKeys(model, relation.fromField),
76
54
  to: normalizeRelationKeys(relatedModel, relation.toField),
77
- } satisfies NormalizedManyToOneRelationDefinition;
55
+ };
78
56
  }
79
57
  });
80
58
  };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,10 +1,7 @@
1
1
  import { snakeCase } from "es-toolkit";
2
2
  import { describe, expect, test } from "vitest";
3
-
4
- import { NormalizedOneToManyRelationDefinition } from "../types/NormalizedRelationDefinition.js";
5
3
  import { normalizeRelations } from "./normalizeRelations.js";
6
4
  import { populateModels } from "./populateModels.js";
7
-
8
5
  describe("normalizeRelations", () => {
9
6
  test("normalizes one-to-many relation", () => {
10
7
  const models = populateModels({
@@ -31,9 +28,7 @@ describe("normalizeRelations", () => {
31
28
  },
32
29
  },
33
30
  });
34
-
35
- const result = normalizeRelations(models, models["user"]!);
36
-
31
+ const result = normalizeRelations(models, models["user"]);
37
32
  expect(result).toEqual({
38
33
  posts: {
39
34
  name: "posts",
@@ -51,7 +46,6 @@ describe("normalizeRelations", () => {
51
46
  },
52
47
  });
53
48
  });
54
-
55
49
  test("normalizes many-to-one relation", () => {
56
50
  const models = populateModels({
57
51
  naming: { column: snakeCase },
@@ -77,9 +71,7 @@ describe("normalizeRelations", () => {
77
71
  },
78
72
  },
79
73
  });
80
-
81
- const result = normalizeRelations(models, models["post"]!);
82
-
74
+ const result = normalizeRelations(models, models["post"]);
83
75
  expect(result).toEqual({
84
76
  author: {
85
77
  name: "author",
@@ -98,7 +90,6 @@ describe("normalizeRelations", () => {
98
90
  },
99
91
  });
100
92
  });
101
-
102
93
  test("normalizes many-to-many relation", () => {
103
94
  const models = populateModels({
104
95
  naming: { column: snakeCase },
@@ -132,9 +123,7 @@ describe("normalizeRelations", () => {
132
123
  },
133
124
  },
134
125
  });
135
-
136
- const result = normalizeRelations(models, models["user"]!);
137
-
126
+ const result = normalizeRelations(models, models["user"]);
138
127
  expect(result).toEqual({
139
128
  likedPosts: {
140
129
  model: "post",
@@ -150,7 +139,6 @@ describe("normalizeRelations", () => {
150
139
  },
151
140
  });
152
141
  });
153
-
154
142
  test("handles composite keys in relations", () => {
155
143
  const models = populateModels({
156
144
  naming: { column: snakeCase },
@@ -179,9 +167,7 @@ describe("normalizeRelations", () => {
179
167
  },
180
168
  },
181
169
  });
182
-
183
- const result = normalizeRelations(models, models["order"]!);
184
-
170
+ const result = normalizeRelations(models, models["order"]);
185
171
  expect(result).toEqual({
186
172
  product: {
187
173
  name: "product",
@@ -200,7 +186,6 @@ describe("normalizeRelations", () => {
200
186
  },
201
187
  });
202
188
  });
203
-
204
189
  test("throws error for non-existent related model", () => {
205
190
  const models = populateModels({
206
191
  models: {
@@ -219,12 +204,8 @@ describe("normalizeRelations", () => {
219
204
  },
220
205
  },
221
206
  });
222
-
223
- expect(() => normalizeRelations(models, models["user"]!)).toThrow(
224
- 'Model "user" has relation "posts" that references non-existent model "nonexistent".',
225
- );
207
+ expect(() => normalizeRelations(models, models["user"])).toThrow('Model "user" has relation "posts" that references non-existent model "nonexistent".');
226
208
  });
227
-
228
209
  test("throws error for non-existent join model", () => {
229
210
  const models = populateModels({
230
211
  models: {
@@ -251,12 +232,8 @@ describe("normalizeRelations", () => {
251
232
  },
252
233
  },
253
234
  });
254
-
255
- expect(() => normalizeRelations(models, models["user"]!)).toThrow(
256
- 'Model "user" has relation "likedPosts" with join model "nonexistent" that does not exist.',
257
- );
235
+ expect(() => normalizeRelations(models, models["user"])).toThrow('Model "user" has relation "likedPosts" with join model "nonexistent" that does not exist.');
258
236
  });
259
-
260
237
  test("throws error for non-existent field in relation", () => {
261
238
  const models = populateModels({
262
239
  models: {
@@ -281,12 +258,8 @@ describe("normalizeRelations", () => {
281
258
  },
282
259
  },
283
260
  });
284
-
285
- expect(() => normalizeRelations(models, models["user"]!)).toThrow(
286
- 'Model "user" has relation with non-existent field "nonexistent".',
287
- );
261
+ expect(() => normalizeRelations(models, models["user"])).toThrow('Model "user" has relation with non-existent field "nonexistent".');
288
262
  });
289
-
290
263
  test("handles custom column names", () => {
291
264
  const models = populateModels({
292
265
  models: {
@@ -317,10 +290,8 @@ describe("normalizeRelations", () => {
317
290
  },
318
291
  },
319
292
  });
320
-
321
- const result = normalizeRelations(models, models["user"]!);
322
-
323
- const posts = result["posts"]! as NormalizedOneToManyRelationDefinition;
293
+ const result = normalizeRelations(models, models["user"]);
294
+ const posts = result["posts"];
324
295
  expect(posts.from.columns).toEqual(["user_identifier"]);
325
296
  expect(posts.to.columns).toEqual(["created_by_user"]);
326
297
  });