cogsbox-shape 0.5.147 → 0.5.149

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 (2) hide show
  1. package/dist/schema.js +24 -36
  2. package/package.json +1 -1
package/dist/schema.js CHANGED
@@ -456,11 +456,14 @@ export function createSchema(schema, relations) {
456
456
  const fullSchema = { ...schema, ...(relations || {}) };
457
457
  let pkKeys = [];
458
458
  let clientPkKeys = [];
459
- const pkResolver = schema.__pkResolver;
460
459
  for (const key in fullSchema) {
460
+ const value = fullSchema[key];
461
461
  if (key === "_tableName" ||
462
462
  key.startsWith("__") ||
463
- key === String(SchemaWrapperBrand))
463
+ key === String(SchemaWrapperBrand) ||
464
+ key === "isClient" ||
465
+ key === "primaryKeySQL" ||
466
+ typeof value === "function")
464
467
  continue;
465
468
  const definition = fullSchema[key];
466
469
  // Handle new-style references
@@ -556,54 +559,43 @@ export function createSchema(schema, relations) {
556
559
  toDb,
557
560
  };
558
561
  }
559
- function createViewObject(initialRegistryKey, // The key for the starting schema, e.g., "users"
560
- selection, registry, tableNameToRegistryKeyMap // The lookup map
561
- ) {
562
- /**
563
- * A recursive helper function that builds a Zod schema for a given schema and its selected relations.
564
- * It is defined inside createViewObject to have access to the `registry` and `tableNameToRegistryKeyMap` via a closure.
565
- *
566
- * @param currentRegistryKey - The user-defined key for the current schema being processed (e.g., "users", then "posts").
567
- * @param subSelection - The part of the selection object for the current schema (e.g., { comments: true } or just `true`).
568
- * @param schemaType - Whether to build the 'client' or 'validation' schema.
569
- * @returns A ZodObject representing the composed schema.
570
- */
562
+ function createViewObject(initialRegistryKey, selection, registry, tableNameToRegistryKeyMap) {
563
+ // Add a flag to track if all tables support reconciliation
564
+ let allTablesSupportsReconciliation = true;
571
565
  function buildView(currentRegistryKey, subSelection, schemaType) {
572
- // 1. Find the current schema's definition in the registry using its KEY.
573
566
  const registryEntry = registry[currentRegistryKey];
574
567
  if (!registryEntry) {
575
568
  throw new Error(`Schema with key "${currentRegistryKey}" not found in the registry.`);
576
569
  }
577
- // 2. Get the base Zod schema (primitives and references only) for the current level.
570
+ // Check if this table has pk and clientPk
571
+ const hasPks = !!(registryEntry.pk &&
572
+ registryEntry.pk.length > 0 &&
573
+ registryEntry.clientPk &&
574
+ registryEntry.clientPk.length > 0);
575
+ if (!hasPks) {
576
+ allTablesSupportsReconciliation = false;
577
+ }
578
578
  const baseSchema = schemaType === "server"
579
579
  ? registryEntry.zodSchemas.validationSchema
580
580
  : registryEntry.zodSchemas.clientSchema;
581
581
  const primitiveShape = baseSchema.shape;
582
- // 3. If the selection is just `true`, we are done at this level. Return the base primitive schema.
583
582
  if (subSelection === true) {
584
583
  return z.object(primitiveShape);
585
584
  }
586
- // 4. If the selection is an object, we need to process its relations.
587
585
  const selectedRelationShapes = {};
588
586
  if (typeof subSelection === "object") {
589
- // Iterate over the keys in the selection object (e.g., "posts", "profile").
590
587
  for (const relationKey in subSelection) {
591
- // Check if this key corresponds to a valid relation in the raw schema definition.
592
588
  const relationBuilder = registryEntry.rawSchema[relationKey];
593
589
  const isRelation = relationBuilder?.config?.sql?.schema;
594
590
  if (subSelection[relationKey] && isRelation) {
595
591
  const relationConfig = relationBuilder.config.sql;
596
- // 5. KEY STEP: Get the internal `_tableName` of the TARGET schema (e.g., "post_table").
597
592
  const targetTableName = relationConfig.schema()._tableName;
598
- // 6. KEY STEP: Use the map to find the REGISTRY KEY for that target schema (e.g., "posts").
599
593
  const nextRegistryKey = tableNameToRegistryKeyMap[targetTableName];
600
594
  if (!nextRegistryKey) {
601
595
  throw new Error(`Could not resolve registry key for table "${targetTableName}"`);
602
596
  }
603
- // 7. RECURSIVE CALL: Call `buildView` for the related schema, passing the
604
- // CORRECT registry key and the sub-selection for that relation.
597
+ // Recursive call will also check that table's pk/clientPk
605
598
  const relationSchema = buildView(nextRegistryKey, subSelection[relationKey], schemaType);
606
- // 8. Wrap the resulting schema in an array or optional based on the relation type.
607
599
  if (["hasMany", "manyToMany"].includes(relationConfig.type)) {
608
600
  selectedRelationShapes[relationKey] = z.array(relationSchema);
609
601
  }
@@ -613,15 +605,14 @@ selection, registry, tableNameToRegistryKeyMap // The lookup map
613
605
  }
614
606
  }
615
607
  }
616
- // 9. Combine the base primitive fields with the newly built relational schemas.
617
608
  const finalShape = { ...primitiveShape, ...selectedRelationShapes };
618
609
  return z.object(finalShape);
619
610
  }
620
- // The main function's return value. It kicks off the recursive process for both client and validation schemas.
621
611
  return {
622
612
  sql: registry[initialRegistryKey].zodSchemas.sqlSchema,
623
613
  client: buildView(initialRegistryKey, selection, "client"),
624
614
  server: buildView(initialRegistryKey, selection, "server"),
615
+ supportsReconciliation: allTablesSupportsReconciliation, // Add this flag
625
616
  };
626
617
  }
627
618
  export function createSchemaBox(schemas, resolver) {
@@ -768,9 +759,8 @@ export function createSchemaBox(schemas, resolver) {
768
759
  createView: (selection) => {
769
760
  const view = createViewObject(tableName, selection, finalRegistry, tableNameToRegistryKeyMap);
770
761
  const defaults = computeViewDefaults(tableName, selection, finalRegistry, tableNameToRegistryKeyMap);
771
- // Return the same shape as regular entries, but with isView marker
772
762
  return {
773
- definition: entry.rawSchema, // Could be enhanced with selection info
763
+ definition: entry.rawSchema,
774
764
  schemaKey: tableName,
775
765
  schemas: {
776
766
  sql: view.sql,
@@ -778,17 +768,15 @@ export function createSchemaBox(schemas, resolver) {
778
768
  server: view.server,
779
769
  },
780
770
  transforms: {
781
- toClient: entry.zodSchemas.toClient, // May need composition for nested
771
+ toClient: entry.zodSchemas.toClient,
782
772
  toDb: entry.zodSchemas.toDb,
783
773
  },
784
774
  defaults: defaults,
785
- isView: true, // Discriminator
786
- viewSelection: selection, // Store what was selected
775
+ // Use the flag from createViewObject
776
+ supportsReconciliation: view.supportsReconciliation,
777
+ isView: true,
778
+ viewSelection: selection,
787
779
  baseTable: tableName,
788
- // Optionally exclude these for views:
789
- // nav: undefined,
790
- // createView: undefined,
791
- // RelationSelection: undefined,
792
780
  __registry: finalRegistry,
793
781
  };
794
782
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cogsbox-shape",
3
- "version": "0.5.147",
3
+ "version": "0.5.149",
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",