cogsbox-shape 0.5.85 → 0.5.87

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 CHANGED
@@ -45,11 +45,11 @@ export interface IBuilderMethods<T extends SQLType | RelationConfig<any>, TSql e
45
45
  }) => TNewNext) | TNewNext, defaultValue: TDefaultNext): Prettify<Builder<"new", T, TSql, z.ZodUnion<[
46
46
  TNewNext,
47
47
  z.ZodLiteral<TDefaultNext extends () => infer R ? R : TDefaultNext>
48
- ]>, IsLiteralType<z.infer<TNewNext>> extends true ? TDefaultNext extends () => infer R ? R : TDefaultNext : z.infer<TNewNext>, z.ZodUnion<[
48
+ ]>, IsLiteralType<z.infer<TNewNext>> extends true ? TDefaultNext extends () => infer R ? R : TDefaultNext : z.infer<TNewNext>, (TDefaultNext extends () => infer R ? R : TDefaultNext) extends z.infer<TNewNext> ? z.ZodUnion<[TSql, TNewNext]> : z.ZodUnion<[
49
49
  TSql,
50
50
  TNewNext,
51
51
  z.ZodLiteral<TDefaultNext extends () => infer R ? R : TDefaultNext>
52
- ]>, z.ZodUnion<[
52
+ ]>, (TDefaultNext extends () => infer R ? R : TDefaultNext) extends z.infer<TNewNext> ? z.ZodUnion<[TSql, TNewNext]> : z.ZodUnion<[
53
53
  TSql,
54
54
  TNewNext,
55
55
  z.ZodLiteral<TDefaultNext extends () => infer R ? R : TDefaultNext>
@@ -150,9 +150,9 @@ export type EnrichFields<T extends ShapeSchema> = {
150
150
  [K in keyof T]: K extends string ? EnrichedField<K, T[K], T> : T[K];
151
151
  };
152
152
  export declare const SchemaWrapperBrand: unique symbol;
153
- export declare function schema<T extends ShapeSchema>(schema: T): EnrichFields<T> & {
153
+ export declare function schema<T extends ShapeSchema>(schema: T): Prettify<EnrichFields<T> & {
154
154
  _tableName: T["_tableName"];
155
- };
155
+ }>;
156
156
  export type RelationType = "hasMany" | "hasOne" | "manyToMany";
157
157
  type BaseSchemaField<T extends SQLType = SQLType> = {
158
158
  type: "field";
@@ -184,10 +184,6 @@ type Relation<U extends Schema<any>> = {
184
184
  defaultCount?: number;
185
185
  };
186
186
  export declare function createMixedValidationSchema<T extends Schema<any>>(schema: T, clientSchema?: z.ZodObject<any>, dbSchema?: z.ZodObject<any>): z.ZodObject<any>;
187
- type SchemaDefinition = {
188
- _tableName: string;
189
- [key: string]: any;
190
- };
191
187
  type InferSchemaByKey<T, Key extends "zodSqlSchema" | "zodClientSchema" | "zodValidationSchema", Depth extends any[] = []> = Depth["length"] extends 10 ? any : {
192
188
  [K in keyof T as K extends "_tableName" | typeof SchemaWrapperBrand ? never : K]: T[K] extends {
193
189
  config: {
@@ -223,30 +219,16 @@ type InferSchemaByKey<T, Key extends "zodSqlSchema" | "zodClientSchema" | "zodVa
223
219
  type InferSqlSchema<T> = InferSchemaByKey<T, "zodSqlSchema">;
224
220
  type InferClientSchema<T> = InferSchemaByKey<T, "zodClientSchema">;
225
221
  type InferValidationSchema<T> = InferSchemaByKey<T, "zodValidationSchema">;
226
- type InferDefaultValues2<T> = {
227
- [K in keyof T as K extends "_tableName" ? never : K]: T[K] extends {
228
- config: {
229
- initialValue: infer D;
230
- };
231
- } ? D : T[K] extends () => {
232
- type: "hasMany" | "manyToMany";
233
- schema: infer S extends SchemaDefinition;
234
- defaultCount?: number;
235
- } ? Array<Prettify<InferDefaultValues2<S>>> : T[K] extends () => {
236
- type: "hasOne" | "belongsTo";
237
- schema: infer S extends SchemaDefinition;
238
- } ? Prettify<InferDefaultValues2<S>> : never;
239
- };
240
222
  export declare function createSchema<T extends {
241
223
  _tableName: string;
242
224
  [SchemaWrapperBrand]?: true;
243
225
  }, R extends Record<string, any> = {}, TActualSchema extends Omit<T & R, typeof SchemaWrapperBrand> = Omit<T & R, typeof SchemaWrapperBrand>>(schema: T, relations?: R): {
244
- sqlSchema: z.ZodObject<Prettify<InferSqlSchema<TActualSchema>>>;
245
- clientSchema: z.ZodObject<Prettify<InferClientSchema<TActualSchema>>>;
246
- validationSchema: z.ZodObject<Prettify<InferValidationSchema<TActualSchema>>>;
247
- defaultValues: Prettify<InferDefaultValues2<TActualSchema>>;
248
- toClient: (dbObject: z.infer<z.ZodObject<Prettify<InferSqlSchema<TActualSchema>>>>) => z.infer<z.ZodObject<Prettify<InferClientSchema<TActualSchema>>>>;
249
- toDb: (clientObject: z.infer<z.ZodObject<Prettify<InferClientSchema<TActualSchema>>>>) => z.infer<z.ZodObject<Prettify<InferSqlSchema<TActualSchema>>>>;
226
+ sqlSchema: z.ZodObject<Prettify<DeriveSchemaByKey<TActualSchema, "zodSqlSchema">>>;
227
+ clientSchema: z.ZodObject<Prettify<DeriveSchemaByKey<TActualSchema, "zodClientSchema">>>;
228
+ validationSchema: z.ZodObject<Prettify<DeriveSchemaByKey<TActualSchema, "zodValidationSchema">>>;
229
+ defaultValues: Prettify<DeriveDefaults<TActualSchema>>;
230
+ toClient: (dbObject: z.infer<z.ZodObject<Prettify<DeriveSchemaByKey<TActualSchema, "zodSqlSchema">>>>) => z.infer<z.ZodObject<Prettify<DeriveSchemaByKey<TActualSchema, "zodClientSchema">>>>;
231
+ toDb: (clientObject: z.infer<z.ZodObject<Prettify<DeriveSchemaByKey<TActualSchema, "zodClientSchema">>>>) => z.infer<z.ZodObject<Prettify<DeriveSchemaByKey<TActualSchema, "zodSqlSchema">>>>;
250
232
  };
251
233
  type RelationBuilders<TSchema> = {
252
234
  reference: <TField extends object>(fieldGetter: () => TField) => {
@@ -257,18 +239,23 @@ type RelationBuilders<TSchema> = {
257
239
  fromKey: keyof TSchema & string;
258
240
  toKey: () => TField;
259
241
  defaultCount?: number;
260
- }) => Builder<"relation", RelationConfig<TField["__parentTableType"]>, z.ZodArray<z.ZodObject<InferSqlSchema<TField["__parentTableType"]>>>, z.ZodArray<z.ZodObject<InferClientSchema<TField["__parentTableType"]>>>, any[], z.ZodArray<z.ZodObject<InferClientSchema<TField["__parentTableType"]>>>, z.ZodArray<z.ZodObject<InferValidationSchema<TField["__parentTableType"]>>>>;
261
- hasOne: <T extends Schema<any>>(config: {
242
+ }) => Builder<"relation", BaseRelationConfig<TField["__parentTableType"]> & {
243
+ type: "hasMany";
244
+ }, z.ZodArray<z.ZodObject<InferSqlSchema<TField["__parentTableType"]>>>, z.ZodArray<z.ZodObject<InferClientSchema<TField["__parentTableType"]>>>, any[], z.ZodArray<z.ZodObject<InferClientSchema<TField["__parentTableType"]>>>, z.ZodArray<z.ZodObject<InferValidationSchema<TField["__parentTableType"]>>>>;
245
+ hasOne: <T extends Schema<any>, K extends keyof T & string, TField extends EnrichedField<K, T[K], T>>(config: {
262
246
  fromKey: keyof TSchema & string;
263
- toKey: () => T[keyof T];
264
- schema: () => T;
265
- }) => Builder<"relation", RelationConfig<T>, z.ZodArray<any>, z.ZodArray<any>, any[], z.ZodArray<any>, z.ZodArray<any>>;
247
+ toKey: () => TField;
248
+ }) => Builder<"relation", BaseRelationConfig<TField["__parentTableType"]> & {
249
+ type: "hasOne";
250
+ }, z.ZodArray<z.ZodObject<InferSqlSchema<TField["__parentTableType"]>>>, z.ZodArray<z.ZodObject<InferClientSchema<TField["__parentTableType"]>>>, any, z.ZodArray<z.ZodObject<InferClientSchema<TField["__parentTableType"]>>>, z.ZodArray<z.ZodObject<InferValidationSchema<TField["__parentTableType"]>>>>;
266
251
  manyToMany: <T extends Schema<any>>(config: {
267
252
  fromKey: keyof TSchema & string;
268
253
  toKey: () => T[keyof T];
269
254
  schema: () => T;
270
255
  defaultCount?: number;
271
- }) => Builder<"relation", RelationConfig<T>, z.ZodOptional<z.ZodArray<z.ZodAny>>, z.ZodOptional<z.ZodArray<z.ZodAny>>, any[], z.ZodOptional<z.ZodArray<z.ZodAny>>, z.ZodOptional<z.ZodArray<z.ZodAny>>>;
256
+ }) => Builder<"relation", BaseRelationConfig<T> & {
257
+ type: "manyToMany";
258
+ }, z.ZodOptional<z.ZodArray<z.ZodAny>>, z.ZodOptional<z.ZodArray<z.ZodAny>>, any[], z.ZodOptional<z.ZodArray<z.ZodAny>>, z.ZodOptional<z.ZodArray<z.ZodAny>>>;
272
259
  };
273
260
  export declare function schemaRelations<TSchema extends Schema<any>, RefObject extends Record<string, any>>(baseSchema: TSchema, referencesBuilder: (rel: RelationBuilders<TSchema>) => RefObject): {
274
261
  [K in keyof RefObject]: RefObject[K] & {
@@ -290,12 +277,11 @@ type DeriveSchemaByKey<T, Key extends "zodSqlSchema" | "zodClientSchema" | "zodV
290
277
  schema: () => infer S;
291
278
  };
292
279
  };
293
- } ? z.ZodArray<S extends {
280
+ } ? S extends {
294
281
  _tableName: string;
295
- } ? z.ZodObject<Prettify<DeriveSchemaByKey<S, Key, [...Depth, 1]>>> : z.ZodObject<any>> : T[K] extends {
282
+ } ? z.ZodArray<z.ZodObject<Prettify<DeriveSchemaByKey<S, Key, [...Depth, 1]>>>> : never : T[K] extends {
296
283
  config: {
297
284
  sql: {
298
- type: "hasOne" | "belongsTo";
299
285
  schema: () => infer S;
300
286
  };
301
287
  };
@@ -314,29 +300,36 @@ type DeriveSchemaByKey<T, Key extends "zodSqlSchema" | "zodClientSchema" | "zodV
314
300
  };
