@sequenceholdings/orm 2.4.0 → 2.5.0

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 (59) hide show
  1. package/dist/authoring.cjs +53 -7
  2. package/dist/authoring.cjs.map +1 -1
  3. package/dist/authoring.d.cts +11 -7
  4. package/dist/authoring.d.ts +11 -7
  5. package/dist/authoring.js +53 -7
  6. package/dist/authoring.js.map +1 -1
  7. package/dist/canonical.cjs +48 -2
  8. package/dist/canonical.cjs.map +1 -1
  9. package/dist/canonical.d.cts +72 -72
  10. package/dist/canonical.d.ts +72 -72
  11. package/dist/canonical.js +48 -2
  12. package/dist/canonical.js.map +1 -1
  13. package/dist/cli.cjs +237 -20
  14. package/dist/cli.cjs.map +1 -1
  15. package/dist/cli.js +237 -20
  16. package/dist/cli.js.map +1 -1
  17. package/dist/client.cjs +1 -1
  18. package/dist/client.cjs.map +1 -1
  19. package/dist/client.d.cts +1 -1
  20. package/dist/client.d.ts +1 -1
  21. package/dist/client.js +1 -1
  22. package/dist/client.js.map +1 -1
  23. package/dist/compiler.cjs +386 -14
  24. package/dist/compiler.cjs.map +1 -1
  25. package/dist/compiler.d.cts +16 -3
  26. package/dist/compiler.d.ts +16 -3
  27. package/dist/compiler.js +386 -15
  28. package/dist/compiler.js.map +1 -1
  29. package/dist/{constants-C6EG6Wq7.d.cts → constants-Dou1RkTo.d.cts} +7 -2
  30. package/dist/{constants-C6EG6Wq7.d.ts → constants-Dou1RkTo.d.ts} +7 -2
  31. package/dist/dynamic-input.d.cts +1 -1
  32. package/dist/dynamic-input.d.ts +1 -1
  33. package/dist/index.cjs +329 -130
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.d.cts +66 -58
  36. package/dist/index.d.ts +66 -58
  37. package/dist/index.js +329 -131
  38. package/dist/index.js.map +1 -1
  39. package/dist/ir.cjs +50 -3
  40. package/dist/ir.cjs.map +1 -1
  41. package/dist/ir.d.cts +71 -71
  42. package/dist/ir.d.ts +71 -71
  43. package/dist/ir.js +50 -3
  44. package/dist/ir.js.map +1 -1
  45. package/dist/predicate-v2.cjs +50 -3
  46. package/dist/predicate-v2.cjs.map +1 -1
  47. package/dist/predicate-v2.d.cts +1 -1
  48. package/dist/predicate-v2.d.ts +1 -1
  49. package/dist/predicate-v2.js +50 -3
  50. package/dist/predicate-v2.js.map +1 -1
  51. package/dist/sdl.cjs +53 -3
  52. package/dist/sdl.cjs.map +1 -1
  53. package/dist/sdl.d.cts +3 -1
  54. package/dist/sdl.d.ts +3 -1
  55. package/dist/sdl.js +53 -3
  56. package/dist/sdl.js.map +1 -1
  57. package/package.json +1 -1
  58. package/dist/{definition-DjfC7Lll.d.cts → definition-B99BsOAO.d.cts} +4 -4
  59. package/dist/{definition-DjfC7Lll.d.ts → definition-B99BsOAO.d.ts} +4 -4
package/dist/sdl.cjs CHANGED
@@ -204,8 +204,10 @@ function compileCheckExpression(source, columns) {
204
204
  }
205
205
 
206
206
  // src/constants.ts
207
+ var NAMESPACE_PATTERN = /^(?!(?:events|native_sources)$)[a-z][a-z0-9_]{0,40}$/;
207
208
  var COLUMN_IDENTIFIER_PATTERN = /^_?[a-z][a-z0-9_]*$/;
208
209
  var MAX_IDENTIFIER_LENGTH = 63;
