@casekit/orm2-config 0.0.0-20250322230249

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 (67) hide show
  1. package/build/index.d.ts +11 -0
  2. package/build/index.js +4 -0
  3. package/build/normalize/defaultZodSchema.d.ts +8 -0
  4. package/build/normalize/defaultZodSchema.js +127 -0
  5. package/build/normalize/defaultZodSchema.test.d.ts +1 -0
  6. package/build/normalize/defaultZodSchema.test.js +153 -0
  7. package/build/normalize/getColumns.d.ts +2 -0
  8. package/build/normalize/getColumns.js +8 -0
  9. package/build/normalize/getColumns.test.d.ts +1 -0
  10. package/build/normalize/getColumns.test.js +63 -0
  11. package/build/normalize/normalizeConfig.d.ts +3 -0
  12. package/build/normalize/normalizeConfig.js +20 -0
  13. package/build/normalize/normalizeConfig.test.d.ts +1 -0
  14. package/build/normalize/normalizeConfig.test.js +217 -0
  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/build/normalize/normalizeField.test.js +59 -0
  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/build/normalize/normalizeForeignKeys.test.js +258 -0
  23. package/build/normalize/normalizeModel.d.ts +3 -0
  24. package/build/normalize/normalizeModel.js +18 -0
  25. package/build/normalize/normalizeModel.test.d.ts +1 -0
  26. package/build/normalize/normalizeModel.test.js +227 -0
  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/build/normalize/normalizePrimaryKey.test.js +144 -0
  31. package/build/normalize/normalizeRelations.d.ts +3 -0
  32. package/build/normalize/normalizeRelations.js +58 -0
  33. package/build/normalize/normalizeRelations.test.d.ts +1 -0
  34. package/build/normalize/normalizeRelations.test.js +298 -0
  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/build/normalize/normalizeUniqueConstraints.test.js +241 -0
  39. package/build/normalize/populateField.d.ts +3 -0
  40. package/build/normalize/populateField.js +15 -0
  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/build/normalize/populateModels.js +16 -0
  45. package/build/normalize/populateModels.test.d.ts +1 -0
  46. package/build/normalize/populateModels.test.js +240 -0
  47. package/build/types/NormalizedConfig.d.ts +16 -0
  48. package/build/types/NormalizedConfig.js +1 -0
  49. package/build/types/NormalizedFieldDefinition.d.ts +10 -0
  50. package/build/types/NormalizedFieldDefinition.js +1 -0
  51. package/build/types/NormalizedForeignKeyDefinition.d.ts +14 -0
  52. package/build/types/NormalizedForeignKeyDefinition.js +1 -0
  53. package/build/types/NormalizedModelDefinition.d.ts +15 -0
  54. package/build/types/NormalizedModelDefinition.js +1 -0
  55. package/build/types/NormalizedPrimaryKey.d.ts +4 -0
  56. package/build/types/NormalizedPrimaryKey.js +1 -0
  57. package/build/types/NormalizedRelationDefinition.d.ts +42 -0
  58. package/build/types/NormalizedRelationDefinition.js +1 -0
  59. package/build/types/NormalizedUniqueConstraintDefinition.d.ts +8 -0
  60. package/build/types/NormalizedUniqueConstraintDefinition.js +1 -0
  61. package/build/types/PopulatedFieldDefinition.d.ts +4 -0
  62. package/build/types/PopulatedFieldDefinition.js +1 -0
  63. package/build/types/PopulatedModelDefinition.d.ts +6 -0
  64. package/build/types/PopulatedModelDefinition.js +1 -0
  65. package/build/util.d.ts +6 -0
  66. package/build/util.js +21 -0
  67. package/package.json +54 -0
