cogsbox-shape 0.5.78 → 0.5.79

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.
@@ -1,680 +0,0 @@
1
- import { z } from "zod";
2
- import { v4 as uuidv4 } from "uuid";
3
- import zodToJsonSchema, {} from "zod-to-json-schema";
4
- export const isFunction = (fn) => typeof fn === "function";
5
- // Function to create a properly typed current timestamp config
6
- export function currentTimeStamp() {
7
- return {
8
- default: "CURRENT_TIMESTAMP",
9
- defaultValue: new Date(),
10
- };
11
- }
12
- // Internal type creation helper
13
- const createClient = ({ sqlConfig, inferredDbType, inferredClientType, baseJsonSchema, serverType, }) => {
14
- return (assert, defaultValue) => {
15
- const clientType = isFunction(assert)
16
- ? assert({
17
- zod: inferredClientType,
18
- ...(serverType && { serverType }),
19
- })
20
- : assert || inferredClientType;
21
- // Handle timestamp default
22
- let finalSqlConfig = sqlConfig;
23
- let finalDefaultValue = defaultValue;
24
- if (defaultValue &&
25
- typeof defaultValue === "object" &&
26
- "default" in defaultValue &&
27
- defaultValue.default === "CURRENT_TIMESTAMP") {
28
- finalSqlConfig = {
29
- ...sqlConfig,
30
- default: "CURRENT_TIMESTAMP",
31
- };
32
- finalDefaultValue = defaultValue.defaultValue;
33
- }
34
- const effectiveDbType = serverType || inferredDbType;
35
- const clientJsonSchema = zodToJsonSchema(clientType);
36
- return {
37
- sql: finalSqlConfig,
38
- zodDbSchema: effectiveDbType,
39
- zodClientSchema: clientType,
40
- jsonSchema: serverType ? clientJsonSchema : baseJsonSchema,
41
- defaultValue: finalDefaultValue ??
42
- (serverType
43
- ? inferDefaultFromZod(serverType)
44
- : finalDefaultValue),
45
- transform: (transforms) => ({
46
- sql: finalSqlConfig,
47
- zodDbSchema: effectiveDbType,
48
- zodClientSchema: clientType,
49
- jsonSchema: serverType ? clientJsonSchema : baseJsonSchema,
50
- defaultValue: finalDefaultValue,
51
- toClient: transforms.toClient,
52
- toDb: transforms.toDb,
53
- transforms: {
54
- toClient: transforms.toClient.toString(),
55
- toDb: transforms.toDb.toString(),
56
- },
57
- }),
58
- };
59
- };
60
- };
61
- export function createTransforms(transforms) {
62
- return {
63
- sql: (config) => {
64
- const base = shape.sql(config);
65
- return {
66
- sql: base.sql,
67
- dbType: base.dbType,
68
- zodDbSchema: base.zodDbSchema,
69
- zodClientSchema: base.zodClientSchema,
70
- client: base.client,
71
- db: (dbType) => {
72
- const baseDb = base.db(dbType);
73
- const transformMethods = Object.entries(transforms).reduce((acc, [key, transform]) => ({
74
- ...acc,
75
- [key]: () => ({
76
- sql: config,
77
- zodDbSchema: baseDb.zodDbSchema,
78
- zodClientSchema: z.unknown(),
79
- toClient: transform.toClient,
80
- toDb: transform.toDb,
81
- }),
82
- }), {});
83
- return {
84
- ...baseDb,
85
- client: Object.assign(baseDb.client, transformMethods),
86
- };
87
- },
88
- };
89
- },
90
- };
91
- }
92
- export const shape = {
93
- // Integer fields
94
- int: (config = {}) => shape.sql({
95
- type: "int",
96
- ...config,
97
- }),
98
- // String fields with variants
99
- varchar: (config = {}) => shape.sql({
100
- type: "varchar",
101
- ...config,
102
- }),
103
- char: (config = {}) => shape.sql({
104
- type: "char",
105
- ...config,
106
- }),
107
- text: (config = {}) => shape.sql({
108
- type: "text",
109
- ...config,
110
- }),
111
- longtext: (config = {}) => shape.sql({
112
- type: "longtext",
113
- ...config,
114
- }),
115
- // Boolean fields
116
- boolean: (config = {}) => shape.sql({
117
- type: "boolean",
118
- ...config,
119
- }),
120
- // Date fields
121
- date: (config = {}) => shape.sql({
122
- type: "date",
123
- ...config,
124
- }),
125
- datetime: (config = {}) => shape.sql({
126
- type: "datetime",
127
- ...config,
128
- }),
129
- sql: (sqlConfig) => {
130
- const inferredDbType = (() => {
131
- let baseType;
132
- if (sqlConfig.pk) {
133
- baseType = z.number(); // DB PKs are always numbers
134
- }
135
- else {
136
- switch (sqlConfig.type) {
137
- case "int":
138
- baseType = z.number();
139
- break;
140
- case "varchar":
141
- case "char":
142
- case "text":
143
- case "longtext":
144
- baseType = z.string();
145
- break;
146
- case "boolean":
147
- baseType = z.boolean();
148
- break;
149
- case "date":
150
- case "datetime":
151
- baseType = z.date();
152
- break;
153
- default:
154
- throw new Error(`Unsupported type: ${sqlConfig}`);
155
- }
156
- }
157
- if (sqlConfig.nullable) {
158
- baseType = baseType.nullable();
159
- }
160
- return baseType;
161
- })();
162
- const inferredClientType = (() => {
163
- let baseType;
164
- if (sqlConfig.pk) {
165
- baseType = z.string(); // Client PKs are always strings
166
- }
167
- else {
168
- switch (sqlConfig.type) {
169
- case "int":
170
- baseType = z.number();
171
- break;
172
- case "varchar":
173
- case "char":
174
- case "text":
175
- case "longtext":
176
- baseType = z.string();
177
- break;
178
- case "boolean":
179
- baseType = z.boolean();
180
- break;
181
- case "date":
182
- case "datetime":
183
- if (sqlConfig.default === "CURRENT_TIMESTAMP") {
184
- baseType = z.date().optional();
185
- }
186
- baseType = z.date();
187
- break;
188
- default:
189
- throw new Error(`Unsupported type: ${sqlConfig}`);
190
- }
191
- }
192
- if (sqlConfig.nullable) {
193
- baseType = baseType.nullable();
194
- }
195
- return baseType;
196
- })();
197
- // Create JSON Schema version immediately
198
- const jsonSchema = zodToJsonSchema(inferredDbType);
199
- return {
200
- sql: sqlConfig,
201
- dbType: inferredDbType,
202
- zodDbSchema: inferredDbType,
203
- zodClientSchema: inferredClientType,
204
- jsonSchema,
205
- defaultValue: inferDefaultFromZod(inferredDbType, sqlConfig),
206
- client: createClient({
207
- sqlConfig,
208
- inferredDbType,
209
- inferredClientType,
210
- baseJsonSchema: jsonSchema,
211
- }),
212
- db: (assert) => {
213
- const serverType = isFunction(assert)
214
- ? assert({ zod: inferredDbType })
215
- : assert;
216
- return {
217
- sql: sqlConfig,
218
- dbType: serverType,
219
- zodDbSchema: serverType,
220
- zodClientSchema: inferredClientType,
221
- jsonSchema: zodToJsonSchema(serverType),
222
- defaultValue: inferDefaultFromZod(serverType),
223
- client: createClient({
224
- sqlConfig,
225
- inferredDbType,
226
- inferredClientType,
227
- baseJsonSchema: jsonSchema,
228
- serverType,
229
- }),
230
- };
231
- },
232
- };
233
- },
234
- sql2: (sqlConfig) => {
235
- const sqlZodType = (() => {
236
- let baseType;
237
- if (sqlConfig.pk) {
238
- baseType = z.number();
239
- }
240
- else {
241
- switch (sqlConfig.type) {
242
- case "int":
243
- baseType = z.number();
244
- break;
245
- case "boolean":
246
- baseType = z.boolean();
247
- break;
248
- case "date":
249
- case "datetime":
250
- baseType = z.date();
251
- break;
252
- default:
253
- baseType = z.string();
254
- break;
255
- }
256
- }
257
- if (sqlConfig.nullable) {
258
- baseType = baseType.nullable();
259
- }
260
- return baseType;
261
- })();
262
- // Initialize with sql type for all schemas
263
- return createBuilder({
264
- stage: "sql",
265
- sqlConfig: sqlConfig,
266
- sqlZod: sqlZodType,
267
- newZod: sqlZodType,
268
- initialValue: undefined,
269
- clientZod: sqlZodType,
270
- validationZod: sqlZodType,
271
- });
272
- },
273
- };
274
- function createBuilder(config) {
275
- // Initialize completed stages tracker
276
- const completedStages = config.completedStages || new Set(["sql"]);
277
- const builderObject = {
278
- config: {
279
- sql: config.sqlConfig,
280
- zodSqlSchema: config.sqlZod,
281
- zodNewSchema: config.newZod,
282
- initialValue: config.initialValue ||
283
- inferDefaultFromZod(config.clientZod, config.sqlConfig),
284
- zodClientSchema: config.clientZod,
285
- zodValidationSchema: config.validationZod,
286
- },
287
- initialState: (schemaOrDefault, defaultValue) => {
288
- // Runtime validation
289
- if (completedStages.has("new")) {
290
- throw new Error("initialState() can only be called once in the chain");
291
- }
292
- if (completedStages.has("client")) {
293
- throw new Error("initialState() must be called before client()");
294
- }
295
- if (completedStages.has("validation")) {
296
- throw new Error("initialState() must be called before validation()");
297
- }
298
- // Handle overload - if no second param, first param is the default
299
- const hasTypeParam = defaultValue !== undefined;
300
- const newSchema = hasTypeParam
301
- ? isFunction(schemaOrDefault)
302
- ? schemaOrDefault({ sql: config.sqlZod })
303
- : schemaOrDefault
304
- : config.sqlZod; // Keep SQL type if just setting default
305
- const finalDefaultValue = hasTypeParam
306
- ? defaultValue()
307
- : schemaOrDefault();
308
- const newCompletedStages = new Set(completedStages);
309
- newCompletedStages.add("new");
310
- const newClientZod = hasTypeParam
311
- ? z.union([config.sqlZod, newSchema])
312
- : config.sqlZod;
313
- return createBuilder({
314
- ...config,
315
- stage: "new",
316
- newZod: newSchema,
317
- initialValue: finalDefaultValue,
318
- clientZod: newClientZod,
319
- validationZod: hasTypeParam
320
- ? z.union([config.sqlZod, newSchema])
321
- : config.sqlZod,
322
- completedStages: newCompletedStages,
323
- });
324
- },
325
- client: (assert) => {
326
- // Runtime validation
327
- if (completedStages.has("client")) {
328
- throw new Error("client() can only be called once in the chain");
329
- }
330
- if (completedStages.has("validation")) {
331
- throw new Error("client() must be called before validation()");
332
- }
333
- const clientSchema = isFunction(assert)
334
- ? assert({ sql: config.sqlZod, initialState: config.newZod })
335
- : assert;
336
- const newCompletedStages = new Set(completedStages);
337
- newCompletedStages.add("client");
338
- return createBuilder({
339
- ...config,
340
- stage: "client",
341
- clientZod: clientSchema,
342
- // Always set validation to match client when client is set
343
- validationZod: clientSchema,
344
- completedStages: newCompletedStages,
345
- });
346
- },
347
- validation: (assert) => {
348
- // Runtime validation
349
- if (completedStages.has("validation")) {
350
- throw new Error("validation() can only be called once in the chain");
351
- }
352
- const validationSchema = isFunction(assert)
353
- ? assert({
354
- sql: config.sqlZod,
355
- initialState: config.newZod,
356
- client: config.clientZod,
357
- })
358
- : assert;
359
- const newCompletedStages = new Set(completedStages);
360
- newCompletedStages.add("validation");
361
- return createBuilder({
362
- ...config,
363
- stage: "validation",
364
- validationZod: validationSchema,
365
- completedStages: newCompletedStages,
366
- });
367
- },
368
- transform: (transforms) => {
369
- // Runtime validation
370
- if (!completedStages.has("validation") &&
371
- !completedStages.has("client")) {
372
- throw new Error("transform() requires at least client() or validation() to be called first");
373
- }
374
- return {
375
- config: {
376
- ...builderObject.config,
377
- transforms: {
378
- toClient: transforms.toClient,
379
- toDb: transforms.toDb,
380
- },
381
- },
382
- };
383
- },
384
- };
385
- return builderObject;
386
- }
387
- export function hasMany(config) {
388
- return () => ({
389
- type: "hasMany",
390
- fromKey: config.fromKey,
391
- toKey: config.toKey(),
392
- schema: config.schema(),
393
- defaultCount: config.defaultCount,
394
- });
395
- }
396
- export function hasOne(config) {
397
- return () => ({
398
- type: "hasOne",
399
- fromKey: config.fromKey,
400
- toKey: config.toKey(),
401
- schema: config.schema(),
402
- });
403
- }
404
- export function belongsTo(config) {
405
- return () => ({
406
- type: "belongsTo",
407
- fromKey: config.fromKey,
408
- toKey: config.toKey(),
409
- schema: config.schema(),
410
- });
411
- }
412
- export function manyToMany(config) {
413
- return () => ({
414
- type: "manyToMany",
415
- fromKey: config.fromKey,
416
- toKey: config.toKey(),
417
- schema: config.schema(),
418
- defaultCount: config.defaultCount,
419
- });
420
- }
421
- function isRelation(value) {
422
- return (value &&
423
- typeof value === "object" &&
424
- "type" in value &&
425
- "fromKey" in value &&
426
- "toKey" in value &&
427
- "schema" in value);
428
- }
429
- function inferDefaultFromZod(zodType, sqlConfig) {
430
- if (sqlConfig?.pk) {
431
- return uuidv4();
432
- }
433
- if (zodType instanceof z.ZodOptional) {
434
- return undefined;
435
- }
436
- if (zodType instanceof z.ZodNullable) {
437
- return null;
438
- }
439
- if (zodType instanceof z.ZodArray) {
440
- return [];
441
- }
442
- if (zodType instanceof z.ZodObject) {
443
- return {};
444
- }
445
- if (zodType instanceof z.ZodString) {
446
- return "";
447
- }
448
- if (zodType instanceof z.ZodNumber) {
449
- return 0;
450
- }
451
- if (zodType instanceof z.ZodBoolean) {
452
- return false;
453
- }
454
- // Check for explicit default last
455
- if (zodType instanceof z.ZodDefault && zodType._def?.defaultValue) {
456
- return typeof zodType._def.defaultValue === "function"
457
- ? zodType._def.defaultValue()
458
- : zodType._def.defaultValue;
459
- }
460
- return undefined;
461
- }
462
- export function reference(config) {
463
- return {
464
- ...config.field,
465
- type: "reference",
466
- to: config.to,
467
- };
468
- }
469
- function createSerializableSchema(schema) {
470
- const serializableSchema = {
471
- _tableName: schema._tableName,
472
- __schemaId: crypto.randomUUID(),
473
- _syncKey: schema._syncKey
474
- ? {
475
- toString: schema._syncKey.toString(),
476
- }
477
- : undefined,
478
- };
479
- for (const [key, value] of Object.entries(schema)) {
480
- if (key === "_tableName" || key === "__schemaId")
481
- continue;
482
- if (typeof value === "function") {
483
- const relation = value();
484
- if (!isRelation(relation)) {
485
- throw new Error(`Invalid relation for key ${key}`);
486
- }
487
- // Call the schema function to get the actual schema
488
- const childSchema = createSerializableSchema(relation.schema);
489
- // Get toKey value by calling the function
490
- const toKeyField = relation.toKey.type === "reference"
491
- ? relation.toKey.to()
492
- : relation.toKey;
493
- const serializedToKey = {
494
- sql: toKeyField.sql,
495
- jsonSchema: zodToJsonSchema(toKeyField.zodClientSchema),
496
- defaultValue: toKeyField.defaultValue,
497
- };
498
- serializableSchema[key] = {
499
- type: "relation",
500
- relationType: relation.type,
501
- fromKey: relation.fromKey,
502
- toKey: serializedToKey,
503
- schema: childSchema,
504
- ...(relation.type === "hasMany" && {
505
- defaultCount: relation.defaultCount,
506
- }),
507
- };
508
- }
509
- else {
510
- // Handle regular fields or references (unchanged)
511
- if (value.type === "reference") {
512
- const referencedField = value.to();
513
- const serializedField = {
514
- sql: referencedField.sql,
515
- jsonSchema: zodToJsonSchema(referencedField.zodClientSchema),
516
- defaultValue: referencedField.defaultValue,
517
- ...(referencedField.toClient &&
518
- referencedField.toDb && {
519
- transforms: {
520
- toClient: referencedField.toClient.toString(),
521
- toDb: referencedField.toDb.toString(),
522
- },
523
- }),
524
- };
525
- serializableSchema[key] = serializedField;
526
- }
527
- else {
528
- const serializedField = {
529
- sql: value.sql,
530
- jsonSchema: zodToJsonSchema(value.zodClientSchema),
531
- defaultValue: value.defaultValue,
532
- ...(value.toClient &&
533
- value.toDb && {
534
- transforms: {
535
- toClient: value.toClient.toString(),
536
- toDb: value.toDb.toString(),
537
- },
538
- }),
539
- };
540
- serializableSchema[key] = serializedField;
541
- }
542
- }
543
- }
544
- return serializableSchema;
545
- }
546
- export function createMixedValidationSchema(schema, clientSchema, dbSchema) {
547
- // If schemas are provided, use them (to avoid circular calls)
548
- if (clientSchema && dbSchema) {
549
- const mixedFields = {};
550
- const allKeys = new Set([
551
- ...Object.keys(clientSchema.shape),
552
- ...Object.keys(dbSchema.shape),
553
- ]);
554
- for (const key of allKeys) {
555
- const clientField = clientSchema.shape[key];
556
- const dbField = dbSchema.shape[key];
557
- if (clientField && dbField) {
558
- mixedFields[key] = z.union([clientField, dbField]);
559
- }
560
- else {
561
- mixedFields[key] = clientField || dbField;
562
- }
563
- }
564
- return z.object(mixedFields);
565
- }
566
- // Build schemas manually without calling createSchema
567
- const clientFields = {};
568
- const dbFields = {};
569
- for (const [key, value] of Object.entries(schema)) {
570
- if (key === "_tableName")
571
- continue;
572
- if (typeof value === "function") {
573
- const relation = value();
574
- if (!isRelation(relation))
575
- continue;
576
- // For relations, create mixed schemas recursively
577
- const childMixedSchema = createMixedValidationSchema(relation.schema);
578
- if (relation.type === "hasMany") {
579
- clientFields[key] = z.array(childMixedSchema);
580
- dbFields[key] = z.array(childMixedSchema);
581
- }
582
- else {
583
- clientFields[key] = childMixedSchema;
584
- dbFields[key] = childMixedSchema;
585
- }
586
- continue;
587
- }
588
- clientFields[key] = value.zodClientSchema;
589
- dbFields[key] = value.zodDbSchema;
590
- }
591
- // Now create mixed fields
592
- const mixedFields = {};
593
- const allKeys = new Set([
594
- ...Object.keys(clientFields),
595
- ...Object.keys(dbFields),
596
- ]);
597
- for (const key of allKeys) {
598
- const clientField = clientFields[key];
599
- const dbField = dbFields[key];
600
- if (clientField && dbField) {
601
- mixedFields[key] = z.union([clientField, dbField]);
602
- }
603
- else {
604
- mixedFields[key] = (clientField || dbField);
605
- }
606
- }
607
- return z.object(mixedFields);
608
- }
609
- export function createSchema(schema) {
610
- const serialized = createSerializableSchema(schema);
611
- const dbFields = {};
612
- const clientFields = {};
613
- const defaultValues = {};
614
- // ... existing schema building logic ...
615
- for (const [key, value] of Object.entries(schema)) {
616
- if (key === "_tableName")
617
- continue;
618
- if (typeof value === "function") {
619
- const relation = value();
620
- if (!isRelation(relation)) {
621
- throw new Error(`Invalid relation for key ${key}`);
622
- }
623
- const childSchema = createSchema(relation.schema);
624
- // ... existing relation logic ...
625
- if (relation.type === "hasMany") {
626
- dbFields[key] = z.array(z.object(childSchema.dbSchema.shape));
627
- clientFields[key] = z.array(z.object(childSchema.clientSchema.shape));
628
- const count = relation.defaultCount || 0;
629
- defaultValues[key] = Array.from({ length: count }, () => ({
630
- ...childSchema.defaultValues,
631
- }));
632
- }
633
- else {
634
- dbFields[key] = z.object(childSchema.dbSchema.shape);
635
- clientFields[key] = z.object(childSchema.clientSchema.shape);
636
- defaultValues[key] = childSchema.defaultValues;
637
- }
638
- continue;
639
- }
640
- dbFields[key] = value.zodDbSchema;
641
- clientFields[key] = value.zodClientSchema;
642
- defaultValues[key] =
643
- value.defaultValue ?? inferDefaultFromZod(value.zodClientSchema);
644
- }
645
- const clientSchemaObj = z.object(clientFields);
646
- const dbSchemaObj = z.object(dbFields);
647
- // Pass the built schemas to avoid circular reference
648
- const mixedSchema = createMixedValidationSchema(schema, clientSchemaObj, dbSchemaObj);
649
- return {
650
- dbSchema: dbSchemaObj,
651
- clientSchema: clientSchemaObj,
652
- mixedSchema: mixedSchema,
653
- defaultValues: defaultValues,
654
- initialValues: () => defaultValues,
655
- serialized: serialized,
656
- };
657
- }
658
- export function createSchema2(schema) {
659
- const sqlFields = {};
660
- const clientFields = {};
661
- const validationFields = {};
662
- const defaultValues = {};
663
- for (const key in schema) {
664
- if (key === "_tableName")
665
- continue;
666
- const field = schema[key];
667
- if (field && typeof field === "object" && "config" in field) {
668
- sqlFields[key] = field.config.zodSqlSchema; //field.config' is of type 'unknown
669
- clientFields[key] = field.config.zodClientSchema;
670
- validationFields[key] = field.config.zodValidationSchema;
671
- defaultValues[key] = field.config.initialValue;
672
- }
673
- }
674
- return {
675
- sqlSchema: z.object(sqlFields),
676
- clientSchema: z.object(clientFields),
677
- validationSchema: z.object(validationFields),
678
- defaultValues: defaultValues,
679
- };
680
- }