210
+ var MAX_PERSISTED_READ_ROWS = 50001;
209
211
  var QUALIFIED_TABLE_PATTERN = /^[a-z][a-z0-9_]{0,62}\.[a-z][a-z0-9_]{0,62}$/;
210
212
  var CELL_PARTS = ["at", "by", "rev", "source", "conflicts"];
211
213
  var CELL_PART_SUFFIX = {
@@ -358,6 +360,7 @@ function validateResolvedView({ view, tables, views = [] }) {
358
360
  function validateSource({ scope, source, table }) {
359
361
  const { fail } = scope;
360
362
  if (source.kind === "etl" && table.source === void 0) fail(`etl source '${source.name}' must reference a synced table`);
363
+ if (source.kind === "etl" && table.primaryKey?.length === 0) fail(`etl source '${source.name}' cannot use an unkeyed synced table for resolved row identity`);
361
364
  if (source.kind !== "etl" && (table.internal !== true || table.cellMetadata !== true)) {
362
365
  fail(`${source.kind} source '${source.name}' must reference an internal table with cell metadata`);
363
366
  }
@@ -649,7 +652,7 @@ var canonicalTableSchema = zod.z.object({
649
652
  /** Synced/reflected read-only tables (`source: schema.table`) — v1 semantics. */
650
653
  source: zod.z.string().regex(QUALIFIED_TABLE_PATTERN).optional(),
651
654
  columns: zod.z.array(canonicalColumnSchema).default([]),
652
- primaryKey: zod.z.array(columnIdentifier).min(1).max(8).optional(),
655
+ primaryKey: zod.z.array(columnIdentifier).max(8).optional(),
653
656
  links: zod.z.array(canonicalLinkSchema).default([]),
654
657
  indexes: zod.z.array(canonicalIndexSchema).default([]),
655
658
  /** Omitted by old definitions, preserving their existing content hashes. */
@@ -685,6 +688,29 @@ var canonicalTableSchema = zod.z.object({
685
688
  * data plane. Omitted otherwise.
686
689
  */
687
690
  materializes: identifier2.optional()
691
+ }).superRefine((table, ctx) => {
692
+ if (table.primaryKey?.length !== 0) return;
693
+ const fail = (message, path = ["primaryKey"]) => ctx.addIssue({ code: "custom", path, message: `unkeyed table '${table.table}' ${message}` });
694
+ if (table.source === void 0 || table.columns.length === 0) {
695
+ fail("requires a typed synced source");
696
+ }
697
+ if ([table.policies.write, table.policies.insert, table.policies.update].some((policy) => policy !== void 0)) {
698
+ fail("is read-only and cannot declare write policies", ["policies"]);
699
+ }
700
+ const ownedCollections = [table.indexes, table.actions, table.checks, table.foreignKeys, table.cowMutations];
701
+ const ownedMetadata = [table.cellMetadata, table.internal, table.materializes, table.renamedFrom];
702
+ if (ownedCollections.some((items) => items !== void 0 && items.length > 0) || ownedMetadata.some((value) => value !== void 0)) {
703
+ fail("cannot declare owned storage, constraints or identity operations");
704
+ }
705
+ for (const [index, column] of table.columns.entries()) {
706
+ const ownedColumnMetadata = [column.default, column.defaultFn, column.onUpdateFn, column.renamedFrom, column.cast, column.cell];
707
+ if (column.unique || ownedColumnMetadata.some((value) => value !== void 0)) {
708
+ fail("cannot declare column uniqueness, mutation defaults or migration metadata", ["columns", index]);
709
+ }
710
+ }
711
+ for (const [index, link] of table.links.entries()) {
712
+ if (link.enforce || link.kind === "toMany") fail("cannot provide an identity for this link", ["links", index]);
713
+ }
688
714
  });
689
715
  var MAX_VIEW_QUERY = 1e5;
690
716
  var MAX_RESOLVED_VIEW_QUERY = 5e6;
@@ -741,6 +767,26 @@ var canonicalViewSchema = zod.z.object({
741
767
  }
742
768
  }
743
769
  });
770
+ function validateUnkeyedLinkIdentities({ definition, ctx }) {
771
+ const tables = new Map(definition.tables.map((table) => [table.table, table]));
772
+ const relations = [
773
+ ...definition.tables.map((table, index) => ({ kind: "tables", index, links: table.links })),
774
+ ...(definition.views ?? []).map((view, index) => ({ kind: "views", index, links: view.links }))
775
+ ];
776
+ for (const relation of relations) {
777
+ for (const [linkIndex, link] of relation.links.entries()) {
778
+ if (link.kind !== "toOne" || link.namespace !== void 0 && link.namespace !== definition.namespace) continue;
779
+ const target = link.target === void 0 ? void 0 : tables.get(link.target);
780
+ if (target?.source !== void 0 && target.primaryKey?.length === 0) {
781
+ ctx.addIssue({
782
+ code: "custom",
783
+ path: [relation.kind, relation.index, "links", linkIndex],
784
+ message: `link '${link.name}' cannot use unkeyed table '${target.table}' as a to-one identity`
785
+ });
786
+ }
787
+ }
788
+ }
789
+ }
744
790
  var CELL_PART_TYPES = {
745
791
  at: "timestamptz",
746
792
  by: "text",
@@ -804,7 +850,7 @@ var exportGateSchema = zod.z.union([zod.z.literal(true), zod.z.object({ capabili
804
850
  var relationExportSchema = zod.z.object({ read: exportGateSchema, write: exportGateSchema.optional() }).strict();
805
851
  var localDefinitionSchema = zod.z.object({
806
852
  definition_format: zod.z.literal(CANONICAL_FORMAT),
807
- namespace: identifier2.max(41),
853
+ namespace: identifier2.max(41).regex(NAMESPACE_PATTERN, "invalid or reserved ORM namespace"),
808
854
  description: zod.z.string().max(2e3).optional(),
809
855
  enums: zod.z.array(canonicalEnumSchema).default([]),
810
856
  tables: zod.z.array(canonicalTableSchema).min(0).max(500),
@@ -838,6 +884,7 @@ var localDefinitionSchema = zod.z.object({
838
884
  }
839
885
  }
840
886
  const fkTables = new Map(definition.tables.map((table) => [table.table, table]));
887
+ validateUnkeyedLinkIdentities({ definition, ctx });
841
888
  const relations = /* @__PURE__ */ new Set([...fkTables.keys(), ...(definition.views ?? []).map((view) => view.view)]);
842
889
  for (const name of Object.keys(definition.exports ?? {})) {
843
890
  if (!relations.has(name)) ctx.addIssue({ code: "custom", path: ["exports", name], message: `export '${name}' is not a local object` });
@@ -1266,7 +1313,7 @@ var limitIrSchema = zod.z.object({
1266
1313
  variable: zod.z.string().optional(),
1267
1314
  value: zod.z.number().int().positive().optional(),
1268
1315
  default: zod.z.number().int().positive(),
1269
- max: zod.z.number().int().positive()
1316
+ max: zod.z.number().int().positive().max(MAX_PERSISTED_READ_ROWS)
1270
1317
  });
1271
1318
  var selectionIrSchema = zod.z.lazy(
1272
1319
  () => zod.z.object({
@@ -1792,6 +1839,9 @@ function generateSdl(canonical, options = {}) {
1792
1839
  blocks.push(
1793
1840
  '"""Gates an operation behind a platform capability or custom role \u2014 checked by the data plane before execution."""\ndirective @requires(capability: String, role: String) on QUERY | MUTATION'
1794
1841
  );
1842
+ if (!options.omitReadBudgetDirective) blocks.push(
1843
+ '"""Sets a document-authored ceiling of 1\u201350001 rows for one flat select root. Runtime variables cannot raise it."""\ndirective @readBudget(maxRows: Int!) on QUERY'
1844
+ );
1795
1845
  blocks.push("directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT");
1796
1846
  blocks.push(
1797
1847
  '"""Abort the entire mutation unless this root affects exactly the document-authored number of rows. Mutation roots only; cannot be conditional."""\ndirective @assertAffectedRows(exactly: Int!) on FIELD'