cogsbox-shape 0.5.148 → 0.5.150

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