@casekit/orm2-config 0.0.1 → 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
@@ -6,12 +6,6 @@ export type { NormalizedFieldDefinition } from "./types/NormalizedFieldDefinitio
6
6
  export type { NormalizedForeignKeyDefinition } from "./types/NormalizedForeignKeyDefinition.js";
7
7
  export type { NormalizedModelDefinition } from "./types/NormalizedModelDefinition.js";
8
8
  export type { NormalizedPrimaryKey } from "./types/NormalizedPrimaryKey.js";
9
- export type {
10
- NormalizedManyToManyRelationDefinition,
11
- NormalizedManyToOneRelationDefinition,
12
- NormalizedOneToManyRelationDefinition,
13
- NormalizedRelationDefinition,
14
- } from "./types/NormalizedRelationDefinition.js";
9
+ export type { NormalizedManyToManyRelationDefinition, NormalizedManyToOneRelationDefinition, NormalizedOneToManyRelationDefinition, NormalizedRelationDefinition, } from "./types/NormalizedRelationDefinition.js";
15
10
  export type { NormalizedUniqueConstraintDefinition } from "./types/NormalizedUniqueConstraintDefinition.js";
16
-
17
11
  export { getField, getModel, getRelation } from "./util.js";
package/build/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { normalizeConfig } from "./normalize/normalizeConfig.js";
2
+ export { normalizeModel } from "./normalize/normalizeModel.js";
3
+ export { normalizeUniqueConstraint } from "./normalize/normalizeUniqueConstraints.js";
4
+ export { getField, getModel, getRelation } from "./util.js";
@@ -0,0 +1,8 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * WARNING!!! The schemas in this file must be kept in sync
4
+ * with DefaultFieldType in packages/orm-schema/src/helper/DefaultFieldType.ts.
5
+ * If you make a change here, make sure to update the
6
+ * corresponding type.
7
+ */
8
+ export declare const defaultZodSchema: (type: string) => z.ZodType;
@@ -1,26 +1,37 @@
1
1
  import { z } from "zod";
2
-
3
2
  /**
4
3
  * WARNING!!! The schemas in this file must be kept in sync
5
4
  * with DefaultFieldType in packages/orm-schema/src/helper/DefaultFieldType.ts.
6
5
  * If you make a change here, make sure to update the
7
6
  * corresponding type.
8
7
  */