315
301
  } ? ZodSchema : never;
316
302
  };
317
- type DeriveDefaults<T> = Prettify<{
303
+ type DeriveDefaults<T, Depth extends any[] = []> = Prettify<Depth["length"] extends 10 ? any : {
318
304
  [K in keyof T as K extends "_tableName" | typeof SchemaWrapperBrand ? never : K]: T[K] extends {
305
+ config: {
306
+ sql: infer SqlConfig;
307
+ initialValue: infer D;
308
+ };
309
+ } ? SqlConfig extends {
310
+ type: "hasMany" | "manyToMany";
311
+ schema: () => infer S;
312
+ } ? Array<DeriveDefaults<S, [...Depth, 1]>> : SqlConfig extends {
313
+ type: "hasOne" | "belongsTo";
314
+ schema: () => infer S;
315
+ } ? DeriveDefaults<S, [...Depth, 1]> : D extends () => infer R ? R : D : T[K] extends {
316
+ type: "reference";
317
+ to: () => infer RefField;
318
+ } ? RefField extends {
319
319
  config: {
320
320
  initialValue: infer D;
321
321
  };
322
- } ? D extends () => infer R ? R : D : never;
322
+ } ? D extends () => infer R ? R : D : never : never;
323
323
  }>;
324
324
  export type InferFromSchema<T extends {
325
325
  _tableName: string;
326
326
  }> = Prettify<{
327
- /** The Zod schema for the **SQL (database)** layer. */
328
327
  SqlSchema: z.ZodObject<Prettify<DeriveSchemaByKey<T, "zodSqlSchema">>>;
329
- /** The Zod schema for the **Client** layer. */
330
328
  ClientSchema: z.ZodObject<Prettify<DeriveSchemaByKey<T, "zodClientSchema">>>;
331
- /** The Zod schema for the **Validation** layer. */
332
329
  ValidationSchema: z.ZodObject<Prettify<DeriveSchemaByKey<T, "zodValidationSchema">>>;
333
- /** The TypeScript type for data as it exists in the **database**. */
334
330
  Sql: z.infer<z.ZodObject<Prettify<DeriveSchemaByKey<T, "zodSqlSchema">>>>;
335
- /** The TypeScript type for data as it is represented on the **client**. */
336
331
  Client: z.infer<z.ZodObject<Prettify<DeriveSchemaByKey<T, "zodClientSchema">>>>;
337
- /** The TypeScript type for **validation** data, often the most flexible shape. */
338
332
  Validation: z.infer<z.ZodObject<Prettify<DeriveSchemaByKey<T, "zodValidationSchema">>>>;
339
- /** The TypeScript type for the object of **default values**. */
340
333
  Defaults: DeriveDefaults<T>;
341
334
  }>;
