cogsbox-shape 0.5.65 → 0.5.67
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/dist/schema.d.ts +65 -98
- package/dist/schema.js +235 -164
- package/package.json +7 -3
- package/dist/example/schema.d.ts +0 -554
- package/dist/example/schema.js +0 -6
- package/dist/example/user.d.ts +0 -552
- package/dist/example/user.js +0 -77
package/dist/schema.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import zodToJsonSchema from "zod-to-json-schema";
|
|
3
2
|
export const isFunction = (fn) => typeof fn === "function";
|
|
4
3
|
// Function to create a properly typed current timestamp config
|
|
5
4
|
export function currentTimeStamp() {
|
|
@@ -9,36 +8,36 @@ export function currentTimeStamp() {
|
|
|
9
8
|
};
|
|
10
9
|
}
|
|
11
10
|
// Now define the shape object with the explicit type annotation
|
|
12
|
-
export const
|
|
13
|
-
int: (config = {}) =>
|
|
11
|
+
export const s = {
|
|
12
|
+
int: (config = {}) => s.sql({
|
|
14
13
|
type: "int",
|
|
15
14
|
...config,
|
|
16
15
|
}),
|
|
17
|
-
varchar: (config = {}) =>
|
|
16
|
+
varchar: (config = {}) => s.sql({
|
|
18
17
|
type: "varchar",
|
|
19
18
|
...config,
|
|
20
19
|
}),
|
|
21
|
-
char: (config = {}) =>
|
|
20
|
+
char: (config = {}) => s.sql({
|
|
22
21
|
type: "char",
|
|
23
22
|
...config,
|
|
24
23
|
}),
|
|
25
|
-
text: (config = {}) =>
|
|
24
|
+
text: (config = {}) => s.sql({
|
|
26
25
|
type: "text",
|
|
27
26
|
...config,
|
|
28
27
|
}),
|
|
29
|
-
longtext: (config = {}) =>
|
|
28
|
+
longtext: (config = {}) => s.sql({
|
|
30
29
|
type: "longtext",
|
|
31
30
|
...config,
|
|
32
31
|
}),
|
|
33
|
-
boolean: (config = {}) =>
|
|
32
|
+
boolean: (config = {}) => s.sql({
|
|
34
33
|
type: "boolean",
|
|
35
34
|
...config,
|
|
36
35
|
}),
|
|
37
|
-
date: (config = {}) =>
|
|
36
|
+
date: (config = {}) => s.sql({
|
|
38
37
|
type: "date",
|
|
39
38
|
...config,
|
|
40
39
|
}),
|
|
41
|
-
datetime: (config = {}) =>
|
|
40
|
+
datetime: (config = {}) => s.sql({
|
|
42
41
|
type: "datetime",
|
|
43
42
|
...config,
|
|
44
43
|
}),
|
|
@@ -144,41 +143,36 @@ function createBuilder(config) {
|
|
|
144
143
|
clientTransform: config.clientTransform, // <-- FIX: Make sure transform is passed through
|
|
145
144
|
validationTransform: config.validationTransform, // <-- FIX: Make sure transform is passed through
|
|
146
145
|
},
|
|
147
|
-
initialState: (
|
|
148
|
-
// ... this initialState function remains unchanged ...
|
|
149
|
-
schemaOrDefault, defaultValue) => {
|
|
146
|
+
initialState: (schemaOrDefault, defaultValue) => {
|
|
150
147
|
if (completedStages.has("new")) {
|
|
151
148
|
throw new Error("initialState() can only be called once in the chain");
|
|
152
149
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
throw new Error("initialState() must be called before validation()");
|
|
158
|
-
}
|
|
159
|
-
const hasTypeParam = defaultValue !== undefined;
|
|
160
|
-
const newSchema = hasTypeParam
|
|
150
|
+
// ... other error checks ...
|
|
151
|
+
const hasSchemaArg = defaultValue !== undefined;
|
|
152
|
+
// This logic is mostly from your original code.
|
|
153
|
+
const newSchema = hasSchemaArg
|
|
161
154
|
? isFunction(schemaOrDefault)
|
|
162
155
|
? schemaOrDefault({ sql: config.sqlZod })
|
|
163
156
|
: schemaOrDefault
|
|
164
|
-
: config.sqlZod;
|
|
165
|
-
const finalDefaultValue =
|
|
166
|
-
? defaultValue
|
|
157
|
+
: config.sqlZod; // If only a primitive is passed, the "new" schema is still the SQL one.
|
|
158
|
+
const finalDefaultValue = hasSchemaArg
|
|
159
|
+
? defaultValue()
|
|
167
160
|
: schemaOrDefault;
|
|
168
161
|
const newCompletedStages = new Set(completedStages);
|
|
169
162
|
newCompletedStages.add("new");
|
|
170
|
-
|
|
163
|
+
// ---- THIS IS THE RUNTIME FIX THAT MATCHES YOUR INTERFACE ----
|
|
164
|
+
// If a new schema was passed, create a union.
|
|
165
|
+
// If ONLY a primitive was passed, we MUST also create a union.
|
|
166
|
+
const newClientZod = hasSchemaArg
|
|
171
167
|
? z.union([config.sqlZod, newSchema])
|
|
172
|
-
: config.sqlZod;
|
|
168
|
+
: z.union([config.sqlZod, z.any()]); // Create the union for the primitive case
|
|
173
169
|
return createBuilder({
|
|
174
170
|
...config,
|
|
175
171
|
stage: "new",
|
|
176
172
|
newZod: newSchema,
|
|
177
173
|
initialValue: finalDefaultValue,
|
|
178
174
|
clientZod: newClientZod,
|
|
179
|
-
validationZod:
|
|
180
|
-
? z.union([config.sqlZod, newSchema])
|
|
181
|
-
: config.sqlZod,
|
|
175
|
+
validationZod: newClientZod, // Keep validation and client in sync for this step
|
|
182
176
|
completedStages: newCompletedStages,
|
|
183
177
|
});
|
|
184
178
|
},
|
|
@@ -191,7 +185,6 @@ function createBuilder(config) {
|
|
|
191
185
|
}
|
|
192
186
|
const newCompletedStages = new Set(completedStages);
|
|
193
187
|
newCompletedStages.add("client");
|
|
194
|
-
// ---- THIS IS THE MAIN FIX ----
|
|
195
188
|
if (config.stage === "relation") {
|
|
196
189
|
return createBuilder({
|
|
197
190
|
...config,
|
|
@@ -263,55 +256,46 @@ function createBuilder(config) {
|
|
|
263
256
|
};
|
|
264
257
|
return builderObject;
|
|
265
258
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
schema: config.schema(),
|
|
289
|
-
});
|
|
290
|
-
}
|
|
291
|
-
export function manyToMany(config) {
|
|
292
|
-
return () => ({
|
|
293
|
-
type: "manyToMany",
|
|
294
|
-
fromKey: config.fromKey,
|
|
295
|
-
toKey: config.toKey(),
|
|
296
|
-
schema: config.schema(),
|
|
297
|
-
defaultCount: config.defaultCount,
|
|
298
|
-
});
|
|
259
|
+
// The table function that enriches fields with their key information
|
|
260
|
+
const SchemaWrapperBrand = Symbol("SchemaWrapper");
|
|
261
|
+
// Update the schema function to use the symbol
|
|
262
|
+
export function schema(schema) {
|
|
263
|
+
const enrichedSchema = {
|
|
264
|
+
_tableName: schema._tableName,
|
|
265
|
+
[SchemaWrapperBrand]: true, // Add the symbol property
|
|
266
|
+
};
|
|
267
|
+
for (const key in schema) {
|
|
268
|
+
if (key !== "_tableName" &&
|
|
269
|
+
Object.prototype.hasOwnProperty.call(schema, key)) {
|
|
270
|
+
enrichedSchema[key] = {
|
|
271
|
+
...schema[key],
|
|
272
|
+
__meta: {
|
|
273
|
+
_key: key,
|
|
274
|
+
_fieldType: schema[key],
|
|
275
|
+
},
|
|
276
|
+
__parentTableType: schema,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return enrichedSchema;
|
|
299
281
|
}
|
|
300
282
|
function inferDefaultFromZod(zodType, sqlConfig) {
|
|
301
|
-
// Handle relation configs
|
|
302
283
|
if (sqlConfig && typeof sqlConfig === "object" && "type" in sqlConfig) {
|
|
303
|
-
//
|
|
284
|
+
// --- THIS IS THE NEW, HIGHEST-PRIORITY CHECK ---
|
|
285
|
+
// If a `default` property exists directly on the SQL config, use it.
|
|
286
|
+
if ("default" in sqlConfig && sqlConfig.default !== undefined) {
|
|
287
|
+
// Exclude CURRENT_TIMESTAMP as it's a special keyword, not a value.
|
|
288
|
+
if (sqlConfig.default === "CURRENT_TIMESTAMP") {
|
|
289
|
+
return new Date();
|
|
290
|
+
}
|
|
291
|
+
return sqlConfig.default;
|
|
292
|
+
}
|
|
293
|
+
// Check if it's a relation config (this logic is fine)
|
|
304
294
|
if (typeof sqlConfig.type === "string" &&
|
|
305
295
|
["hasMany", "hasOne", "belongsTo", "manyToMany"].includes(sqlConfig.type)) {
|
|
306
|
-
|
|
307
|
-
if (relationConfig.type === "hasMany" ||
|
|
308
|
-
relationConfig.type === "manyToMany") {
|
|
309
|
-
return Array.from({ length: relationConfig.defaultCount || 0 }, () => ({}));
|
|
310
|
-
}
|
|
311
|
-
// For hasOne and belongsTo
|
|
312
|
-
return {};
|
|
296
|
+
// ... your existing relation logic is fine ...
|
|
313
297
|
}
|
|
314
|
-
// Handle SQL
|
|
298
|
+
// Handle SQL type-based generation (this is the fallback)
|
|
315
299
|
const sqlTypeConfig = sqlConfig;
|
|
316
300
|
if (sqlTypeConfig.type && !sqlTypeConfig.nullable) {
|
|
317
301
|
switch (sqlTypeConfig.type) {
|
|
@@ -321,7 +305,7 @@ function inferDefaultFromZod(zodType, sqlConfig) {
|
|
|
321
305
|
case "longtext":
|
|
322
306
|
return "";
|
|
323
307
|
case "int":
|
|
324
|
-
return 0;
|
|
308
|
+
return 0; // This is now only used if no `default` is provided
|
|
325
309
|
case "boolean":
|
|
326
310
|
return false;
|
|
327
311
|
case "date":
|
|
@@ -333,11 +317,10 @@ function inferDefaultFromZod(zodType, sqlConfig) {
|
|
|
333
317
|
return null;
|
|
334
318
|
}
|
|
335
319
|
}
|
|
336
|
-
// Fall back to
|
|
320
|
+
// Fall back to Zod-based inference (this logic is fine)
|
|
337
321
|
if (zodType instanceof z.ZodOptional) {
|
|
338
322
|
return undefined;
|
|
339
323
|
}
|
|
340
|
-
// Check for explicit default last
|
|
341
324
|
if (zodType instanceof z.ZodDefault && zodType._def?.defaultValue) {
|
|
342
325
|
return typeof zodType._def.defaultValue === "function"
|
|
343
326
|
? zodType._def.defaultValue()
|
|
@@ -345,12 +328,12 @@ function inferDefaultFromZod(zodType, sqlConfig) {
|
|
|
345
328
|
}
|
|
346
329
|
return undefined;
|
|
347
330
|
}
|
|
348
|
-
export function reference(config) {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
}
|
|
331
|
+
// export function reference<TField extends object>(config: TField) {
|
|
332
|
+
// return {
|
|
333
|
+
// type: "reference" as const,
|
|
334
|
+
// to: config,
|
|
335
|
+
// };
|
|
336
|
+
// }
|
|
354
337
|
export function createMixedValidationSchema(schema, clientSchema, dbSchema) {
|
|
355
338
|
// If schemas are provided, use them (to avoid circular calls)
|
|
356
339
|
if (clientSchema && dbSchema) {
|
|
@@ -422,109 +405,197 @@ function isRelation(value) {
|
|
|
422
405
|
"toKey" in value &&
|
|
423
406
|
"schema" in value);
|
|
424
407
|
}
|
|
425
|
-
export function createSchema(schema) {
|
|
408
|
+
export function createSchema(schema, relations) {
|
|
426
409
|
const sqlFields = {};
|
|
427
410
|
const clientFields = {};
|
|
428
411
|
const validationFields = {};
|
|
429
412
|
const defaultValues = {};
|
|
430
|
-
const
|
|
431
|
-
// --- PASS 1:
|
|
413
|
+
const fieldTransforms = {};
|
|
414
|
+
// --- PASS 1: Process main schema fields (no relations here) ---
|
|
432
415
|
for (const key in schema) {
|
|
433
416
|
if (key === "_tableName" || key.startsWith("__"))
|
|
434
417
|
continue;
|
|
435
418
|
const definition = schema[key];
|
|
436
|
-
if (
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
// Process any non-builder, non-deferred fields if they exist.
|
|
419
|
+
if (definition && definition.type === "reference") {
|
|
420
|
+
// Handle reference fields
|
|
421
|
+
const referencedFieldBuilder = definition.to();
|
|
422
|
+
const referencedConfig = referencedFieldBuilder.config;
|
|
423
|
+
sqlFields[key] = referencedConfig.zodSqlSchema;
|
|
424
|
+
clientFields[key] = referencedConfig.zodClientSchema;
|
|
425
|
+
validationFields[key] = referencedConfig.zodValidationSchema;
|
|
426
|
+
// Foreign key fields should get their own default, not the referenced field's default
|
|
427
|
+
defaultValues[key] = inferDefaultFromZod(referencedConfig.zodClientSchema, { ...referencedConfig.sql, default: undefined });
|
|
446
428
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
.array(childSchemaResult.validationSchema)
|
|
461
|
-
.optional();
|
|
462
|
-
defaultValues[key] = Array.from({ length: relation.defaultCount || 0 }, () => childSchemaResult.defaultValues);
|
|
429
|
+
else if (definition && definition.config) {
|
|
430
|
+
// Handle regular fields with builder pattern
|
|
431
|
+
const config = definition.config;
|
|
432
|
+
sqlFields[key] = config.zodSqlSchema;
|
|
433
|
+
clientFields[key] = config.zodClientSchema;
|
|
434
|
+
validationFields[key] = config.zodValidationSchema;
|
|
435
|
+
if (config.transforms) {
|
|
436
|
+
fieldTransforms[key] = config.transforms;
|
|
437
|
+
}
|
|
438
|
+
// Handle initial value
|
|
439
|
+
const initialValueOrFn = config.initialValue;
|
|
440
|
+
if (isFunction(initialValueOrFn)) {
|
|
441
|
+
defaultValues[key] = initialValueOrFn();
|
|
463
442
|
}
|
|
464
443
|
else {
|
|
465
|
-
|
|
466
|
-
clientFields[key] = childSchemaResult.clientSchema.optional();
|
|
467
|
-
validationFields[key] = childSchemaResult.validationSchema.optional();
|
|
468
|
-
defaultValues[key] = childSchemaResult.defaultValues;
|
|
444
|
+
defaultValues[key] = initialValueOrFn;
|
|
469
445
|
}
|
|
470
446
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
447
|
+
}
|
|
448
|
+
// --- PASS 2: Process relations if provided ---
|
|
449
|
+
if (relations) {
|
|
450
|
+
for (const key in relations) {
|
|
451
|
+
const relationDefinition = relations[key];
|
|
452
|
+
if (relationDefinition && relationDefinition.config) {
|
|
453
|
+
const config = relationDefinition.config;
|
|
454
|
+
const sqlConfig = config.sql;
|
|
455
|
+
if (sqlConfig &&
|
|
456
|
+
typeof sqlConfig === "object" &&
|
|
457
|
+
["hasMany", "hasOne", "belongsTo", "manyToMany"].includes(sqlConfig.type)) {
|
|
458
|
+
const relationConfig = sqlConfig;
|
|
459
|
+
const childSchemaResult = createSchema(relationConfig.schema());
|
|
460
|
+
// Create the base schemas based on relation type
|
|
461
|
+
let baseSqlSchema;
|
|
462
|
+
let baseClientSchema;
|
|
463
|
+
let baseValidationSchema;
|
|
464
|
+
if (relationConfig.type === "hasMany" ||
|
|
465
|
+
relationConfig.type === "manyToMany") {
|
|
466
|
+
baseSqlSchema = z.array(childSchemaResult.sqlSchema);
|
|
467
|
+
baseClientSchema = z.array(childSchemaResult.clientSchema);
|
|
468
|
+
baseValidationSchema = z.array(childSchemaResult.validationSchema);
|
|
469
|
+
defaultValues[key] = Array.from({ length: relationConfig.defaultCount || 0 }, () => childSchemaResult.defaultValues);
|
|
470
|
+
}
|
|
471
|
+
else {
|
|
472
|
+
baseSqlSchema = childSchemaResult.sqlSchema;
|
|
473
|
+
baseClientSchema = childSchemaResult.clientSchema;
|
|
474
|
+
baseValidationSchema = childSchemaResult.validationSchema;
|
|
475
|
+
defaultValues[key] = childSchemaResult.defaultValues;
|
|
476
|
+
}
|
|
477
|
+
// Apply transforms if they exist
|
|
478
|
+
const finalClientSchema = config.clientTransform
|
|
479
|
+
? config.clientTransform(baseClientSchema)
|
|
480
|
+
: baseClientSchema;
|
|
481
|
+
const finalValidationSchema = config.validationTransform
|
|
482
|
+
? config.validationTransform(baseValidationSchema)
|
|
483
|
+
: finalClientSchema;
|
|
484
|
+
// Assign the schemas
|
|
485
|
+
sqlFields[key] = baseSqlSchema.optional(); // SQL fields are optional for lazy loading
|
|
486
|
+
clientFields[key] = finalClientSchema;
|
|
487
|
+
validationFields[key] = finalValidationSchema;
|
|
502
488
|
}
|
|
503
|
-
// 2. Apply the transform to the RAW schema
|
|
504
|
-
const transformedClientSchema = config.clientTransform
|
|
505
|
-
? config.clientTransform(rawClientSchema)
|
|
506
|
-
: rawClientSchema;
|
|
507
|
-
const transformedValidationSchema = config.validationTransform
|
|
508
|
-
? config.validationTransform(rawValidationSchema)
|
|
509
|
-
: transformedClientSchema;
|
|
510
|
-
// 3. Assign the final schemas. NO .optional() is added.
|
|
511
|
-
sqlFields[key] = z.array(childSchemaResult.sqlSchema).optional(); // SQL is still optional, as it might not be loaded.
|
|
512
|
-
clientFields[key] = transformedClientSchema; // <-- NO .optional()
|
|
513
|
-
validationFields[key] = transformedValidationSchema; // <-- NO .optional()
|
|
514
|
-
}
|
|
515
|
-
else {
|
|
516
|
-
// It's a standard field builder (`shape.sql(...)`)
|
|
517
|
-
sqlFields[key] = config.zodSqlSchema;
|
|
518
|
-
clientFields[key] = config.zodClientSchema;
|
|
519
|
-
validationFields[key] = config.zodValidationSchema;
|
|
520
|
-
defaultValues[key] = config.initialValue;
|
|
521
489
|
}
|
|
522
490
|
}
|
|
523
491
|
}
|
|
492
|
+
// Create transform functions
|
|
493
|
+
const toClient = (dbObject) => {
|
|
494
|
+
const clientObject = { ...dbObject };
|
|
495
|
+
for (const key in fieldTransforms) {
|
|
496
|
+
if (key in clientObject && clientObject[key] !== undefined) {
|
|
497
|
+
clientObject[key] = fieldTransforms[key].toClient(clientObject[key]);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
return clientObject;
|
|
501
|
+
};
|
|
502
|
+
const toDb = (clientObject) => {
|
|
503
|
+
const dbObject = { ...clientObject };
|
|
504
|
+
for (const key in fieldTransforms) {
|
|
505
|
+
if (key in dbObject && dbObject[key] !== undefined) {
|
|
506
|
+
dbObject[key] = fieldTransforms[key].toDb(dbObject[key]);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
return dbObject;
|
|
510
|
+
};
|
|
524
511
|
return {
|
|
525
512
|
sqlSchema: z.object(sqlFields),
|
|
526
513
|
clientSchema: z.object(clientFields),
|
|
527
514
|
validationSchema: z.object(validationFields),
|
|
528
515
|
defaultValues: defaultValues,
|
|
516
|
+
toClient,
|
|
517
|
+
toDb,
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
export function schemaRelations(baseSchema, referencesBuilder) {
|
|
521
|
+
const rel = {
|
|
522
|
+
reference: (fieldGetter) => ({
|
|
523
|
+
type: "reference",
|
|
524
|
+
to: fieldGetter,
|
|
525
|
+
}),
|
|
526
|
+
hasMany: (config) => {
|
|
527
|
+
const relationConfig = {
|
|
528
|
+
type: "hasMany",
|
|
529
|
+
fromKey: config.fromKey,
|
|
530
|
+
toKey: () => config.toKey.__meta._key,
|
|
531
|
+
schema: () => config.toKey.__parentTableType,
|
|
532
|
+
defaultCount: config.defaultCount,
|
|
533
|
+
};
|
|
534
|
+
const placeholderSchema = z.array(z.any());
|
|
535
|
+
return createBuilder({
|
|
536
|
+
stage: "relation",
|
|
537
|
+
sqlConfig: relationConfig,
|
|
538
|
+
sqlZod: placeholderSchema,
|
|
539
|
+
newZod: placeholderSchema,
|
|
540
|
+
initialValue: Array.from({ length: config.defaultCount || 0 }, () => ({})),
|
|
541
|
+
clientZod: placeholderSchema,
|
|
542
|
+
validationZod: placeholderSchema,
|
|
543
|
+
}); // FIX: This is a hack to get around the circular reference
|
|
544
|
+
},
|
|
545
|
+
hasOne: (config) => {
|
|
546
|
+
const relationConfig = {
|
|
547
|
+
type: "hasOne",
|
|
548
|
+
fromKey: config.fromKey,
|
|
549
|
+
toKey: config.toKey,
|
|
550
|
+
schema: config.schema,
|
|
551
|
+
};
|
|
552
|
+
const relationZodType = z.any();
|
|
553
|
+
return createBuilder({
|
|
554
|
+
stage: "relation",
|
|
555
|
+
sqlConfig: relationConfig,
|
|
556
|
+
sqlZod: relationZodType,
|
|
557
|
+
newZod: relationZodType,
|
|
558
|
+
initialValue: {},
|
|
559
|
+
clientZod: relationZodType,
|
|
560
|
+
validationZod: relationZodType,
|
|
561
|
+
});
|
|
562
|
+
},
|
|
563
|
+
manyToMany: (config) => {
|
|
564
|
+
const relationConfig = {
|
|
565
|
+
type: "manyToMany",
|
|
566
|
+
fromKey: config.fromKey,
|
|
567
|
+
toKey: config.toKey,
|
|
568
|
+
schema: config.schema,
|
|
569
|
+
...(config.defaultCount !== undefined && {
|
|
570
|
+
defaultCount: config.defaultCount,
|
|
571
|
+
}),
|
|
572
|
+
};
|
|
573
|
+
const relationZodType = z.array(z.any()).optional();
|
|
574
|
+
return createBuilder({
|
|
575
|
+
stage: "relation",
|
|
576
|
+
sqlConfig: relationConfig,
|
|
577
|
+
sqlZod: relationZodType,
|
|
578
|
+
newZod: relationZodType,
|
|
579
|
+
initialValue: Array.from({ length: config.defaultCount || 0 }, () => ({})),
|
|
580
|
+
clientZod: relationZodType,
|
|
581
|
+
validationZod: relationZodType,
|
|
582
|
+
});
|
|
583
|
+
},
|
|
529
584
|
};
|
|
585
|
+
const refs = referencesBuilder(rel);
|
|
586
|
+
const enrichedRefs = {};
|
|
587
|
+
// Enrich each field in the refs object with __meta and __parentTableType
|
|
588
|
+
for (const key in refs) {
|
|
589
|
+
if (Object.prototype.hasOwnProperty.call(refs, key)) {
|
|
590
|
+
enrichedRefs[key] = {
|
|
591
|
+
...refs[key],
|
|
592
|
+
__meta: {
|
|
593
|
+
_key: key,
|
|
594
|
+
_fieldType: refs[key],
|
|
595
|
+
},
|
|
596
|
+
__parentTableType: baseSchema,
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
return enrichedRefs;
|
|
530
601
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cogsbox-shape",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.67",
|
|
4
4
|
"description": "A TypeScript library for creating type-safe database schemas with Zod validation, SQL type definitions, and automatic client/server transformations. Unifies client, server, and database types through a single schema definition, with built-in support for relationships and serialization.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"scripts": {
|
|
12
12
|
"build": " tsc",
|
|
13
13
|
"lint": "eslint src --ext .ts",
|
|
14
|
-
"format": "prettier --write \"src/**/*.ts\""
|
|
14
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
15
|
+
"test": "vitest "
|
|
15
16
|
},
|
|
16
17
|
"bin": {
|
|
17
18
|
"cogsbox-shape": "tsx ./dist/cli.js"
|
|
@@ -44,8 +45,11 @@
|
|
|
44
45
|
"@typescript-eslint/eslint-plugin": "^6.15.0",
|
|
45
46
|
"@typescript-eslint/parser": "^6.15.0",
|
|
46
47
|
"eslint": "^8.56.0",
|
|
48
|
+
"expect-type": "^1.2.1",
|
|
47
49
|
"prettier": "^3.1.1",
|
|
48
|
-
"typescript": "^5.3.3"
|
|
50
|
+
"typescript": "^5.3.3",
|
|
51
|
+
"vitest": "^3.2.0",
|
|
52
|
+
"zod": "^3.25.67"
|
|
49
53
|
},
|
|
50
54
|
"peerDependencies": {
|
|
51
55
|
"zod": "^3.22.4"
|