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