cogsbox-shape 0.5.192 → 0.5.194
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/README.md +126 -37
- package/cogsbox-shape-db/dist/connect.d.ts +39 -14
- package/cogsbox-shape-db/dist/connect.js +9 -5
- package/cogsbox-shape-db/dist/sqlite/sqlite-driver.d.ts +1 -1
- package/cogsbox-shape-db/dist/table-db.d.ts +10 -2
- package/cogsbox-shape-db/dist/table-db.js +7 -0
- package/cogsbox-shape-db/dist/types.d.ts +11 -6
- package/dist/generateSQL.js +148 -67
- package/dist/schema.d.ts +62 -8
- package/dist/schema.js +115 -42
- package/dist/vitest/fullSchema.test.d.ts +1 -0
- package/dist/vitest/fullSchema.test.js +1367 -0
- package/dist/vitest/generateSQL.test.d.ts +1 -0
- package/dist/vitest/generateSQL.test.js +70 -0
- package/dist/vitest/packageExports.test.d.ts +1 -0
- package/dist/vitest/packageExports.test.js +15 -0
- package/package.json +2 -1
package/dist/schema.js
CHANGED
|
@@ -7,6 +7,48 @@ export function currentTimeStamp() {
|
|
|
7
7
|
defaultValue: new Date(),
|
|
8
8
|
};
|
|
9
9
|
}
|
|
10
|
+
function createSqlBuilder(dialect, sqlConfig) {
|
|
11
|
+
const sqlZodType = (() => {
|
|
12
|
+
let baseType;
|
|
13
|
+
if (sqlConfig.pk) {
|
|
14
|
+
baseType = z.number();
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
switch (sqlConfig.type) {
|
|
18
|
+
case "int":
|
|
19
|
+
baseType = z.number();
|
|
20
|
+
break;
|
|
21
|
+
case "boolean":
|
|
22
|
+
baseType = z.number();
|
|
23
|
+
break;
|
|
24
|
+
case "date":
|
|
25
|
+
case "datetime":
|
|
26
|
+
case "timestamp":
|
|
27
|
+
baseType = z.date();
|
|
28
|
+
break;
|
|
29
|
+
case "enum":
|
|
30
|
+
baseType = z.enum(sqlConfig.values);
|
|
31
|
+
break;
|
|
32
|
+
default:
|
|
33
|
+
baseType = z.string();
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (sqlConfig.nullable) {
|
|
38
|
+
baseType = baseType.nullable();
|
|
39
|
+
}
|
|
40
|
+
return baseType;
|
|
41
|
+
})();
|
|
42
|
+
const dialectConfig = { ...sqlConfig, dialect };
|
|
43
|
+
return createBuilder({
|
|
44
|
+
stage: "sql",
|
|
45
|
+
sqlConfig: dialectConfig,
|
|
46
|
+
sqlZod: sqlZodType,
|
|
47
|
+
initialValue: inferDefaultFromZod(sqlZodType, dialectConfig),
|
|
48
|
+
clientZod: sqlZodType,
|
|
49
|
+
validationZod: sqlZodType,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
10
52
|
export const s = {
|
|
11
53
|
clientInput: (value) => {
|
|
12
54
|
const sample = isFunction(value) ? value({ uuid }) : value;
|
|
@@ -60,44 +102,9 @@ export const s = {
|
|
|
60
102
|
relationType: "manyToMany",
|
|
61
103
|
defaultCount: config?.defaultCount ?? 0,
|
|
62
104
|
}),
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (sqlConfig.pk) {
|
|
67
|
-
baseType = z.number();
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
switch (sqlConfig.type) {
|
|
71
|
-
case "int":
|
|
72
|
-
baseType = z.number();
|
|
73
|
-
break;
|
|
74
|
-
case "boolean":
|
|
75
|
-
baseType = z.number();
|
|
76
|
-
break;
|
|
77
|
-
case "date":
|
|
78
|
-
case "datetime":
|
|
79
|
-
case "timestamp":
|
|
80
|
-
baseType = z.date();
|
|
81
|
-
break;
|
|
82
|
-
default:
|
|
83
|
-
baseType = z.string();
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
if (sqlConfig.nullable) {
|
|
88
|
-
baseType = baseType.nullable();
|
|
89
|
-
}
|
|
90
|
-
return baseType;
|
|
91
|
-
})();
|
|
92
|
-
return createBuilder({
|
|
93
|
-
stage: "sql",
|
|
94
|
-
sqlConfig: sqlConfig,
|
|
95
|
-
sqlZod: sqlZodType,
|
|
96
|
-
initialValue: inferDefaultFromZod(sqlZodType, sqlConfig),
|
|
97
|
-
clientZod: sqlZodType,
|
|
98
|
-
validationZod: sqlZodType,
|
|
99
|
-
});
|
|
100
|
-
},
|
|
105
|
+
sqlite: (sqlConfig) => createSqlBuilder("sqlite", sqlConfig),
|
|
106
|
+
postgres: (sqlConfig) => createSqlBuilder("postgres", sqlConfig),
|
|
107
|
+
mysql: (sqlConfig) => createSqlBuilder("mysql", sqlConfig),
|
|
101
108
|
};
|
|
102
109
|
function createBuilder(config) {
|
|
103
110
|
const completedStages = config.completedStages || new Set([config.stage]);
|
|
@@ -350,6 +357,7 @@ export function schema(schema) {
|
|
|
350
357
|
enrichedSchema[SchemaWrapperBrand] = true;
|
|
351
358
|
enrichedSchema.__primaryKeySQL = undefined;
|
|
352
359
|
enrichedSchema.__derives = undefined;
|
|
360
|
+
enrichedSchema.__refinements = undefined;
|
|
353
361
|
enrichedSchema.primaryKeySQL = function (definer) {
|
|
354
362
|
const pkFieldsOnly = {};
|
|
355
363
|
for (const key in schema) {
|
|
@@ -367,6 +375,10 @@ export function schema(schema) {
|
|
|
367
375
|
enrichedSchema.__derives = derivers;
|
|
368
376
|
return enrichedSchema;
|
|
369
377
|
};
|
|
378
|
+
enrichedSchema.refine = function (refinements) {
|
|
379
|
+
enrichedSchema.__refinements = refinements;
|
|
380
|
+
return enrichedSchema;
|
|
381
|
+
};
|
|
370
382
|
return enrichedSchema;
|
|
371
383
|
}
|
|
372
384
|
function inferDefaultFromZod(zodType, sqlConfig) {
|
|
@@ -387,6 +399,8 @@ function inferDefaultFromZod(zodType, sqlConfig) {
|
|
|
387
399
|
case "char":
|
|
388
400
|
case "longtext":
|
|
389
401
|
return "";
|
|
402
|
+
case "enum":
|
|
403
|
+
return sqlTypeConfig.default ?? sqlTypeConfig.values[0];
|
|
390
404
|
case "int":
|
|
391
405
|
return 0;
|
|
392
406
|
case "boolean":
|
|
@@ -431,6 +445,7 @@ export function createSchema(schema, relations) {
|
|
|
431
445
|
let pkKeys = [];
|
|
432
446
|
let clientPkKeys = [];
|
|
433
447
|
const derives = schema.__derives;
|
|
448
|
+
const refinements = schema.__refinements;
|
|
434
449
|
for (const key in fullSchema) {
|
|
435
450
|
const value = fullSchema[key];
|
|
436
451
|
if (key === "_tableName" ||
|
|
@@ -633,7 +648,7 @@ export function createSchema(schema, relations) {
|
|
|
633
648
|
// 2. Map Database ONLY derives directly to the dbObject
|
|
634
649
|
if (derives?.forDb) {
|
|
635
650
|
for (const schemaKey in derives.forDb) {
|
|
636
|
-
// Resolve custom DB column name if they used s.
|
|
651
|
+
// Resolve custom DB column name if they used s.sqlite({ field: "custom_name" })
|
|
637
652
|
const sqlConfig = fullSchema[schemaKey]?.config?.sql;
|
|
638
653
|
const dbKey = sqlConfig?.field || schemaKey;
|
|
639
654
|
dbObject[dbKey] = derives.forDb[schemaKey]?.(clientObject);
|
|
@@ -669,22 +684,78 @@ export function createSchema(schema, relations) {
|
|
|
669
684
|
};
|
|
670
685
|
trackDeriveDependencies(derives?.forClient);
|
|
671
686
|
trackDeriveDependencies(derives?.forDb);
|
|
687
|
+
const refineDependencies = { server: [], client: [] };
|
|
688
|
+
const trackRefinementDependencies = (fn, key) => {
|
|
689
|
+
if (!fn)
|
|
690
|
+
return;
|
|
691
|
+
const accessed = new Set();
|
|
692
|
+
const trackingRow = new Proxy(defaultValues, {
|
|
693
|
+
get(target, prop, receiver) {
|
|
694
|
+
if (typeof prop === "string") {
|
|
695
|
+
accessed.add(prop);
|
|
696
|
+
}
|
|
697
|
+
return Reflect.get(target, prop, receiver);
|
|
698
|
+
},
|
|
699
|
+
});
|
|
700
|
+
try {
|
|
701
|
+
fn(trackingRow);
|
|
702
|
+
}
|
|
703
|
+
catch (e) { }
|
|
704
|
+
refineDependencies[key] = Array.from(accessed);
|
|
705
|
+
};
|
|
706
|
+
trackRefinementDependencies(refinements?.server, "server");
|
|
707
|
+
trackRefinementDependencies(refinements?.client, "client");
|
|
708
|
+
let refinedValidationSchema = finalValidationSchema;
|
|
709
|
+
if (refinements?.server) {
|
|
710
|
+
const serverRefine = refinements.server;
|
|
711
|
+
refinedValidationSchema = finalValidationSchema.superRefine((data, ctx) => {
|
|
712
|
+
const result = serverRefine(data);
|
|
713
|
+
if (!result)
|
|
714
|
+
return;
|
|
715
|
+
const errors = Array.isArray(result) ? result : [result];
|
|
716
|
+
for (const err of errors) {
|
|
717
|
+
ctx.addIssue({
|
|
718
|
+
code: z.ZodIssueCode.custom,
|
|
719
|
+
message: err.message,
|
|
720
|
+
path: err.path,
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
let refinedClientInputSchema = finalClientInputSchema;
|
|
726
|
+
if (refinements?.client) {
|
|
727
|
+
const clientRefine = refinements.client;
|
|
728
|
+
refinedClientInputSchema = finalClientInputSchema.superRefine((data, ctx) => {
|
|
729
|
+
const result = clientRefine(data);
|
|
730
|
+
if (!result)
|
|
731
|
+
return;
|
|
732
|
+
const errors = Array.isArray(result) ? result : [result];
|
|
733
|
+
for (const err of errors) {
|
|
734
|
+
ctx.addIssue({
|
|
735
|
+
code: z.ZodIssueCode.custom,
|
|
736
|
+
message: err.message,
|
|
737
|
+
path: err.path,
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
});
|
|
741
|
+
}
|
|
672
742
|
return {
|
|
673
743
|
pk: pkKeys.length ? pkKeys : null,
|
|
674
744
|
clientPk: clientPkKeys.length ? clientPkKeys : null,
|
|
675
745
|
deriveDependencies,
|
|
746
|
+
refineDependencies,
|
|
676
747
|
isClientRecord,
|
|
677
748
|
sqlSchema: finalSqlSchema,
|
|
678
|
-
clientInputSchema:
|
|
749
|
+
clientInputSchema: refinedClientInputSchema,
|
|
679
750
|
clientSchema: finalClientSchema,
|
|
680
|
-
serverSchema:
|
|
751
|
+
serverSchema: refinedValidationSchema,
|
|
681
752
|
defaultValues: defaultValues,
|
|
682
753
|
stateType: {},
|
|
683
754
|
generateDefaults,
|
|
684
755
|
toClient,
|
|
685
756
|
toDb,
|
|
686
757
|
parseForDb: (appData) => {
|
|
687
|
-
const validData =
|
|
758
|
+
const validData = refinedValidationSchema.parse(appData);
|
|
688
759
|
return toDb(validData);
|
|
689
760
|
},
|
|
690
761
|
parsePatchForDb: (patchData) => {
|
|
@@ -840,6 +911,7 @@ export function createSchemaBox(schemas, resolutions) {
|
|
|
840
911
|
pk: zodSchemas.pk,
|
|
841
912
|
clientPk: zodSchemas.clientPk,
|
|
842
913
|
deriveDependencies: zodSchemas.deriveDependencies,
|
|
914
|
+
refineDependencies: zodSchemas.refineDependencies,
|
|
843
915
|
isClientRecord: zodSchemas.isClientRecord,
|
|
844
916
|
generateDefaults: zodSchemas.generateDefaults,
|
|
845
917
|
};
|
|
@@ -925,6 +997,7 @@ export function createSchemaBox(schemas, resolutions) {
|
|
|
925
997
|
pk: entry.pk,
|
|
926
998
|
clientPk: entry.clientPk,
|
|
927
999
|
deriveDependencies: entry.deriveDependencies,
|
|
1000
|
+
refineDependencies: entry.refineDependencies,
|
|
928
1001
|
isClientRecord: entry.isClientRecord,
|
|
929
1002
|
nav: createNavProxy(tableName, finalRegistry),
|
|
930
1003
|
createView: (selection) => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|