@@ -0,0 +1,240 @@
1
+ import { snakeCase } from "es-toolkit";
2
+ import { describe, expect, test } from "vitest";
3
+ import { ZodSchema } from "zod";
4
+ import { populateModels } from "./populateModels.js";
5
+ describe("populateModels", () => {
6
+ test("populates basic models with defaults", () => {
7
+ const result = populateModels({
8
+ models: {
9
+ user: {
10
+ fields: {
11
+ id: { type: "serial", primaryKey: true },
12
+ name: { type: "text" },
13
+ },
14
+ },
15
+ },
16
+ });
17
+ expect(result).toEqual({
18
+ user: {
19
+ name: "user",
20
+ schema: "public",
21
+ table: "user",
22
+ primaryKey: null,
23
+ uniqueConstraints: [],
24
+ foreignKeys: [],
25
+ relations: {},
26
+ fields: {
27
+ id: {
28
+ name: "id",
29
+ column: "id",
30
+ type: "serial",
31
+ zodSchema: expect.any(ZodSchema),
32
+ default: null,
33
+ references: null,
34
+ nullable: false,
35
+ unique: false,
36
+ primaryKey: true,
37
+ provided: false,
38
+ },
39
+ name: {
40
+ name: "name",
41
+ column: "name",
42
+ type: "text",
43
+ zodSchema: expect.any(ZodSchema),
44
+ default: null,
45
+ references: null,
46
+ nullable: false,
47
+ unique: false,
48
+ primaryKey: false,
49
+ provided: false,
50
+ },
51
+ },
52
+ },
53
+ });
54
+ });
55
+ test("uses config schema when model schema not provided", () => {
56
+ const result = populateModels({
57
+ schema: "custom",
58
+ models: {
59
+ user: {
60
+ fields: {
61
+ id: { type: "serial", primaryKey: true },
62
+ },
63
+ },
64
+ },
65
+ });
66
+ expect(result["user"].schema).toBe("custom");
67
+ });
68
+ test("model schema overrides config schema", () => {
69
+ const result = populateModels({
70
+ schema: "config_schema",
71
+ models: {
72
+ user: {
73
+ schema: "model_schema",
74
+ fields: {
75
+ id: { type: "serial", primaryKey: true },
76
+ },
77
+ },
78
+ },
79
+ });
80
+ expect(result["user"].schema).toBe("model_schema");
81
+ });
82
+ test("applies table naming function when provided", () => {
83
+ const result = populateModels({
84
+ naming: { table: snakeCase },
85
+ models: {
86
+ userProfile: {
87
+ fields: {
88
+ id: { type: "serial", primaryKey: true },
89
+ },
90
+ },
91
+ },
92
+ });
93
+ expect(result["userProfile"].table).toBe("user_profile");
94
+ });
95
+ test("explicit table name overrides naming function", () => {
96
+ const result = populateModels({
97
+ naming: { table: snakeCase },
98
+ models: {
99
+ userProfile: {
100
+ table: "custom_table",
101
+ fields: {
102
+ id: { type: "serial", primaryKey: true },
103
+ },
104
+ },
105
+ },
106
+ });
107
+ expect(result["userProfile"].table).toBe("custom_table");
108
+ });
109
+ test("uses explicit primary key when provided", () => {
110
+ const result = populateModels({
111
+ models: {
112
+ post: {
113
+ primaryKey: ["authorId", "slug"],
114
+ fields: {
115
+ authorId: { type: "integer" },
116
+ slug: { type: "text" },
117
+ content: { type: "text" },
118
+ },
119
+ },
120
+ },
121
+ });
122
+ expect(result["post"].primaryKey).toEqual(["authorId", "slug"]);
123
+ });
124
+ test("handles unique constraints", () => {
125
+ const result = populateModels({
126
+ models: {
127
+ user: {
128
+ fields: {
129
+ id: { type: "serial", primaryKey: true },
130
+ email: { type: "text" },
131
+ },
132
+ uniqueConstraints: [
133
+ {
134
+ name: "unique_email",
135
+ fields: ["email"],
136
+ },
137
+ ],
138
+ },
139
+ },
140
+ });
141
+ expect(result["user"].uniqueConstraints).toEqual([
142
+ {
143
+ name: "unique_email",
144
+ fields: ["email"],
145
+ },
146
+ ]);
147
+ });
148
+ test("handles foreign keys", () => {
149
+ const result = populateModels({
150
+ models: {
151
+ user: {
152
+ fields: {
153
+ id: { type: "serial", primaryKey: true },
154
+ },
155
+ },
156
+ post: {
157
+ fields: {
158
+ id: { type: "serial", primaryKey: true },
159
+ },
160
+ foreignKeys: [
161
+ {
162
+ fields: ["authorId"],
163
+ references: {
164
+ model: "user",
165
+ fields: ["id"],
166
+ },
167
+ },
168
+ ],
169
+ },
170
+ },
171
+ });
172
+ expect(result["post"].foreignKeys).toEqual([
173
+ {
174
+ fields: ["authorId"],
175
+ references: {
176
+ model: "user",
177
+ fields: ["id"],
178
+ },
179
+ },
180
+ ]);
181
+ });
182
+ test("handles relations", () => {
183
+ const result = populateModels({
184
+ models: {
185
+ user: {
186
+ fields: {
187
+ id: { type: "serial", primaryKey: true },
188
+ },
189
+ relations: {
190
+ posts: {
191
+ type: "1:N",
192
+ model: "post",
193
+ fromField: "id",
194
+ toField: "authorId",
195
+ },
196
+ },
197
+ },
198
+ post: {
199
+ fields: {
200
+ id: { type: "serial", primaryKey: true },
201
+ authorId: { type: "integer" },
202
+ },
203
+ },
204
+ },
205
+ });
206
+ expect(result["user"].relations).toEqual({
207
+ posts: {
208
+ type: "1:N",
209
+ model: "post",
210
+ fromField: "id",
211
+ toField: "authorId",
212
+ },
213
+ });
214
+ });
215
+ test("handles multiple models", () => {
216
+ const result = populateModels({
217
+ models: {
218
+ user: {
219
+ fields: {
220
+ id: { type: "serial", primaryKey: true },
221
+ },
222
+ },
223
+ post: {
224
+ fields: {
225
+ id: { type: "serial", primaryKey: true },
226
+ },
227
+ },
228
+ comment: {
229
+ fields: {
230
+ id: { type: "serial", primaryKey: true },
231
+ },
232
+ },
233
+ },
234
+ });
235
+ expect(Object.keys(result)).toEqual(["user", "post", "comment"]);
236
+ expect(result["user"].name).toBe("user");
237
+ expect(result["post"].name).toBe("post");
238
+ expect(result["comment"].name).toBe("comment");
239
+ });
240
+ });
@@ -0,0 +1,16 @@
1
+ import pg from "pg";
2
+ import { Logger, OperatorDefinitions } from "@casekit/orm2-schema";
3
+ import { NormalizedModelDefinition } from "./NormalizedModelDefinition.js";
4
+ export interface NormalizedConfig {
5
+ readonly schema: string;
6
+ readonly models: Record<string, NormalizedModelDefinition>;
7
+ readonly operators: OperatorDefinitions;
8
+ readonly extensions: readonly string[];
9
+ readonly connection: pg.ConnectionConfig | pg.PoolConfig | pg.PoolOptions | null;
10
+ readonly pool: boolean;
11
+ readonly logger: Logger;
12
+ readonly naming: {
13
+ readonly column: (name: string) => string;
14
+ readonly table: (name: string) => string;
15
+ };
16
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ import { z } from "zod";
2
+ export interface NormalizedFieldDefinition {
3
+ name: string;
4
+ column: string;
5
+ type: string;
6
+ zodSchema: z.ZodType<unknown>;
7
+ nullable: boolean;
8
+ default: unknown;
9
+ provided?: boolean;
10
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,14 @@
1
+ export interface NormalizedForeignKeyDefinition {
2
+ name: string;
3
+ fields: string[];
4
+ columns: string[];
5
+ references: {
6
+ model: string;
7
+ fields: string[];
8
+ schema: string;
9
+ table: string;
10
+ columns: string[];
11
+ };
12
+ onUpdate: "RESTRICT" | "CASCADE" | "SET NULL" | "SET DEFAULT" | null;
13
+ onDelete: "RESTRICT" | "CASCADE" | "SET NULL" | "SET DEFAULT" | null;
14
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,15 @@
1
+ import { NormalizedFieldDefinition } from "./NormalizedFieldDefinition.js";
2
+ import { NormalizedForeignKeyDefinition } from "./NormalizedForeignKeyDefinition.js";
3
+ import { NormalizedPrimaryKey } from "./NormalizedPrimaryKey.js";
4
+ import { NormalizedRelationDefinition } from "./NormalizedRelationDefinition.js";
5
+ import { NormalizedUniqueConstraintDefinition } from "./NormalizedUniqueConstraintDefinition.js";
6
+ export interface NormalizedModelDefinition {
7
+ name: string;
8
+ schema: string;
9
+ table: string;
10
+ primaryKey: NormalizedPrimaryKey[];
11
+ uniqueConstraints: NormalizedUniqueConstraintDefinition[];
12
+ foreignKeys: NormalizedForeignKeyDefinition[];
13
+ relations: Record<string, NormalizedRelationDefinition>;
14
+ fields: Record<string, NormalizedFieldDefinition>;
15
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ export type NormalizedPrimaryKey = {
2
+ field: string;
3
+ column: string;
4
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,42 @@
1
+ export interface NormalizedOneToManyRelationDefinition {
2
+ name: string;
3
+ type: "1:N";
4
+ model: string;
5
+ table: string;
6
+ from: {
7
+ fields: string[];
8
+ columns: string[];
9
+ };
10
+ to: {
11
+ fields: string[];
12
+ columns: string[];
13
+ };
14
+ }
15
+ export interface NormalizedManyToManyRelationDefinition {
16
+ name: string;
17
+ type: "N:N";
18
+ model: string;
19
+ table: string;
20
+ through: {
21
+ model: string;
22
+ table: string;
23
+ fromRelation: string;
24
+ toRelation: string;
25
+ };
26
+ }
27
+ export interface NormalizedManyToOneRelationDefinition {
28
+ name: string;
29
+ type: "N:1";
30
+ model: string;
31
+ table: string;
32
+ optional: boolean;
33
+ from: {
34
+ fields: string[];
35
+ columns: string[];
36
+ };
37
+ to: {
38
+ fields: string[];
39
+ columns: string[];
40
+ };
41
+ }
42
+ export type NormalizedRelationDefinition = NormalizedOneToManyRelationDefinition | NormalizedManyToManyRelationDefinition | NormalizedManyToOneRelationDefinition;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ import { SQLStatement } from "@casekit/sql";
2
+ export interface NormalizedUniqueConstraintDefinition {
3
+ name: string;
4
+ fields: string[];
5
+ columns: string[];
6
+ where: SQLStatement | null;
7
+ nullsNotDistinct?: boolean;
8
+ }
@@ -0,0 +1,4 @@
1
+ import { FieldDefinition } from "@casekit/orm2-schema";
2
+ export type PopulatedFieldDefinition = Required<FieldDefinition> & {
3
+ name: string;
4
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ import { ModelDefinition } from "@casekit/orm2-schema";
2
+ import { PopulatedFieldDefinition } from "./PopulatedFieldDefinition.js";
3
+ export type PopulatedModelDefinition = Required<ModelDefinition> & {
4
+ name: string;
5
+ fields: Record<string, PopulatedFieldDefinition>;
6
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ import { NormalizedFieldDefinition } from "./types/NormalizedFieldDefinition.js";
2
+ import { NormalizedModelDefinition } from "./types/NormalizedModelDefinition.js";
3
+ import { NormalizedRelationDefinition } from "./types/NormalizedRelationDefinition.js";
4
+ export declare const getModel: (models: Record<string, NormalizedModelDefinition>, name: string) => NormalizedModelDefinition;
5
+ export declare const getRelation: (model: NormalizedModelDefinition, name: string) => NormalizedRelationDefinition;
6
+ export declare const getField: (model: NormalizedModelDefinition, name: string) => NormalizedFieldDefinition;
package/build/util.js ADDED
@@ -0,0 +1,21 @@
1
+ export const getModel = (models, name) => {
2
+ const model = models[name];
3
+ if (!model) {
4
+ throw new Error(`Model "${name}" not found in config`);
5
+ }
6
+ return model;
7
+ };
8
+ export const getRelation = (model, name) => {
9
+ const relation = model.relations[name];
10
+ if (!relation) {
11
+ throw new Error(`Relation "${name}" not found in model "${model.name}"`);
12
+ }
13
+ return relation;
14
+ };
15
+ export const getField = (model, name) => {
16
+ const field = model.fields[name];
17
+ if (!field) {
18
+ throw new Error(`Field "${name}" not found in model "${model.name}"`);
19
+ }
20
+ return field;
21
+ };
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@casekit/orm2-config",
3
+ "description": "",
4
+ "version": "0.0.0-20250322230249",
5
+ "author": "",
6
+ "dependencies": {
7
+ "es-toolkit": "^1.33.0",
8
+ "@casekit/orm2-schema": "0.0.0-20250322230249",
9
+ "@casekit/sql": "0.0.0-20250322230249",
10
+ "@casekit/toolbox": "0.0.0-20250322230249"
11
+ },
12
+ "devDependencies": {
13
+ "@trivago/prettier-plugin-sort-imports": "^5.2.2",
14
+ "@types/node": "^22.13.11",
15
+ "@types/pg": "^8.11.11",
16
+ "@types/uuid": "^10.0.0",
17
+ "dotenv": "^16.4.7",
18
+ "prettier": "^3.5.3",
19
+ "ts-essentials": "^10.0.4",
20
+ "typescript": "^5.8.2",
21
+ "typescript-eslint": "^8.27.0",
22
+ "vite-tsconfig-paths": "^5.1.4",
23
+ "vitest": "^3.0.9",
24
+ "@casekit/tsconfig": "0.0.0-20250322230249",
25
+ "@casekit/prettier-config": "0.0.0-20250322230249"
26
+ },
27
+ "exports": {
28
+ ".": "./src/index.js"
29
+ },
30
+ "files": [
31
+ "/build"
32
+ ],
33
+ "imports": {
34
+ "#*": "./build/*"
35
+ },
36
+ "keywords": [],
37
+ "license": "ISC",
38
+ "main": "index.js",
39
+ "peerDependencies": {
40
+ "pg": "^8.13.1",
41
+ "zod": "^3.24.2"
42
+ },
43
+ "prettier": "@casekit/prettier-config",
44
+ "type": "module",
45
+ "scripts": {
46
+ "build": "rm -rf ./build && tsc",
47
+ "format:check": "prettier --check .",
48
+ "format": "prettier --write .",
49
+ "lint": "eslint src --max-warnings 0",
50
+ "test": "vitest --run --typecheck",
51
+ "test:watch": "vitest --typecheck",
52
+ "typecheck": "tsc --noEmit"
53
+ }
54
+ }