@sequenceholdings/orm 2.4.0 → 2.6.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 (58) hide show
  1. package/README.md +23 -0
  2. package/dist/authoring.cjs +53 -7
  3. package/dist/authoring.cjs.map +1 -1
  4. package/dist/authoring.d.cts +10 -6
  5. package/dist/authoring.d.ts +10 -6
  6. package/dist/authoring.js +53 -7
  7. package/dist/authoring.js.map +1 -1
  8. package/dist/canonical.cjs +48 -2
  9. package/dist/canonical.cjs.map +1 -1
  10. package/dist/canonical.d.cts +1 -1
  11. package/dist/canonical.d.ts +1 -1
  12. package/dist/canonical.js +48 -2
  13. package/dist/canonical.js.map +1 -1
  14. package/dist/cli.cjs +260 -31
  15. package/dist/cli.cjs.map +1 -1
  16. package/dist/cli.js +260 -31
  17. package/dist/cli.js.map +1 -1
  18. package/dist/client.cjs +11 -6
  19. package/dist/client.cjs.map +1 -1
  20. package/dist/client.d.cts +38 -31
  21. package/dist/client.d.ts +38 -31
  22. package/dist/client.js +11 -7
  23. package/dist/client.js.map +1 -1
  24. package/dist/compiler.cjs +513 -23
  25. package/dist/compiler.cjs.map +1 -1
  26. package/dist/compiler.d.cts +39 -3
  27. package/dist/compiler.d.ts +39 -3
  28. package/dist/compiler.js +510 -24
  29. package/dist/compiler.js.map +1 -1
  30. package/dist/{constants-C6EG6Wq7.d.cts → constants-Dou1RkTo.d.cts} +7 -2
  31. package/dist/{constants-C6EG6Wq7.d.ts → constants-Dou1RkTo.d.ts} +7 -2
  32. package/dist/dynamic-input.d.cts +1 -1
  33. package/dist/dynamic-input.d.ts +1 -1
  34. package/dist/index.cjs +461 -140
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +34 -4
  37. package/dist/index.d.ts +34 -4
  38. package/dist/index.js +460 -141
  39. package/dist/index.js.map +1 -1
  40. package/dist/ir.cjs +55 -4
  41. package/dist/ir.cjs.map +1 -1
  42. package/dist/ir.d.cts +1 -1
  43. package/dist/ir.d.ts +1 -1
  44. package/dist/ir.js +55 -4
  45. package/dist/ir.js.map +1 -1
  46. package/dist/predicate-v2.cjs +55 -4
  47. package/dist/predicate-v2.cjs.map +1 -1
  48. package/dist/predicate-v2.d.cts +1 -1
  49. package/dist/predicate-v2.d.ts +1 -1
  50. package/dist/predicate-v2.js +55 -4
  51. package/dist/predicate-v2.js.map +1 -1
  52. package/dist/sdl.cjs +60 -4
  53. package/dist/sdl.cjs.map +1 -1
  54. package/dist/sdl.d.cts +3 -1
  55. package/dist/sdl.d.ts +3 -1
  56. package/dist/sdl.js +60 -4
  57. package/dist/sdl.js.map +1 -1
  58. package/package.json +1 -1
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` });
@@ -1199,6 +1246,11 @@ var CELL_TYPENAMES = {
1199
1246
  function cellsTypename(typename) {
1200
1247
  return `${typename}Cells`;
1201
1248
  }
1249
+
1250
+ // src/client/sql.ts
1251
+ var BUILTIN_SQL_READ_HASH = "sha256:a50c477c952a5e0fe68ed158a4530e4aab573c09bcbb1a8ac454dc88a39a6258";
1252
+
1253
+ // src/ir/index.ts
1202
1254
  var LEGACY_IR_VERSION = 1;
1203
1255
  var GUARDED_IR_VERSION = 2;
1204
1256
  var COMPOSED_IR_VERSION = 3;
@@ -1266,7 +1318,7 @@ var limitIrSchema = zod.z.object({
1266
1318
  variable: zod.z.string().optional(),
1267
1319
  value: zod.z.number().int().positive().optional(),
1268
1320
  default: zod.z.number().int().positive(),
1269
- max: zod.z.number().int().positive()
1321
+ max: zod.z.number().int().positive().max(MAX_PERSISTED_READ_ROWS)
1270
1322
  });
1271
1323
  var selectionIrSchema = zod.z.lazy(
1272
1324
  () => zod.z.object({
@@ -1511,7 +1563,8 @@ var compiledOperationSchema = zod.z.object({
1511
1563
  }).superRefine((operation, ctx) => {
1512
1564
  if (operation.language === "sql") {
1513
1565
  const validPlan = operation.sqlQuery ? !operation.sql && operation.irVersion === RUNTIME_SQL_IR_VERSION : !!operation.sql && operation.irVersion === SQL_IR_VERSION;
1514
- if (!validPlan || operation.kind !== "query" || operation.roots.length !== 0 || !operation.requires?.capability) {
1566
+ const builtin = operation.name === "BuiltinSqlRead" && operation.opHash === BUILTIN_SQL_READ_HASH && operation.requires === null;
1567
+ if (!validPlan || operation.kind !== "query" || operation.roots.length !== 0 || !builtin && !operation.requires?.capability) {
1515
1568
  ctx.addIssue({ code: "custom", message: "SQL operations require a query-only v4 plan or v5 runtime contract, capability, and no GraphQL roots" });
1516
1569
  }
1517
1570
  } else if (operation.sql || operation.sqlQuery || operation.roots.length === 0) {
@@ -1792,6 +1845,9 @@ function generateSdl(canonical, options = {}) {
1792
1845
  blocks.push(
1793
1846
  '"""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
1847
  );
1848
+ if (!options.omitReadBudgetDirective) blocks.push(
1849
+ '"""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'
1850
+ );
1795
1851
  blocks.push("directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT");
1796
1852
  blocks.push(
1797
1853
  '"""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'