9
- export const defaultZodSchema = (type: string): z.ZodType => {
8
+ export const defaultZodSchema = (type) => {
10
9
  if (type.endsWith("[]"))
11
10
  return z.array(defaultZodSchema(type.slice(0, -2)));
12
- if (type.startsWith("bit ")) return z.string();
13
- if (type.startsWith("bit(")) return z.string();
14
- if (type.startsWith("character varying")) return z.string();
15
- if (type.startsWith("character")) return z.string();
16
- if (type.startsWith("numeric ")) return z.string();
17
- if (type.startsWith("numeric(")) return z.string();
18
- if (type.startsWith("timestamp ")) return z.date();
19
- if (type.startsWith("timestamp(")) return z.date();
20
- if (type.startsWith("time ")) return z.string();
21
- if (type.startsWith("time(")) return z.string();
22
- if (type.startsWith("varchar ")) return z.string();
23
- if (type.startsWith("varchar(")) return z.string();
11
+ if (type.startsWith("bit "))
12
+ return z.string();
13
+ if (type.startsWith("bit("))
14
+ return z.string();
15
+ if (type.startsWith("character varying"))
16
+ return z.string();
17
+ if (type.startsWith("character"))
18
+ return z.string();
19
+ if (type.startsWith("numeric "))
20
+ return z.string();
21
+ if (type.startsWith("numeric("))
22
+ return z.string();
23
+ if (type.startsWith("timestamp "))
24
+ return z.date();
25
+ if (type.startsWith("timestamp("))
26
+ return z.date();
27
+ if (type.startsWith("time "))
28
+ return z.string();
29
+ if (type.startsWith("time("))
30
+ return z.string();
31
+ if (type.startsWith("varchar "))
32
+ return z.string();
33
+ if (type.startsWith("varchar("))
34
+ return z.string();
24
35
  // if (type.startsWith("interval"))
25
36
  // return z.object({
26
37
  // years: z.number().optional(),
@@ -31,7 +42,6 @@ export const defaultZodSchema = (type: string): z.ZodType => {
31
42
  // seconds: z.number().optional(),
32
43
  // milliseconds: z.number().optional(),
33
44
  // });
34
-
35
45
  switch (type) {
36
46
  case "bigint":
37
47
  case "bigserial":
@@ -110,10 +120,8 @@ export const defaultZodSchema = (type: string): z.ZodType => {
110
120
  case "timestamptz":
111
121
  return z.date();
112
122
  default:
113
- throw new Error(
114
- "Unsupported type: " +
115
- type +
116
- " - please specify a zod schema in the field definition",
117
- );
123
+ throw new Error("Unsupported type: " +
124
+ type +
125
+ " - please specify a zod schema in the field definition");
118
126
  }
119
127
  };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,24 +1,18 @@
1
1
  import pg from "pg";
2
2
  import { afterAll, afterEach, beforeAll, describe, expect, test } from "vitest";
3
-
4
3
  import { defaultZodSchema } from "./defaultZodSchema.js";
5
-
6
4
  describe("defaultZodSchema", () => {
7
- let db: pg.Client;
8
-
5
+ let db;
9
6
  beforeAll(async () => {
10
7
  db = new pg.Client();
11
8
  await db.connect();
12
9
  });
13
-
14
10
  afterEach(async () => {
15
11
  await db.query("ROLLBACK");
16
12
  });
17
-
18
13
  afterAll(async () => {
19
14
  await db.end();
20
15
  });
21
-
22
16
  test.for([
23
17
  ["char", "a", "a"],
24
18
  ["character", "a", "a"],
@@ -141,20 +135,18 @@ describe("defaultZodSchema", () => {
141
135
  ],
142
136
  ],
143
137
  ],
144
- ] as const)("%s columns", async ([datatype, value, expected = value]) => {
138
+ ])("%s columns", async ([datatype, value, expected = value]) => {
145
139
  await db.query("BEGIN TRANSACTION");
146
140
  await db.query(`CREATE TABLE foo (value ${datatype})`);
147
-
148
141
  if (datatype.endsWith("serial")) {
149
142
  await db.query("INSERT INTO foo DEFAULT VALUES");
150
- } else {
143
+ }
144
+ else {
151
145
  await db.query(`INSERT INTO foo (value) VALUES ($1::${datatype})`, [
152
146
  value,
153
147
  ]);
154
148
  }
155
-
156
- const result = await db.query<{ value: unknown }>(`SELECT * FROM foo`);
157
-
149
+ const result = await db.query(`SELECT * FROM foo`);
158
150
  const parsed = defaultZodSchema(datatype).parse(result.rows[0]?.value);
159
151
  expect(parsed).toEqual(expected);
160
152
  });
@@ -0,0 +1,2 @@
1
+ import { PopulatedModelDefinition } from "#types/PopulatedModelDefinition.js";
2
+ export declare const getColumns: (model: PopulatedModelDefinition, fields: string[]) => string[];
@@ -1,9 +1,4 @@
1
- import { PopulatedModelDefinition } from "#types/PopulatedModelDefinition.js";
2
-
3
- export const getColumns = (
4
- model: PopulatedModelDefinition,
5
- fields: string[],
6
- ): string[] => {
1
+ export const getColumns = (model, fields) => {
7
2
  return fields.map((f) => {
8
3
  if (!model.fields[f]) {
9
4
  throw new Error(`Field "${f}" not found in model "${model.name}"`);
@@ -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 { getColumns } from "./getColumns.js";
5
4
  import { populateModels } from "./populateModels.js";
6
-
7
5
  describe("getColumns", () => {
8
6
  test("returns column names for given fields", () => {
9
7
  const models = populateModels({
@@ -18,12 +16,8 @@ describe("getColumns", () => {
18
16
  },
19
17
  },
20
18
  });
21
-
22
- expect(
23
- getColumns(models["user"]!, ["id", "fullName", "emailAddress"]),
24
- ).toEqual(["id", "full_name", "email_address"]);
19
+ expect(getColumns(models["user"], ["id", "fullName", "emailAddress"])).toEqual(["id", "full_name", "email_address"]);
25
20
  });
26
-
27
21
  test("throws error for non-existent field", () => {
28
22
  const models = populateModels({
29
23
  naming: { column: snakeCase },
@@ -35,12 +29,8 @@ describe("getColumns", () => {
35
29
  },
36
30
  },
37
31
  });
38
-
39
- expect(() =>
40
- getColumns(models["user"]!, ["id", "nonexistent"]),
41
- ).toThrow('Field "nonexistent" not found in model "user"');
32
+ expect(() => getColumns(models["user"], ["id", "nonexistent"])).toThrow('Field "nonexistent" not found in model "user"');
42
33
  });
43
-
44
34
  test("returns empty array for empty fields array", () => {
45
35
  const models = populateModels({
46
36
  naming: { column: snakeCase },
@@ -52,10 +42,8 @@ describe("getColumns", () => {
52
42
  },
53
43
  },
54
44
  });
55
-
56
- expect(getColumns(models["user"]!, [])).toEqual([]);
45
+ expect(getColumns(models["user"], [])).toEqual([]);
57
46
  });
58
-
59
47
  test("handles custom column names", () => {
60
48
  const models = populateModels({
61
49
  models: {
@@ -67,8 +55,7 @@ describe("getColumns", () => {
67
55
  },
68
56
  },
69
57
  });
70
-
71
- expect(getColumns(models["user"]!, ["id", "name"])).toEqual([
58
+ expect(getColumns(models["user"], ["id", "name"])).toEqual([
72
59
  "id",
73
60
  "user_full_name",
74
61
  ]);
@@ -0,0 +1,3 @@
1
+ import { Config } from "@casekit/orm2-schema";
2
+ import { NormalizedConfig } from "#types/NormalizedConfig.js";
3
+ export declare const normalizeConfig: (config: Config) => NormalizedConfig;
@@ -1,12 +1,7 @@
1
1
  import { identity, mapValues } from "es-toolkit";
2
-
3
- import { Config } from "@casekit/orm2-schema";
4
-
5
- import { NormalizedConfig } from "#types/NormalizedConfig.js";
6
2
  import { normalizeModel } from "./normalizeModel.js";
7
3
  import { populateModels } from "./populateModels.js";
8
-
9
- export const normalizeConfig = (config: Config): NormalizedConfig => {
4
+ export const normalizeConfig = (config) => {
10
5
  const models = populateModels(config);
11
6
  return {
12
7
  ...config,
@@ -0,0 +1 @@
1
+ export {};
@@ -1,11 +1,8 @@
1
1
  import { snakeCase } from "es-toolkit";
2
2
  import { describe, expect, test } from "vitest";
3
3
  import { z } from "zod";
4
-
5
4
  import { sql } from "@casekit/sql";
6
-
7
5
  import { normalizeConfig } from "./normalizeConfig.js";
8
-
9
6
  describe("normalizeConfig", () => {
10
7
  test("normalizes minimal config with defaults", () => {
11
8
  const config = {
@@ -17,10 +14,8 @@ describe("normalizeConfig", () => {
17
14
  },
18
15
  },
19
16
  },
20
- } as const;
21
-
17
+ };
22
18
  const result = normalizeConfig(config);
23
-
24
19
  expect(result.schema).toBe("public");
25
20
  expect(result.operators).toEqual({ where: {} });
26
21
  expect(result.extensions).toEqual([]);
@@ -29,12 +24,10 @@ describe("normalizeConfig", () => {
29
24
  expect(result.logger).toBe(console);
30
25
  expect(typeof result.naming.column).toBe("function");
31
26
  expect(typeof result.naming.table).toBe("function");
32
-
33
27
  // Test that default identity functions don't transform names
34
28
  expect(result.naming.column("userName")).toBe("userName");
35
29
  expect(result.naming.table("UserProfile")).toBe("UserProfile");
36
30
  });
37
-
38
31
  test("preserves provided config values", () => {
39
32
  const customLogger = {
40
33
  debug: () => {
@@ -50,9 +43,7 @@ describe("normalizeConfig", () => {
50
43
  /* empty */
51
44
  },
52
45
  };
53
-
54
46
  const $contains = Symbol("contains");
55
-
56
47
  const config = {
57
48
  schema: "custom",
58
49
  models: {
@@ -64,7 +55,7 @@ describe("normalizeConfig", () => {
64
55
  },
65
56
  operators: {
66
57
  where: {
67
- [$contains]: () => sql``,
58
+ [$contains]: () => sql ``,
68
59
  },
69
60
  },
70
61
  extensions: ["uuid-ossp"],
@@ -78,10 +69,8 @@ describe("normalizeConfig", () => {
78
69
  column: snakeCase,
79
70
  table: snakeCase,
80
71
  },
81
- } as const;
82
-
72
+ };
83
73
  const result = normalizeConfig(config);
84
-
85
74
  expect(result.schema).toBe("custom");
86
75
  expect(result.operators).toBe(config.operators);
87
76
  expect(result.extensions).toEqual(["uuid-ossp"]);
@@ -91,7 +80,6 @@ describe("normalizeConfig", () => {
91
80
  expect(result.naming.column).toBe(snakeCase);
92
81
  expect(result.naming.table).toBe(snakeCase);
93
82
  });
94
-
95
83
  test("normalizes models with relationships", () => {
96
84
  const config = {
97
85
  models: {
@@ -102,7 +90,7 @@ describe("normalizeConfig", () => {
102
90
  },
103
91
  relations: {
104
92
  posts: {
105
- type: "1:N" as const,
93
+ type: "1:N",
106
94
  model: "post",
107
95
  fromField: "id",
108
96
  toField: "authorId",
@@ -116,11 +104,9 @@ describe("normalizeConfig", () => {
116
104
  },
117
105
  },
118
106
  },
119
- } as const;
120
-
107
+ };
121
108
  const result = normalizeConfig(config);
122
-
123
- expect(result.models["user"]!.relations["posts"]!).toEqual({
109
+ expect(result.models["user"].relations["posts"]).toEqual({
124
110
  name: "posts",
125
111
  type: "1:N",
126
112
  model: "post",
@@ -135,7 +121,6 @@ describe("normalizeConfig", () => {
135
121
  },
136
122
  });
137
123
  });
138
-
139
124
  test("applies naming functions to all models", () => {
140
125
  const config = {
141
126
  naming: {
@@ -158,37 +143,20 @@ describe("normalizeConfig", () => {
158
143
  },
159
144
  },
160
145
  },
161
- } as const;
162
-
146
+ };
163
147
  const result = normalizeConfig(config);
164
-
165
148
  // Check table names
166
- expect(result.models["userProfile"]!.table).toBe("user_profile");
167
- expect(result.models["orderItem"]!.table).toBe("order_item");
168
-
149
+ expect(result.models["userProfile"].table).toBe("user_profile");
150
+ expect(result.models["orderItem"].table).toBe("order_item");
169
151
  // Check column names in first model
170
- expect(result.models["userProfile"]!.fields["userId"]!.column).toBe(
171
- "user_id",
172
- );
173
- expect(result.models["userProfile"]!.fields["firstName"]!.column).toBe(
174
- "first_name",
175
- );
176
- expect(result.models["userProfile"]!.fields["lastName"]!.column).toBe(
177
- "last_name",
178
- );
179
-
152
+ expect(result.models["userProfile"].fields["userId"].column).toBe("user_id");
153
+ expect(result.models["userProfile"].fields["firstName"].column).toBe("first_name");
154
+ expect(result.models["userProfile"].fields["lastName"].column).toBe("last_name");
180
155
  // Check column names in second model
181
- expect(result.models["orderItem"]!.fields["orderId"]!.column).toBe(
182
- "order_id",
183
- );
184
- expect(result.models["orderItem"]!.fields["productId"]!.column).toBe(
185
- "product_id",
186
- );
187
- expect(result.models["orderItem"]!.fields["unitPrice"]!.column).toBe(
188
- "unit_price",
189
- );
156
+ expect(result.models["orderItem"].fields["orderId"].column).toBe("order_id");
157
+ expect(result.models["orderItem"].fields["productId"].column).toBe("product_id");
158
+ expect(result.models["orderItem"].fields["unitPrice"].column).toBe("unit_price");
190
159
  });
191
-
192
160
  test("normalizes custom Zod schemas in models", () => {
193
161
  const config = {
194
162
  models: {
@@ -206,19 +174,12 @@ describe("normalizeConfig", () => {
206
174
  },
207
175
  },
208
176
  },
209
- } as const;
210
-
177
+ };
211
178
  const result = normalizeConfig(config);
212
-
213
179
  // Verify that Zod schemas are preserved
214
- expect(
215
- result.models["user"]!.fields["email"]!.zodSchema,
216
- ).toBeInstanceOf(z.ZodEmail);
217
- expect(result.models["user"]!.fields["age"]!.zodSchema).toBeInstanceOf(
218
- z.ZodNumber,
219
- );
180
+ expect(result.models["user"].fields["email"].zodSchema).toBeInstanceOf(z.ZodEmail);
181
+ expect(result.models["user"].fields["age"].zodSchema).toBeInstanceOf(z.ZodNumber);
220
182
  });
221
-
222
183
  test("handles partial naming configuration", () => {
223
184
  const config = {
224
185
  naming: {
@@ -232,18 +193,13 @@ describe("normalizeConfig", () => {
232
193
  },
233
194
  },
234
195
  },
235
- } as const;
236
-
196
+ };
237
197
  const result = normalizeConfig(config);
238
-
239
198
  // Column should be transformed
240
- expect(result.models["userProfile"]!.fields["userId"]!.column).toBe(
241
- "user_id",
242
- );
199
+ expect(result.models["userProfile"].fields["userId"].column).toBe("user_id");
243
200
  // Table should remain unchanged due to default identity function
244
- expect(result.models["userProfile"]!.table).toBe("userProfile");
201
+ expect(result.models["userProfile"].table).toBe("userProfile");
245
202
  });
246
-
247
203
  test("handles empty extensions array", () => {
248
204
  const config = {
249
205
  models: {
@@ -254,10 +210,8 @@ describe("normalizeConfig", () => {
254
210
  },
255
211
  },
256
212
  extensions: [],
257
- } as const;
258
-
213
+ };
259
214
  const result = normalizeConfig(config);
260
-
261
215
  expect(result.extensions).toEqual([]);
262
216
  });
263
217
  });
@@ -0,0 +1,3 @@
1
+ import { NormalizedFieldDefinition } from "#types/NormalizedFieldDefinition.js";
2
+ import { PopulatedFieldDefinition } from "#types/PopulatedFieldDefinition.js";
3
+ export declare const normalizeField: (field: PopulatedFieldDefinition) => NormalizedFieldDefinition;
@@ -0,0 +1,11 @@
1
+ export const normalizeField = (field) => {
2
+ return {
3
+ name: field.name,
4
+ column: field.column,
5
+ type: field.type,
6
+ zodSchema: field.zodSchema,
7
+ nullable: field.nullable,
8
+ default: field.default,
9
+ provided: field.provided,
10
+ };
11
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,10 +1,8 @@
1
1
  import { snakeCase } from "es-toolkit";
2
2
  import { describe, expect, test } from "vitest";
3
3
  import { ZodType } from "zod";
4
-
5
4
  import { normalizeField } from "./normalizeField.js";
6
5
  import { populateModels } from "./populateModels.js";
7
-
8
6
  describe("normalizeField", () => {
9
7
  test("strips out references, unique, and primary key properties", () => {
10
8
  const models = populateModels({
@@ -30,8 +28,7 @@ describe("normalizeField", () => {
30
28
  },
31
29
  },
32
30
  });
33
-
34
- expect(normalizeField(models["post"]!.fields["id"]!)).toEqual({
31
+ expect(normalizeField(models["post"].fields["id"])).toEqual({
35
32
  name: "id",
36
33
  column: "id",
37
34
  type: "serial",
@@ -40,8 +37,7 @@ describe("normalizeField", () => {
40
37
  default: null,
41
38
  provided: false,
42
39
  });
43
-
44
- expect(normalizeField(models["post"]!.fields["slug"]!)).toEqual({
40
+ expect(normalizeField(models["post"].fields["slug"])).toEqual({
45
41
  name: "slug",
46
42
  column: "slug",
47
43
  type: "text",
@@ -50,8 +46,7 @@ describe("normalizeField", () => {
50
46
  default: null,
51
47
  provided: false,
52
48
  });
53
-
54
- expect(normalizeField(models["post"]!.fields["authorId"]!)).toEqual({
49
+ expect(normalizeField(models["post"].fields["authorId"])).toEqual({
55
50
  name: "authorId",
56
51
  column: "author_id",
57
52
  type: "integer",
@@ -0,0 +1,5 @@
1
+ import { ForeignKeyDefinition } from "@casekit/orm2-schema";
2
+ import { NormalizedForeignKeyDefinition } from "#types/NormalizedForeignKeyDefinition.js";
3
+ import { PopulatedModelDefinition } from "#types/PopulatedModelDefinition.js";
4
+ export declare const normalizeForeignKeys: (models: Record<string, PopulatedModelDefinition>, model: PopulatedModelDefinition) => NormalizedForeignKeyDefinition[];
5
+ export declare const normalizeForeignKey: (models: Record<string, PopulatedModelDefinition>, model: PopulatedModelDefinition, fk: ForeignKeyDefinition) => NormalizedForeignKeyDefinition;
@@ -0,0 +1,50 @@
1
+ import { isEqual } from "es-toolkit";
2
+ import { getColumns } from "./getColumns.js";
3
+ export const normalizeForeignKeys = (models, model) => {
4
+ const columnLevelForeignKeys = Object.values(model.fields)
5
+ .filter(hasReference)
6
+ .map(referenceToForeignKey)
7
+ .map((fk) => normalizeForeignKey(models, model, fk));
8
+ const modelLevelForeignKeys = model.foreignKeys.map((fk) => normalizeForeignKey(models, model, fk));
9
+ for (const fk of columnLevelForeignKeys) {
10
+ if (modelLevelForeignKeys.some((other) => isEqual(fk.columns, other.columns))) {
11
+ throw new Error(`Duplicate foreign key defined in model "${model.name}"`);
12
+ }
13
+ }
14
+ return [...columnLevelForeignKeys, ...modelLevelForeignKeys];
15
+ };
16
+ export const normalizeForeignKey = (models, model, fk) => {
17
+ const referencedModel = models[fk.references.model];
18
+ if (!referencedModel) {
19
+ throw new Error(`Referenced model "${fk.references.model}" not found in models`);
20
+ }
21
+ const columns = getColumns(model, fk.fields);
22
+ return {
23
+ name: fk.name ?? [model.table, ...columns, "fkey"].join("_"),
24
+ fields: fk.fields,
25
+ columns: columns,
26
+ references: {
27
+ model: fk.references.model,
28
+ fields: fk.references.fields,
29
+ schema: referencedModel.schema,
30
+ table: referencedModel.table,
31
+ columns: getColumns(referencedModel, fk.references.fields),
32
+ },
33
+ onUpdate: fk.onUpdate ?? null,
34
+ onDelete: fk.onDelete ?? null,
35
+ };
36
+ };
37
+ const referenceToForeignKey = (field) => {
38
+ return {
39
+ fields: [field.name],
40
+ references: {
41
+ model: field.references.model,
42
+ fields: [field.references.field],
43
+ },
44
+ onUpdate: field.references.onUpdate,
45
+ onDelete: field.references.onDelete,
46
+ };
47
+ };
48
+ const hasReference = (field) => {
49
+ return !!field.references;
50
+ };
@@ -0,0 +1 @@
1
+ export {};