342
335
  export {};
package/dist/schema.js CHANGED
@@ -301,10 +301,19 @@ function inferDefaultFromZod(zodType, sqlConfig) {
301
301
  }
302
302
  return sqlConfig.default;
303
303
  }
304
- // Check if it's a relation config (this logic is fine)
305
304
  if (typeof sqlConfig.type === "string" &&
306
305
  ["hasMany", "hasOne", "belongsTo", "manyToMany"].includes(sqlConfig.type)) {
307
- // ... your existing relation logic is fine ...
306
+ const relationConfig = sqlConfig;
307
+ if (relationConfig.type === "hasMany" ||
308
+ relationConfig.type === "manyToMany") {
309
+ // For hasMany/manyToMany, default to an array based on defaultCount.
310
+ return Array.from({ length: relationConfig.defaultCount || 0 }, () => ({}));
311
+ }
312
+ if (relationConfig.type === "hasOne" ||
313
+ relationConfig.type === "belongsTo") {
314
+ // For hasOne/belongsTo, default to a single empty object.
315
+ return {};
316
+ }
308
317
  }
309
318
  // Handle SQL type-based generation (this is the fallback)
310
319
  const sqlTypeConfig = sqlConfig;
@@ -422,85 +431,69 @@ export function createSchema(schema, relations) {
422
431
  const validationFields = {};
423
432
  const defaultValues = {};
424
433
  const fieldTransforms = {};
425
- // --- PASS 1: Process main schema fields (no relations here) ---
426
- for (const key in schema) {
427
- if (key === "_tableName" || key.startsWith("__"))
434
+ const fullSchema = { ...schema, ...(relations || {}) };
435
+ for (const key in fullSchema) {
436
+ if (key === "_tableName" ||
437
+ key.startsWith("__") ||
438
+ key === String(SchemaWrapperBrand))
439
+ continue;
440
+ const definition = fullSchema[key];
441
+ // --- THIS IS THE FIX ---
442
+ // The condition now correctly checks for EITHER a `reference` type OR a builder with a `.config`.
443
+ if (!definition ||
444
+ (definition.type !== "reference" && !definition.config)) {
428
445
  continue;
429
- const definition = schema[key];
430
- if (definition && definition.type === "reference") {
431
- // Handle reference fields
446
+ }
447
+ if (definition.type === "reference") {
448
+ // This block now correctly processes `testId`.
432
449
  const referencedFieldBuilder = definition.to();
433
450
  const referencedConfig = referencedFieldBuilder.config;
434
451
  sqlFields[key] = referencedConfig.zodSqlSchema;
435
452
  clientFields[key] = referencedConfig.zodClientSchema;
436
453
  validationFields[key] = referencedConfig.zodValidationSchema;
437
- // Foreign key fields should get their own default, not the referenced field's default
438
454
  defaultValues[key] = inferDefaultFromZod(referencedConfig.zodClientSchema, { ...referencedConfig.sql, default: undefined });
439
455
  }
440
- else if (definition && definition.config) {
441
- // Handle regular fields with builder pattern
456
+ else {
457
+ // This block handles fields with a `.config` property, like `pets`.
442
458
  const config = definition.config;
443
- sqlFields[key] = config.zodSqlSchema;
444
- clientFields[key] = config.zodClientSchema;
445
- validationFields[key] = config.zodValidationSchema;
446
- if (config.transforms) {
447
- fieldTransforms[key] = config.transforms;
448
- }
449
- // Handle initial value
450
- const initialValueOrFn = config.initialValue;
451
- if (isFunction(initialValueOrFn)) {
452
- defaultValues[key] = initialValueOrFn();
459
+ const sqlConfig = config.sql;
460
+ if (sqlConfig &&
461
+ typeof sqlConfig === "object" &&
462
+ ["hasMany", "hasOne", "belongsTo", "manyToMany"].includes(sqlConfig.type)) {
463
+ const relatedSchemaFactory = sqlConfig.schema;
464
+ const childSchemaResult = createSchema(relatedSchemaFactory());
465
+ let baseSqlSchema;
466
+ let baseClientSchema;
467
+ if (sqlConfig.type === "hasMany" || sqlConfig.type === "manyToMany") {
468
+ baseSqlSchema = z.array(childSchemaResult.sqlSchema);
469
+ baseClientSchema = z.array(childSchemaResult.clientSchema);
470
+ defaultValues[key] = Array.from({ length: sqlConfig.defaultCount || 0 }, () => childSchemaResult.defaultValues);
471
+ }
472
+ else {
473
+ baseSqlSchema = childSchemaResult.sqlSchema;
474
+ baseClientSchema = childSchemaResult.clientSchema;
475
+ defaultValues[key] = childSchemaResult.defaultValues;
476
+ }
477
+ sqlFields[key] = baseSqlSchema.optional();
478
+ clientFields[key] = config.clientTransform
479
+ ? config.clientTransform(baseClientSchema)
480
+ : baseClientSchema;
481
+ validationFields[key] = clientFields[key];
453
482
  }
454
483
  else {
455
- defaultValues[key] = initialValueOrFn;
456
- }
457
- }
458
- }
459
- // --- PASS 2: Process relations if provided ---
460
- if (relations) {
461
- for (const key in relations) {
462
- const relationDefinition = relations[key];
463
- if (relationDefinition && relationDefinition.config) {
464
- const config = relationDefinition.config;
465
- const sqlConfig = config.sql;
466
- if (sqlConfig &&
467
- typeof sqlConfig === "object" &&
468
- ["hasMany", "hasOne", "belongsTo", "manyToMany"].includes(sqlConfig.type)) {
469
- const relationConfig = sqlConfig;
470
- const childSchemaResult = createSchema(relationConfig.schema());
471
- // Create the base schemas based on relation type
472
- let baseSqlSchema;
473
- let baseClientSchema;
474
- let baseValidationSchema;
475
- if (relationConfig.type === "hasMany" ||
476
- relationConfig.type === "manyToMany") {
477
- baseSqlSchema = z.array(childSchemaResult.sqlSchema);
478
- baseClientSchema = z.array(childSchemaResult.clientSchema);
479
- baseValidationSchema = z.array(childSchemaResult.validationSchema);
480
- defaultValues[key] = Array.from({ length: relationConfig.defaultCount || 0 }, () => childSchemaResult.defaultValues);
481
- }
482
- else {
483
- baseSqlSchema = childSchemaResult.sqlSchema;
484
- baseClientSchema = childSchemaResult.clientSchema;
485
- baseValidationSchema = childSchemaResult.validationSchema;
486
- defaultValues[key] = childSchemaResult.defaultValues;
487
- }
488
- // Apply transforms if they exist
489
- const finalClientSchema = config.clientTransform
490
- ? config.clientTransform(baseClientSchema)
491
- : baseClientSchema;
492
- const finalValidationSchema = config.validationTransform
493
- ? config.validationTransform(baseValidationSchema)
494
- : finalClientSchema;
495
- // Assign the schemas
496
- sqlFields[key] = baseSqlSchema.optional(); // SQL fields are optional for lazy loading
497
- clientFields[key] = finalClientSchema;
498
- validationFields[key] = finalValidationSchema;
484
+ sqlFields[key] = config.zodSqlSchema;
485
+ clientFields[key] = config.zodClientSchema;
486
+ validationFields[key] = config.zodValidationSchema;
487
+ if (config.transforms) {
488
+ fieldTransforms[key] = config.transforms;
499
489
  }
490
+ const initialValueOrFn = config.initialValue;
491
+ defaultValues[key] = isFunction(initialValueOrFn)
492
+ ? initialValueOrFn()
493
+ : initialValueOrFn;
500
494
  }
501
495
  }
502
496
  }
503
- // Create transform functions
504
497
  const toClient = (dbObject) => {
505
498
  const clientObject = { ...dbObject };
506
499
  for (const key in fieldTransforms) {
@@ -558,7 +551,7 @@ export function schemaRelations(baseSchema, referencesBuilder) {
558
551
  type: "hasOne",
559
552
  fromKey: config.fromKey,
560
553
  toKey: config.toKey,
561
- schema: config.schema,
554
+ schema: () => config.toKey.__parentTableType,
562
555
  };
563
556
  const relationZodType = z.any();
564
557
  return createBuilder({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cogsbox-shape",
3
- "version": "0.5.85",
3
+ "version": "0.5.87",
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",