@sequenceholdings/orm 2.1.1 → 2.2.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 (68) hide show
  1. package/README.md +3 -1
  2. package/dist/authoring.cjs +284 -99
  3. package/dist/authoring.cjs.map +1 -1
  4. package/dist/authoring.d.cts +31 -8
  5. package/dist/authoring.d.ts +31 -8
  6. package/dist/authoring.js +282 -100
  7. package/dist/authoring.js.map +1 -1
  8. package/dist/canonical.cjs +51 -3
  9. package/dist/canonical.cjs.map +1 -1
  10. package/dist/canonical.d.cts +838 -12
  11. package/dist/canonical.d.ts +838 -12
  12. package/dist/canonical.js +47 -4
  13. package/dist/canonical.js.map +1 -1
  14. package/dist/cli.cjs +5838 -4197
  15. package/dist/cli.cjs.map +1 -1
  16. package/dist/cli.js +5838 -4197
  17. package/dist/cli.js.map +1 -1
  18. package/dist/client.cjs +49 -32
  19. package/dist/client.cjs.map +1 -1
  20. package/dist/client.d.cts +49 -6
  21. package/dist/client.d.ts +49 -6
  22. package/dist/client.js +49 -32
  23. package/dist/client.js.map +1 -1
  24. package/dist/compiler.cjs +1237 -263
  25. package/dist/compiler.cjs.map +1 -1
  26. package/dist/compiler.d.cts +57 -3
  27. package/dist/compiler.d.ts +57 -3
  28. package/dist/compiler.js +1230 -264
  29. package/dist/compiler.js.map +1 -1
  30. package/dist/{constants-YoFGjIBM.d.cts → constants-C6EG6Wq7.d.cts} +1 -1
  31. package/dist/{constants-YoFGjIBM.d.ts → constants-C6EG6Wq7.d.ts} +1 -1
  32. package/dist/definition-DjfC7Lll.d.cts +91 -0
  33. package/dist/definition-DjfC7Lll.d.ts +91 -0
  34. package/dist/dynamic-input.cjs +2 -1
  35. package/dist/dynamic-input.cjs.map +1 -1
  36. package/dist/dynamic-input.d.cts +9 -2
  37. package/dist/dynamic-input.d.ts +9 -2
  38. package/dist/dynamic-input.js +2 -1
  39. package/dist/dynamic-input.js.map +1 -1
  40. package/dist/index.cjs +1094 -321
  41. package/dist/index.cjs.map +1 -1
  42. package/dist/index.d.cts +479 -19
  43. package/dist/index.d.ts +479 -19
  44. package/dist/index.js +1083 -322
  45. package/dist/index.js.map +1 -1
  46. package/dist/ir.cjs +84 -10
  47. package/dist/ir.cjs.map +1 -1
  48. package/dist/ir.d.cts +138 -13
  49. package/dist/ir.d.ts +138 -13
  50. package/dist/ir.js +81 -11
  51. package/dist/ir.js.map +1 -1
  52. package/dist/predicate-v2.cjs +78 -9
  53. package/dist/predicate-v2.cjs.map +1 -1
  54. package/dist/predicate-v2.d.cts +1 -1
  55. package/dist/predicate-v2.d.ts +1 -1
  56. package/dist/predicate-v2.js +78 -9
  57. package/dist/predicate-v2.js.map +1 -1
  58. package/dist/sdl.cjs +156 -21
  59. package/dist/sdl.cjs.map +1 -1
  60. package/dist/sdl.d.cts +8 -1
  61. package/dist/sdl.d.ts +8 -1
  62. package/dist/sdl.js +156 -21
  63. package/dist/sdl.js.map +1 -1
  64. package/package.json +5 -4
  65. package/src/codegen-gql/server-fns.cjs +2 -2
  66. package/templates/orm-namespace/AGENTS.md +10 -0
  67. package/templates/orm-namespace/CLAUDE.md +1 -84
  68. package/templates/orm-namespace/package.json +1 -1
package/dist/index.js CHANGED
@@ -163,8 +163,8 @@ var COLUMN_IDENTIFIER_PATTERN = /^_?[a-z][a-z0-9_]*$/;
163
163
  var MAX_IDENTIFIER_LENGTH = 63;
164
164
  var CAPABILITY_KEY_PATTERN = /^(?:org\/|app\/[a-z][a-z0-9-]{0,63}\/)?[a-z0-9-]{1,64}$/;
165
165
  var CLAIM_KEY_PATTERN = /^[a-z][a-z0-9_]*$/;
166
- var QUALIFIED_TABLE_PATTERN = /^[a-z][a-z0-9_]*\.[a-z][a-z0-9_]*$/;
167
- var SYNCED_SOURCE_PATTERN = /^gold\.[a-z][a-z0-9_]*$/;
166
+ var QUALIFIED_TABLE_PATTERN = /^[a-z][a-z0-9_]{0,62}\.[a-z][a-z0-9_]{0,62}$/;
167
+ var SYNCED_SOURCE_PATTERN = QUALIFIED_TABLE_PATTERN;
168
168
  var ORM_SCHEMA_PREFIX = "orm_";
169
169
  var CONSUMER_ROLE_SUFFIX = "_consumer";
170
170
  var ormSchemaName = (namespace) => `${ORM_SCHEMA_PREFIX}${namespace}`;
@@ -265,6 +265,9 @@ function registerNamespaceConfig(value) {
265
265
  // src/authoring/table.ts
266
266
  var TABLE_BRAND = "seq-table";
267
267
  var LINK_BRAND = "seq-link";
268
+ function objectRef(namespace, table) {
269
+ return { kind: "seq-external-object", namespace, table };
270
+ }
268
271
  function toOne(target, options) {
269
272
  return {
270
273
  kind: LINK_BRAND,
@@ -318,51 +321,51 @@ function assertIdentifier({ value, what, file, pattern = IDENTIFIER_PATTERN }) {
318
321
  );
319
322
  }
320
323
  }
321
- function defineTable(name, columns, config = {}) {
324
+ function defineTable(name2, columns, config = {}) {
322
325
  const file = activeAuthoringContext()?.currentFile;
323
- assertIdentifier({ value: name, what: "table name", file });
326
+ assertIdentifier({ value: name2, what: "table name", file });
324
327
  const entries = Object.entries(columns);
325
328
  if (entries.length === 0) {
326
- throw new OrmDefinitionError(`table "${name}" declares no columns`, file);
329
+ throw new OrmDefinitionError(`table "${name2}" declares no columns`, file);
327
330
  }
328
331
  const seenColumnNames = /* @__PURE__ */ new Map();
329
332
  for (const [propertyName, builder] of entries) {
330
333
  if (!isColumnBuilder(builder)) {
331
334
  throw new OrmDefinitionError(
332
- `table "${name}": column "${propertyName}" is not a column builder \u2014 use the t.* factories (t.uuid(), t.text(), \u2026)`,
335
+ `table "${name2}": column "${propertyName}" is not a column builder \u2014 use the t.* factories (t.uuid(), t.text(), \u2026)`,
333
336
  file
334
337
  );
335
338
  }
336
339
  const columnName = builder.columnNameFor(propertyName);
337
- assertIdentifier({ value: columnName, what: `table "${name}": column "${propertyName}" column name`, file, pattern: COLUMN_IDENTIFIER_PATTERN });
340
+ assertIdentifier({ value: columnName, what: `table "${name2}": column "${propertyName}" column name`, file, pattern: COLUMN_IDENTIFIER_PATTERN });
338
341
  if (config.materializes === void 0 && (propertyName === CELLS_FIELD || Object.values(CELL_PART_SUFFIX).some((suffix) => columnName.endsWith(suffix) || propertyName.endsWith(suffix)))) {
339
342
  throw new OrmDefinitionError(
340
- `table "${name}": "${propertyName}" collides with the reserved cell-metadata names ('${CELLS_FIELD}', or a ${Object.values(CELL_PART_SUFFIX).join("/")} suffix)`,
343
+ `table "${name2}": "${propertyName}" collides with the reserved cell-metadata names ('${CELLS_FIELD}', or a ${Object.values(CELL_PART_SUFFIX).join("/")} suffix)`,
341
344
  file
342
345
  );
343
346
  }
344
347
  const existing = seenColumnNames.get(columnName);
345
348
  if (existing !== void 0) {
346
349
  throw new OrmDefinitionError(
347
- `table "${name}": columns "${existing}" and "${propertyName}" both map to Postgres column "${columnName}"`,
350
+ `table "${name2}": columns "${existing}" and "${propertyName}" both map to Postgres column "${columnName}"`,
348
351
  file
349
352
  );
350
353
  }
351
354
  seenColumnNames.set(columnName, propertyName);
352
355
  }
353
- const table = { kind: TABLE_BRAND, tableName: name, columns, config, source: void 0, file };
356
+ const table = { kind: TABLE_BRAND, tableName: name2, columns, config, source: void 0, file };
354
357
  registerTable(table);
355
358
  return table;
356
359
  }
357
- function defineSyncedTable(name, columnsOrConfig, maybeConfig) {
360
+ function defineSyncedTable(name2, columnsOrConfig, maybeConfig) {
358
361
  const file = activeAuthoringContext()?.currentFile;
359
- assertIdentifier({ value: name, what: "table name", file });
362
+ assertIdentifier({ value: name2, what: "table name", file });
360
363
  const isTyped = maybeConfig !== void 0;
361
364
  const columns = isTyped ? columnsOrConfig : {};
362
365
  const config = isTyped ? maybeConfig : columnsOrConfig;
363
366
  if (!SYNCED_SOURCE_PATTERN.test(config.source)) {
364
367
  throw new OrmDefinitionError(
365
- `synced table "${name}": source "${config.source}" must match ${SYNCED_SOURCE_PATTERN} (gold layer only)`,
368
+ `synced table "${name2}": source "${config.source}" must be a qualified lowercase schema.table identifier`,
366
369
  file
367
370
  );
368
371
  }
@@ -372,21 +375,21 @@ function defineSyncedTable(name, columnsOrConfig, maybeConfig) {
372
375
  for (const [propertyName, builder] of entries) {
373
376
  if (!isColumnBuilder(builder)) {
374
377
  throw new OrmDefinitionError(
375
- `synced table "${name}": column "${propertyName}" is not a column builder \u2014 use the t.* factories (t.uuid(), t.text(), \u2026)`,
378
+ `synced table "${name2}": column "${propertyName}" is not a column builder \u2014 use the t.* factories (t.uuid(), t.text(), \u2026)`,
376
379
  file
377
380
  );
378
381
  }
379
382
  const columnName = builder.columnNameFor(propertyName);
380
383
  assertIdentifier({
381
384
  value: columnName,
382
- what: `synced table "${name}": column "${propertyName}" column name`,
385
+ what: `synced table "${name2}": column "${propertyName}" column name`,
383
386
  file,
384
387
  pattern: COLUMN_IDENTIFIER_PATTERN
385
388
  });
386
389
  const existing = seenColumnNames.get(columnName);
387
390
  if (existing !== void 0) {
388
391
  throw new OrmDefinitionError(
389
- `synced table "${name}": columns "${existing}" and "${propertyName}" both map to Postgres column "${columnName}"`,
392
+ `synced table "${name2}": columns "${existing}" and "${propertyName}" both map to Postgres column "${columnName}"`,
390
393
  file
391
394
  );
392
395
  }
@@ -397,13 +400,13 @@ function defineSyncedTable(name, columnsOrConfig, maybeConfig) {
397
400
  const hasConfigPk = config.primaryKey !== void 0 && config.primaryKey.length > 0;
398
401
  if (columnLevelPk.length === 0 && !hasConfigPk) {
399
402
  throw new OrmDefinitionError(
400
- `synced table "${name}" declares columns but no primary key \u2014 use .primaryKey() or config.primaryKey`,
403
+ `synced table "${name2}" declares columns but no primary key \u2014 use .primaryKey() or config.primaryKey`,
401
404
  file
402
405
  );
403
406
  }
404
407
  if (columnLevelPk.length > 0 && hasConfigPk) {
405
408
  throw new OrmDefinitionError(
406
- `synced table "${name}": declare the primary key either with .primaryKey() on columns or with config.primaryKey \u2014 not both`,
409
+ `synced table "${name2}": declare the primary key either with .primaryKey() on columns or with config.primaryKey \u2014 not both`,
407
410
  file
408
411
  );
409
412
  }
@@ -415,7 +418,7 @@ function defineSyncedTable(name, columnsOrConfig, maybeConfig) {
415
418
  if (config.policies !== void 0) tableConfig.policies = { read: config.policies.read };
416
419
  const table = {
417
420
  kind: TABLE_BRAND,
418
- tableName: name,
421
+ tableName: name2,
419
422
  columns,
420
423
  config: tableConfig,
421
424
  source: config.source,
@@ -424,26 +427,26 @@ function defineSyncedTable(name, columnsOrConfig, maybeConfig) {
424
427
  registerTable(table);
425
428
  return table;
426
429
  }
427
- function defineEnum(name, values) {
430
+ function defineEnum(name2, values) {
428
431
  const file = activeAuthoringContext()?.currentFile;
429
- assertIdentifier({ value: name, what: "enum name", file });
432
+ assertIdentifier({ value: name2, what: "enum name", file });
430
433
  if (values.length === 0 || values.length > 100) {
431
- throw new OrmDefinitionError(`enum "${name}" must declare between 1 and 100 values`, file);
434
+ throw new OrmDefinitionError(`enum "${name2}" must declare between 1 and 100 values`, file);
432
435
  }
433
436
  const seen = /* @__PURE__ */ new Set();
434
437
  for (const value of values) {
435
438
  if (value.length === 0 || value.length > MAX_IDENTIFIER_LENGTH) {
436
439
  throw new OrmDefinitionError(
437
- `enum "${name}": value ${JSON.stringify(value)} must be 1-${MAX_IDENTIFIER_LENGTH} characters`,
440
+ `enum "${name2}": value ${JSON.stringify(value)} must be 1-${MAX_IDENTIFIER_LENGTH} characters`,
438
441
  file
439
442
  );
440
443
  }
441
444
  if (seen.has(value)) {
442
- throw new OrmDefinitionError(`enum "${name}" declares duplicate value "${value}"`, file);
445
+ throw new OrmDefinitionError(`enum "${name2}" declares duplicate value "${value}"`, file);
443
446
  }
444
447
  seen.add(value);
445
448
  }
446
- const ref = { kind: ENUM_BRAND, name, values: [...values] };
449
+ const ref = { kind: ENUM_BRAND, name: name2, values: [...values] };
447
450
  registerEnum(ref);
448
451
  return ref;
449
452
  }
@@ -451,52 +454,52 @@ var VIEW_BRAND = "seq-view";
451
454
  function isSeqView(value) {
452
455
  return typeof value === "object" && value !== null && value.kind === VIEW_BRAND;
453
456
  }
454
- function defineView(name, columns, config) {
457
+ function defineView(name2, columns, config) {
455
458
  const file = activeAuthoringContext()?.currentFile;
456
- if (!IDENTIFIER_PATTERN.test(name) || name.length > MAX_IDENTIFIER_LENGTH) {
459
+ if (!IDENTIFIER_PATTERN.test(name2) || name2.length > MAX_IDENTIFIER_LENGTH) {
457
460
  throw new OrmDefinitionError(
458
- `view name "${name}" must match ${IDENTIFIER_PATTERN} and be at most ${MAX_IDENTIFIER_LENGTH} characters`,
461
+ `view name "${name2}" must match ${IDENTIFIER_PATTERN} and be at most ${MAX_IDENTIFIER_LENGTH} characters`,
459
462
  file
460
463
  );
461
464
  }
462
465
  const entries = Object.entries(columns);
463
- if (entries.length === 0) throw new OrmDefinitionError(`view "${name}" declares no columns`, file);
466
+ if (entries.length === 0) throw new OrmDefinitionError(`view "${name2}" declares no columns`, file);
464
467
  const seenColumnNames = /* @__PURE__ */ new Map();
465
468
  for (const [propertyName, builder] of entries) {
466
469
  if (!isColumnBuilder(builder)) {
467
470
  throw new OrmDefinitionError(
468
- `view "${name}": column "${propertyName}" is not a column builder \u2014 use the t.* factories`,
471
+ `view "${name2}": column "${propertyName}" is not a column builder \u2014 use the t.* factories`,
469
472
  file
470
473
  );
471
474
  }
472
475
  const columnName = builder.columnNameFor(propertyName);
473
476
  if (!COLUMN_IDENTIFIER_PATTERN.test(columnName) || columnName.length > MAX_IDENTIFIER_LENGTH) {
474
- throw new OrmDefinitionError(`view "${name}": column "${propertyName}" has invalid column name "${columnName}"`, file);
477
+ throw new OrmDefinitionError(`view "${name2}": column "${propertyName}" has invalid column name "${columnName}"`, file);
475
478
  }
476
479
  const existing = seenColumnNames.get(columnName);
477
480
  if (existing !== void 0) {
478
481
  throw new OrmDefinitionError(
479
- `view "${name}": columns "${existing}" and "${propertyName}" both map to Postgres column "${columnName}"`,
482
+ `view "${name2}": columns "${existing}" and "${propertyName}" both map to Postgres column "${columnName}"`,
480
483
  file
481
484
  );
482
485
  }
483
486
  seenColumnNames.set(columnName, propertyName);
484
487
  }
485
- const view = { kind: VIEW_BRAND, viewName: name, columns, config, file };
488
+ const view = { kind: VIEW_BRAND, viewName: name2, columns, config, file };
486
489
  registerView(view);
487
490
  return view;
488
491
  }
489
492
  var QUERY_COLUMN_FACTORIES = {
490
- uuid: (name) => uuid(name),
491
- text: (name) => text(name),
492
- integer: (name) => integer(name),
493
- bigint: (name) => bigint(name, { mode: "bigint" }),
494
- numeric: (name) => numeric(name),
495
- double: (name) => doublePrecision(name),
496
- boolean: (name) => boolean(name),
497
- timestamptz: (name) => timestamp(name, { withTimezone: true }),
498
- date: (name) => date(name),
499
- jsonb: (name) => jsonb(name)
493
+ uuid: (name2) => uuid(name2),
494
+ text: (name2) => text(name2),
495
+ integer: (name2) => integer(name2),
496
+ bigint: (name2) => bigint(name2, { mode: "bigint" }),
497
+ numeric: (name2) => numeric(name2),
498
+ double: (name2) => doublePrecision(name2),
499
+ boolean: (name2) => boolean(name2),
500
+ timestamptz: (name2) => timestamp(name2, { withTimezone: true }),
501
+ date: (name2) => date(name2),
502
+ jsonb: (name2) => jsonb(name2)
500
503
  };
501
504
  function compileViewQueries(input) {
502
505
  const schemaName = `orm_${input.namespace}`;
@@ -552,9 +555,9 @@ function compileViewQueries(input) {
552
555
  }
553
556
  const handle = handles.get(resolved);
554
557
  if (!handle) {
555
- const name = isSeqTable(resolved) ? resolved.tableName : resolved.viewName;
558
+ const name2 = isSeqTable(resolved) ? resolved.tableName : resolved.viewName;
556
559
  throw new OrmDefinitionError(
557
- `view "${authored.viewName}" references relation "${name}" which is not part of this namespace`,
560
+ `view "${authored.viewName}" references relation "${name2}" which is not part of this namespace`,
558
561
  authored.file
559
562
  );
560
563
  }
@@ -745,8 +748,8 @@ function overlayWinsUnion(input) {
745
748
  // src/authoring/cow-mutations.ts
746
749
  function overrideRowMutation(input) {
747
750
  const { overlay, synced, pk } = input;
748
- const name = input.name ?? `override_${overlay.tableName}`;
749
- assertMutationName(name, "overrideRowMutation");
751
+ const name2 = input.name ?? `override_${overlay.tableName}`;
752
+ assertMutationName(name2, "overrideRowMutation");
750
753
  assertOverlayPairPrimaryKey({ overlay, synced, pk, helper: "overrideRowMutation" });
751
754
  const sharedProperties = sharedNonPkProperties({ overlay, synced, pk });
752
755
  const setProperties = resolveSetProperties({
@@ -765,7 +768,7 @@ function overrideRowMutation(input) {
765
768
  });
766
769
  return {
767
770
  kind: "override",
768
- name,
771
+ name: name2,
769
772
  synced: synced.tableName,
770
773
  pk,
771
774
  copy: [pk, ...sharedProperties],
@@ -774,23 +777,23 @@ function overrideRowMutation(input) {
774
777
  }
775
778
  function revertOverlayMutation(input) {
776
779
  const { overlay, synced, pk } = input;
777
- const name = input.name ?? `revert_${overlay.tableName}`;
778
- assertMutationName(name, "revertOverlayMutation");
780
+ const name2 = input.name ?? `revert_${overlay.tableName}`;
781
+ assertMutationName(name2, "revertOverlayMutation");
779
782
  assertOverlayPairPrimaryKey({ overlay, synced, pk, helper: "revertOverlayMutation" });
780
783
  assertMatchingColumns({ overlay, synced, properties: [pk], helper: "revertOverlayMutation" });
781
784
  return {
782
785
  kind: "revert",
783
- name,
786
+ name: name2,
784
787
  synced: synced.tableName,
785
788
  pk,
786
789
  copy: [],
787
790
  set: []
788
791
  };
789
792
  }
790
- function assertMutationName(name, helper) {
791
- if (!IDENTIFIER_PATTERN.test(name) || name.length > MAX_IDENTIFIER_LENGTH) {
793
+ function assertMutationName(name2, helper) {
794
+ if (!IDENTIFIER_PATTERN.test(name2) || name2.length > MAX_IDENTIFIER_LENGTH) {
792
795
  throw new OrmDefinitionError(
793
- `${helper}: mutation name "${name}" must match ${IDENTIFIER_PATTERN} and be at most ${MAX_IDENTIFIER_LENGTH} characters`
796
+ `${helper}: mutation name "${name2}" must match ${IDENTIFIER_PATTERN} and be at most ${MAX_IDENTIFIER_LENGTH} characters`
794
797
  );
795
798
  }
796
799
  }
@@ -916,17 +919,35 @@ function scalarColumnType(table, property, helper) {
916
919
  }
917
920
  return type;
918
921
  }
922
+ var objectRef2 = z.string().max(255).regex(/^[a-z][a-z0-9_]{0,40}\/[A-Za-z_][A-Za-z0-9_]*$/, "Expected an explicit namespace/object reference (no wildcards)");
923
+ var functionRef = z.string().max(255).regex(/^[a-z][a-z0-9-]*$/, "Expected a function slug");
924
+ var refs = (schema) => z.array(schema).max(256).refine(
925
+ (values) => new Set(values).size === values.length,
926
+ "Duplicate dependency reference"
927
+ ).default([]);
928
+ var ontologyContractSchema = z.strictObject({
929
+ version: z.literal(1),
930
+ read: refs(objectRef2),
931
+ write: refs(objectRef2),
932
+ produce: refs(objectRef2),
933
+ invoke: refs(functionRef)
934
+ }).refine((contract) => JSON.stringify(contract).length <= 4096, "Ontology contract exceeds the 4 KiB signed-context budget");
935
+ function readOntologyContract(manifest) {
936
+ if (!manifest || typeof manifest !== "object" || !("ontology" in manifest) || manifest.ontology === void 0) return void 0;
937
+ return ontologyContractSchema.parse(manifest.ontology);
938
+ }
919
939
 
920
940
  // src/compiler/sql.ts
921
941
  var CLAIMS_SETTING = "request.jwt.claims";
922
942
  var CAPABILITIES_CLAIM_KEY = "capabilities";
923
943
  var ROLES_CLAIM_KEY = "roles";
924
- var quoteIdentifier = (name) => `"${name.replaceAll('"', '""')}"`;
944
+ var quoteIdentifier = (name2) => `"${name2.replaceAll('"', '""')}"`;
925
945
  var quoteLiteral = (value) => `'${value.replaceAll("'", "''")}'`;
926
946
  var CLAIMS_SOURCE = `nullif(current_setting('${CLAIMS_SETTING}', true), '')::jsonb`;
927
947
  var claimExpression = (key) => `(${CLAIMS_SOURCE} ->> ${quoteLiteral(key)})`;
928
- var capabilityExpression = (key) => `coalesce(${CLAIMS_SOURCE} -> '${CAPABILITIES_CLAIM_KEY}' ? ${quoteLiteral(key)}, false)`;
929
- var roleExpression = (key) => `coalesce(${CLAIMS_SOURCE} -> '${ROLES_CLAIM_KEY}' ? ${quoteLiteral(key)}, false)`;
948
+ var scopedClaimsSource = (namespace) => namespace ? `(CASE WHEN ${CLAIMS_SOURCE} ? 'namespaces' THEN ${CLAIMS_SOURCE} -> 'namespaces' -> ${quoteLiteral(namespace)} ELSE ${CLAIMS_SOURCE} END)` : CLAIMS_SOURCE;
949
+ var capabilityExpression = (key, namespace) => `coalesce(${scopedClaimsSource(namespace)} -> '${CAPABILITIES_CLAIM_KEY}' ? ${quoteLiteral(key)}, false)`;
950
+ var roleExpression = (key, namespace) => `coalesce(${scopedClaimsSource(namespace)} -> '${ROLES_CLAIM_KEY}' ? ${quoteLiteral(key)}, false)`;
930
951
 
931
952
  // src/checks/compile.ts
932
953
  function tokenize(source) {
@@ -1259,8 +1280,8 @@ function validateResolvedView({ view, tables, views = [] }) {
1259
1280
  validateRules(scope);
1260
1281
  validateViewCells(scope);
1261
1282
  if (resolved.materialized) validateMaterialized({ scope, tableByName, views });
1262
- for (const name of resolved.deletedBy) {
1263
- if (scope.sourceByName.get(name)?.kind !== "manual") fail(`deletedBy '${name}' must be the manual source`);
1283
+ for (const name2 of resolved.deletedBy) {
1284
+ if (scope.sourceByName.get(name2)?.kind !== "manual") fail(`deletedBy '${name2}' must be the manual source`);
1264
1285
  }
1265
1286
  return errors;
1266
1287
  }
@@ -1357,7 +1378,7 @@ function validateViewCells({ view, dataColumns, pkColumn, fail }) {
1357
1378
  if (column.type !== VIEW_CELL_TYPES[column.cell.part]) fail(`cell column '${column.name}' must be ${VIEW_CELL_TYPES[column.cell.part]}`);
1358
1379
  expected.delete(column.name);
1359
1380
  }
1360
- for (const name of expected.keys()) fail(`missing cell column '${name}'`);
1381
+ for (const name2 of expected.keys()) fail(`missing cell column '${name2}'`);
1361
1382
  }
1362
1383
  var columnSignature = (columns) => JSON.stringify(columns.map((column) => [column.name, column.columnName, column.type]));
1363
1384
  function validateMaterialized({ scope, tableByName, views }) {
@@ -1448,6 +1469,8 @@ var canonicalLinkSchema = z.object({
1448
1469
  kind: z.enum(["toOne", "toMany", "toPlatformUser"]),
1449
1470
  /** Target table name (namespace-local). Absent for toPlatformUser. */
1450
1471
  target: identifier2.optional(),
1472
+ /** Owning namespace of an imported target; omitted for local links. */
1473
+ namespace: identifier2.max(41).optional(),
1451
1474
  /** FK column on the owning side (toOne/toPlatformUser: on this table; toMany: on the target). */
1452
1475
  on: columnIdentifier,
1453
1476
  /** Referenced column on the target (default: target's PK / platform user `sub`). */
@@ -1706,11 +1729,12 @@ var canonicalForeignKeySchema = z.object({
1706
1729
  }).strict();
1707
1730
  var canonicalTableSchema = z.object({
1708
1731
  table: identifier2,
1732
+ displayName: z.string().trim().min(1).max(120).optional(),
1709
1733
  description: z.string().max(2e3).optional(),
1710
1734
  /** Table-level rename hint (new in v2). */
1711
1735
  renamedFrom: identifier2.optional(),
1712
- /** Synced/reflected read-only tables (`source: gold.*`) — v1 semantics. */
1713
- source: z.string().regex(/^gold\.[a-z][a-z0-9_]*$/).optional(),
1736
+ /** Synced/reflected read-only tables (`source: schema.table`) — v1 semantics. */
1737
+ source: z.string().regex(QUALIFIED_TABLE_PATTERN).optional(),
1714
1738
  columns: z.array(canonicalColumnSchema).default([]),
1715
1739
  primaryKey: z.array(columnIdentifier).min(1).max(8).optional(),
1716
1740
  links: z.array(canonicalLinkSchema).default([]),
@@ -1863,7 +1887,9 @@ function validateCellMetadata(table, index3, ctx) {
1863
1887
  }
1864
1888
  }
1865
1889
  }
1866
- var canonicalDefinitionSchema = z.object({
1890
+ var exportGateSchema = z.union([z.literal(true), z.object({ capability: z.string().min(1) }).strict(), z.object({ role: z.string().min(1) }).strict()]);
1891
+ var relationExportSchema = z.object({ read: exportGateSchema, write: exportGateSchema.optional() }).strict();
1892
+ var localDefinitionSchema = z.object({
1867
1893
  definition_format: z.literal(CANONICAL_FORMAT),
1868
1894
  namespace: identifier2.max(41),
1869
1895
  description: z.string().max(2e3).optional(),
@@ -1871,6 +1897,8 @@ var canonicalDefinitionSchema = z.object({
1871
1897
  tables: z.array(canonicalTableSchema).min(0).max(500),
1872
1898
  /** Optional to preserve byte-identical hashes for pre-view canonical v2 documents. */
1873
1899
  views: z.array(canonicalViewSchema).max(500).optional(),
1900
+ /** Target-owned cross-namespace access contract, using existing namespace grants. */
1901
+ exports: z.record(identifier2, relationExportSchema).optional(),
1874
1902
  /** Verbatim custom-roles grammar (@sequenceholdings/custom-roles-manifest). */
1875
1903
  capabilities: z.object({
1876
1904
  roles: z.unknown().optional(),
@@ -1897,7 +1925,16 @@ var canonicalDefinitionSchema = z.object({
1897
1925
  }
1898
1926
  }
1899
1927
  const fkTables = new Map(definition.tables.map((table) => [table.table, table]));
1928
+ const relations = /* @__PURE__ */ new Set([...fkTables.keys(), ...(definition.views ?? []).map((view) => view.view)]);
1929
+ for (const name2 of Object.keys(definition.exports ?? {})) {
1930
+ if (!relations.has(name2)) ctx.addIssue({ code: "custom", path: ["exports", name2], message: `export '${name2}' is not a local object` });
1931
+ }
1900
1932
  for (const [tableIndex, table] of definition.tables.entries()) {
1933
+ for (const [linkIndex, link] of table.links.entries()) {
1934
+ if (link.enforce && link.namespace !== void 0 && link.namespace !== definition.namespace) {
1935
+ ctx.addIssue({ code: "custom", path: ["tables", tableIndex, "links", linkIndex], message: "physical foreign keys require a local target; use an ORM link without enforce" });
1936
+ }
1937
+ }
1901
1938
  const names = /* @__PURE__ */ new Set([
1902
1939
  ...table.primaryKey?.length ? [`${table.table}_pkey`] : [],
1903
1940
  ...table.columns.filter((column) => column.unique && !(table.primaryKey?.length === 1 && table.primaryKey[0] === column.columnName)).map((column) => `${table.table}_${column.columnName}_unique`),
@@ -1934,14 +1971,14 @@ var canonicalDefinitionSchema = z.object({
1934
1971
  }
1935
1972
  if (fk.columns.length !== fk.references.length) fail("foreign key columns and references must have the same number of columns");
1936
1973
  if (new Set(fk.columns).size !== fk.columns.length || new Set(fk.references).size !== fk.references.length) fail("foreign key columns must not repeat");
1937
- for (const [position, name] of fk.columns.entries()) {
1938
- const sourceColumn = table.columns.find((column) => column.columnName === name);
1974
+ for (const [position, name2] of fk.columns.entries()) {
1975
+ const sourceColumn = table.columns.find((column) => column.columnName === name2);
1939
1976
  const targetColumn = target.columns.find((column) => column.columnName === fk.references[position]);
1940
1977
  if (!sourceColumn || !targetColumn) fail("foreign key references an unknown column");
1941
1978
  else if (JSON.stringify(sourceColumn.type) !== JSON.stringify(targetColumn.type)) fail("foreign key column types must match");
1942
1979
  }
1943
1980
  if (fk.onDelete === "set null" || fk.onUpdate === "set null") {
1944
- if (fk.columns.some((name) => table.columns.find((column) => column.columnName === name)?.nullable === false || table.primaryKey?.includes(name))) fail("SET NULL requires nullable source columns");
1981
+ if (fk.columns.some((name2) => table.columns.find((column) => column.columnName === name2)?.nullable === false || table.primaryKey?.includes(name2))) fail("SET NULL requires nullable source columns");
1945
1982
  }
1946
1983
  const uniqueKeys = [target.primaryKey ?? [], ...target.indexes.filter((index4) => index4.unique).map((index4) => index4.columns), ...target.columns.filter((column) => column.unique).map((column) => [column.columnName])];
1947
1984
  if (!uniqueKeys.some((key) => key.length === fk.references.length && key.every((column) => fk.references.includes(column)))) fail("foreign key target columns must form a unique key");
@@ -2046,27 +2083,31 @@ var canonicalDefinitionSchema = z.object({
2046
2083
  const visiting = /* @__PURE__ */ new Set();
2047
2084
  const visited = /* @__PURE__ */ new Set();
2048
2085
  let cycleReported = false;
2049
- const visit = (name, path) => {
2050
- if (visited.has(name) || cycleReported) return;
2051
- if (visiting.has(name)) {
2086
+ const visit = (name2, path) => {
2087
+ if (visited.has(name2) || cycleReported) return;
2088
+ if (visiting.has(name2)) {
2052
2089
  cycleReported = true;
2053
2090
  ctx.addIssue({
2054
2091
  code: "custom",
2055
2092
  path: ["views"],
2056
- message: `view dependencies form a cycle: ${[...path, name].join(" -> ")}`
2093
+ message: `view dependencies form a cycle: ${[...path, name2].join(" -> ")}`
2057
2094
  });
2058
2095
  return;
2059
2096
  }
2060
- visiting.add(name);
2061
- const view = viewByName.get(name);
2097
+ visiting.add(name2);
2098
+ const view = viewByName.get(name2);
2062
2099
  for (const dependency of view?.dependencies ?? []) {
2063
- if (viewByName.has(dependency)) visit(dependency, [...path, name]);
2100
+ if (viewByName.has(dependency)) visit(dependency, [...path, name2]);
2064
2101
  }
2065
- visiting.delete(name);
2066
- visited.add(name);
2102
+ visiting.delete(name2);
2103
+ visited.add(name2);
2067
2104
  };
2068
2105
  for (const view of views) visit(view.view, []);
2069
2106
  });
2107
+ var canonicalDefinitionSchema = localDefinitionSchema.safeExtend({
2108
+ /** Flattened, pinned snapshots. Imported relations never participate in this namespace's DDL. */
2109
+ imports: z.array(localDefinitionSchema).max(32).optional()
2110
+ });
2070
2111
  function canonicalRelations(definition) {
2071
2112
  const views = (definition.views ?? []).map((view) => ({
2072
2113
  table: view.view,
@@ -2110,6 +2151,11 @@ function normalizeCanonical(definition) {
2110
2151
  dependencies: [...view.dependencies].sort()
2111
2152
  }));
2112
2153
  }
2154
+ if (definition.imports?.length) {
2155
+ normalized.imports = definition.imports.map(normalizeCanonical).sort((a, b) => a.namespace.localeCompare(b.namespace));
2156
+ } else {
2157
+ delete normalized.imports;
2158
+ }
2113
2159
  return normalized;
2114
2160
  }
2115
2161
 
@@ -2234,8 +2280,8 @@ var literal = (value) => `'${value.replace(/'/g, "''")}'`;
2234
2280
  var physical = ({ source, property }) => source.table.columns[property].columnNameFor(property);
2235
2281
  function candidateSql({ source, column, pk, pgType }) {
2236
2282
  const a = ident(`s_${source.name}`);
2237
- const name = physical({ source, property: column });
2238
- const value = `CAST(${a}.${ident(name)} AS ${pgType})`;
2283
+ const name2 = physical({ source, property: column });
2284
+ const value = `CAST(${a}.${ident(name2)} AS ${pgType})`;
2239
2285
  if (source.kind === "etl") {
2240
2286
  return {
2241
2287
  source: source.name,
@@ -2245,9 +2291,9 @@ function candidateSql({ source, column, pk, pgType }) {
2245
2291
  by: "CAST(NULL AS text)"
2246
2292
  };
2247
2293
  }
2248
- const at = `${a}.${ident(cellColumnName(name, "at"))}`;
2294
+ const at = `${a}.${ident(cellColumnName(name2, "at"))}`;
2249
2295
  const tombstoned2 = source.kind === "prefetch" ? ` AND NOT ${a}.${ident(RESOLVED_SOURCE_SYSTEM_COLUMNS.tombstoned.columnName)}` : "";
2250
- return { source: source.name, value, has: `(${at} IS NOT NULL${tombstoned2})`, at, by: `${a}.${ident(cellColumnName(name, "by"))}` };
2296
+ return { source: source.name, value, has: `(${at} IS NOT NULL${tombstoned2})`, at, by: `${a}.${ident(cellColumnName(name2, "by"))}` };
2251
2297
  }
2252
2298
  function outranks({ i, j, key, direction, inclusive }) {
2253
2299
  const ki = i[key];
@@ -2340,7 +2386,7 @@ function buildResolvedQuery({ context, plan }) {
2340
2386
  plan.rules.forEach((rule, index3) => {
2341
2387
  const canonical = plan.columns[rule.column].toCanonicalColumn(rule.column);
2342
2388
  const pgType = typeof canonical.type === "string" ? PG_TYPE[canonical.type] : `${schema === void 0 ? "" : `${ident(schema)}.`}${ident(canonical.type.enum)}`;
2343
- const candidates = rule.candidates.map((name) => candidateSql({ source: sourceByName.get(name), column: rule.column, pk: plan.pk, pgType }));
2389
+ const candidates = rule.candidates.map((name2) => candidateSql({ source: sourceByName.get(name2), column: rule.column, pk: plan.pk, pgType }));
2344
2390
  cells.set(rule.column, rule.comparator === "custom" ? customCell({ candidates, orderBy: rule.orderBy, index: index3 }) : builtinCell({ comparator: rule.comparator, candidates }));
2345
2391
  });
2346
2392
  const laterals = [...cells.values()].flatMap((cell) => cell.lateral ? [sql.raw(cell.lateral)] : []);
@@ -2361,7 +2407,7 @@ function buildResolvedQuery({ context, plan }) {
2361
2407
  const system = RESOLVED_VIEW_SYSTEM_COLUMNS;
2362
2408
  selected[system.writebackStatus.name] = sql.raw(`${alias(manual.name)}.${ident(RESOLVED_SOURCE_SYSTEM_COLUMNS.writebackStatus.columnName)}`).as(system.writebackStatus.columnName);
2363
2409
  selected[system.writebackError.name] = sql.raw(`${alias(manual.name)}.${ident(RESOLVED_SOURCE_SYSTEM_COLUMNS.writebackError.columnName)}`).as(system.writebackError.columnName);
2364
- const hidden = plan.deletedBy.map((name) => `NOT COALESCE(${alias(name)}.${ident(tombstoned2)}, false)`);
2410
+ const hidden = plan.deletedBy.map((name2) => `NOT COALESCE(${alias(name2)}.${ident(tombstoned2)}, false)`);
2365
2411
  const query = qb.select(selected).from(from);
2366
2412
  return hidden.length > 0 ? query.where(sql.raw(hidden.join(" AND "))) : query;
2367
2413
  }
@@ -2387,12 +2433,12 @@ var SYSTEM_VIEW_COLUMNS = {
2387
2433
  [RESOLVED_VIEW_SYSTEM_COLUMNS.writebackStatus.name]: () => t.text(RESOLVED_VIEW_SYSTEM_COLUMNS.writebackStatus.columnName),
2388
2434
  [RESOLVED_VIEW_SYSTEM_COLUMNS.writebackError.name]: () => t.text(RESOLVED_VIEW_SYSTEM_COLUMNS.writebackError.columnName)
2389
2435
  };
2390
- function defineResolvedTable(name, columns, config) {
2436
+ function defineResolvedTable(name2, columns, config) {
2391
2437
  const file = activeAuthoringContext()?.currentFile;
2392
2438
  const fail = (message) => {
2393
- throw new OrmDefinitionError(`resolved table "${name}": ${message}`, file);
2439
+ throw new OrmDefinitionError(`resolved table "${name2}": ${message}`, file);
2394
2440
  };
2395
- if (!IDENTIFIER_PATTERN.test(name)) fail(`name must match ${IDENTIFIER_PATTERN}`);
2441
+ if (!IDENTIFIER_PATTERN.test(name2)) fail(`name must match ${IDENTIFIER_PATTERN}`);
2396
2442
  for (const property of Object.keys(columns)) {
2397
2443
  if (RESERVED_RESOLVED_COLUMN_NAMES.has(property) || RESERVED_RESOLVED_COLUMN_NAMES.has(columns[property].columnNameFor(property))) {
2398
2444
  fail(`column "${property}" collides with a reserved system column`);
@@ -2411,7 +2457,7 @@ function defineResolvedTable(name, columns, config) {
2411
2457
  const sourceEntries = Object.entries(config.sources);
2412
2458
  if (sourceEntries.filter(([, source]) => source.kind === "manual").length !== 1) fail("declare exactly one manualSource()");
2413
2459
  const plans = sourceEntries.map(
2414
- ([sourceName, input]) => planSource({ viewName: name, sourceName, input, columns, pk, pkBuilder, dataColumns, fail })
2460
+ ([sourceName, input]) => planSource({ viewName: name2, sourceName, input, columns, pk, pkBuilder, dataColumns, fail })
2415
2461
  );
2416
2462
  const rules = planRules({ config, plans, dataColumns, fail });
2417
2463
  const deletedBy = [...config.rows?.deletedBy ?? []];
@@ -2445,23 +2491,23 @@ function defineResolvedTable(name, columns, config) {
2445
2491
  policies: { read }
2446
2492
  };
2447
2493
  if (!config.materialize) {
2448
- return defineView(name, typedColumns, { ...surface, query: (context) => buildResolvedQuery({ context, plan: queryPlan }), resolved });
2494
+ return defineView(name2, typedColumns, { ...surface, query: (context) => buildResolvedQuery({ context, plan: queryPlan }), resolved });
2449
2495
  }
2450
2496
  const materialize = config.materialize === true ? {} : config.materialize;
2451
- const computeName = `${name}__compute`;
2452
- const tableName = `${name}__materialized`;
2497
+ const computeName = `${name2}__compute`;
2498
+ const tableName = `${name2}__materialized`;
2453
2499
  const compute = defineView(computeName, typedColumns, {
2454
2500
  policies: { read },
2455
2501
  query: (context) => buildResolvedQuery({ context, plan: queryPlan }),
2456
2502
  internal: true
2457
2503
  });
2458
2504
  const table = defineTable(tableName, viewColumns, {
2459
- description: `Materialized rows of resolved table "${name}". System-maintained from "${computeName}".`,
2505
+ description: `Materialized rows of resolved table "${name2}". System-maintained from "${computeName}".`,
2460
2506
  internal: true,
2461
- materializes: name,
2507
+ materializes: name2,
2462
2508
  ...materialize.indexes !== void 0 ? { indexes: materialize.indexes } : {}
2463
2509
  });
2464
- return defineView(name, typedColumns, {
2510
+ return defineView(name2, typedColumns, {
2465
2511
  ...surface,
2466
2512
  query: (context) => {
2467
2513
  const handle = context.relation(table);
@@ -2488,7 +2534,7 @@ function planRules({ config, plans, dataColumns, fail }) {
2488
2534
  return dataColumns.map((column) => {
2489
2535
  const explicit = config.resolve?.[column];
2490
2536
  const comparator = explicit ?? fallback;
2491
- const candidates = explicit ? [...explicit.candidates] : comparator.candidates.filter((name) => plans.find((plan) => plan.name === name)?.columns.includes(column));
2537
+ const candidates = explicit ? [...explicit.candidates] : comparator.candidates.filter((name2) => plans.find((plan) => plan.name === name2)?.columns.includes(column));
2492
2538
  for (const candidate of candidates) {
2493
2539
  const plan = plans.find((entry) => entry.name === candidate);
2494
2540
  if (!plan) fail(`column "${column}" names unknown source "${candidate}"`);
@@ -2590,8 +2636,8 @@ function canonicalTable(table) {
2590
2636
  },
2591
2637
  actions: emptyToNull(
2592
2638
  Object.fromEntries(
2593
- Object.entries(table.actions ?? {}).map(([name, action]) => [
2594
- name,
2639
+ Object.entries(table.actions ?? {}).map(([name2, action]) => [
2640
+ name2,
2595
2641
  {
2596
2642
  description: action.description ?? null,
2597
2643
  requires: action.requires?.source ?? null,
@@ -2645,6 +2691,72 @@ function computeDefinitionHash(definition) {
2645
2691
  return createHash("sha256").update(HASH_DOMAIN).update(stableJson(canonicalizeDefinition(definition))).digest("hex");
2646
2692
  }
2647
2693
 
2694
+ // src/canonical/composition.ts
2695
+ function localContract(definition) {
2696
+ return normalizeCanonical(localDefinitionSchema.parse(definition));
2697
+ }
2698
+ function flattenNamespaceImports(inputs) {
2699
+ const definitions = /* @__PURE__ */ new Map();
2700
+ const visit = (value, depth) => {
2701
+ if (depth > 16 || definitions.size > 32) throw new OrmDefinitionError("namespace import graph is too large");
2702
+ const definition = localContract(localDefinitionSchema.parse(value));
2703
+ const previous = definitions.get(definition.namespace);
2704
+ if (previous) {
2705
+ if (stableJson(previous) !== stableJson(definition)) throw new OrmDefinitionError(`conflicting contracts for namespace '${definition.namespace}'`);
2706
+ }
2707
+ definitions.set(definition.namespace, definition);
2708
+ if (typeof value === "object" && value !== null && "imports" in value && Array.isArray(value.imports)) {
2709
+ for (const dependency of value.imports) visit(dependency, depth + 1);
2710
+ }
2711
+ };
2712
+ for (const input of inputs) visit(input, 0);
2713
+ return [...definitions.values()].sort((a, b) => a.namespace.localeCompare(b.namespace));
2714
+ }
2715
+ function composeNamespace(definition) {
2716
+ const all = [localContract(definition), ...definition.imports ?? []];
2717
+ const owners = /* @__PURE__ */ new Map();
2718
+ const namespaces = /* @__PURE__ */ new Set();
2719
+ const enums = /* @__PURE__ */ new Map();
2720
+ for (const owner of all) {
2721
+ if (namespaces.has(owner.namespace)) throw new OrmDefinitionError(`duplicate imported namespace '${owner.namespace}'`);
2722
+ namespaces.add(owner.namespace);
2723
+ for (const value of owner.enums) {
2724
+ const previous = enums.get(value.name);
2725
+ if (previous && stableJson(previous) !== stableJson(value)) {
2726
+ throw new OrmDefinitionError(`conflicting imported enum '${value.name}'`);
2727
+ }
2728
+ enums.set(value.name, value);
2729
+ }
2730
+ for (const relation of canonicalRelations(owner)) {
2731
+ if (owners.has(relation.table)) throw new OrmDefinitionError(`ambiguous imported relation '${relation.table}'`);
2732
+ owners.set(relation.table, owner);
2733
+ }
2734
+ }
2735
+ for (const owner of definition.imports?.length ? all : []) {
2736
+ for (const relation of canonicalRelations(owner)) {
2737
+ for (const link of relation.links) {
2738
+ if (link.kind === "toPlatformUser") continue;
2739
+ const target = owners.get(link.target ?? "");
2740
+ if (!target || target.namespace !== (link.namespace ?? owner.namespace)) {
2741
+ throw new OrmDefinitionError(`link '${owner.namespace}/${relation.table}.${link.name}' has no matching imported target`);
2742
+ }
2743
+ if (target.namespace !== owner.namespace && !target.exports?.[link.target ?? ""]) {
2744
+ throw new OrmDefinitionError(`target '${target.namespace}/${link.target}' is not exported`);
2745
+ }
2746
+ }
2747
+ }
2748
+ }
2749
+ return {
2750
+ owners,
2751
+ definition: {
2752
+ ...localContract(definition),
2753
+ tables: all.flatMap((item) => item.tables),
2754
+ views: all.flatMap((item) => item.views ?? []),
2755
+ enums: [...enums.values()]
2756
+ }
2757
+ };
2758
+ }
2759
+
2648
2760
  // src/authoring/namespace.ts
2649
2761
  var NAMESPACE_CONFIG_BRAND = "seq-namespace-config";
2650
2762
  function isSeqNamespaceConfig(value) {
@@ -2660,6 +2772,8 @@ function defineNamespace(input) {
2660
2772
  namespace: input.namespace,
2661
2773
  description: input.description,
2662
2774
  capabilities: input.capabilities ?? {},
2775
+ imports: input.imports,
2776
+ exports: input.exports,
2663
2777
  file
2664
2778
  };
2665
2779
  registerNamespaceConfig(config);
@@ -2704,15 +2818,15 @@ function serializeNamespace(input) {
2704
2818
  }
2705
2819
  const relationsByName = /* @__PURE__ */ new Map();
2706
2820
  for (const relation of [...tables, ...views]) {
2707
- const name = relationName(relation);
2708
- const existing = relationsByName.get(name);
2821
+ const name2 = relationName(relation);
2822
+ const existing = relationsByName.get(name2);
2709
2823
  if (existing) {
2710
2824
  throw new OrmDefinitionError(
2711
- `duplicate relation "${name}" (defined as ${relationKind(existing)} in ${describeFile(existing)} and ${relationKind(relation)} in ${describeFile(relation)})`,
2825
+ `duplicate relation "${name2}" (defined as ${relationKind(existing)} in ${describeFile(existing)} and ${relationKind(relation)} in ${describeFile(relation)})`,
2712
2826
  relation.file
2713
2827
  );
2714
2828
  }
2715
- relationsByName.set(name, relation);
2829
+ relationsByName.set(name2, relation);
2716
2830
  }
2717
2831
  const enumsByName = /* @__PURE__ */ new Map();
2718
2832
  for (const ref of enums) {
@@ -2753,6 +2867,8 @@ function serializeNamespace(input) {
2753
2867
  };
2754
2868
  if (config.description !== void 0) candidate.description = config.description;
2755
2869
  if (canonicalViews.length > 0) candidate.views = canonicalViews;
2870
+ if (config.imports?.length) candidate.imports = flattenNamespaceImports(config.imports);
2871
+ if (config.exports) candidate.exports = config.exports;
2756
2872
  let parsed;
2757
2873
  try {
2758
2874
  parsed = canonicalDefinitionSchema.parse(candidate);
@@ -2762,7 +2878,9 @@ function serializeNamespace(input) {
2762
2878
  }
2763
2879
  throw error;
2764
2880
  }
2765
- return normalizeCanonical(parsed);
2881
+ const normalized = normalizeCanonical(parsed);
2882
+ if (normalized.imports?.length) composeNamespace(normalized);
2883
+ return normalized;
2766
2884
  }
2767
2885
  function computeCanonicalHash(definition) {
2768
2886
  return createHash("sha256").update(HASH_DOMAIN).update(stableJson(definition)).digest("hex");
@@ -2776,6 +2894,7 @@ function buildCanonicalTable({ table, relationsByName, enumsByName }) {
2776
2894
  policies: {},
2777
2895
  actions: []
2778
2896
  };
2897
+ if (table.config.displayName !== void 0) candidate.displayName = table.config.displayName;
2779
2898
  if (table.config.description !== void 0) candidate.description = table.config.description;
2780
2899
  if (table.config.renamedFrom !== void 0) candidate.renamedFrom = table.config.renamedFrom;
2781
2900
  if (table.source !== void 0) candidate.source = table.source;
@@ -2859,6 +2978,9 @@ function buildCanonicalTable({ table, relationsByName, enumsByName }) {
2859
2978
  if (table.config.foreignKeys?.length) {
2860
2979
  if (table.source) throw new OrmDefinitionError(`synced table "${table.tableName}" cannot enforce foreign keys`, table.file);
2861
2980
  candidate.foreignKeys = table.config.foreignKeys.map((fk) => {
2981
+ if (typeof fk.target === "object" && fk.target.kind === "seq-external-object") {
2982
+ throw new OrmDefinitionError("physical foreign keys require a local target; use a cross-namespace ORM link", table.file);
2983
+ }
2862
2984
  const target = resolveRelationRef({ ref: fk.target, fail: (message) => {
2863
2985
  throw new OrmDefinitionError(message, table.file);
2864
2986
  } });
@@ -3029,6 +3151,19 @@ function buildCanonicalLink({
3029
3151
  ...link.description !== void 0 ? { description: link.description } : {}
3030
3152
  };
3031
3153
  }
3154
+ if (typeof link.target === "object" && link.target?.kind === "seq-external-object") {
3155
+ if (link.enforce) return fail("cannot enforce a cross-namespace physical foreign key; use an ORM link without enforce");
3156
+ return {
3157
+ name: linkName,
3158
+ kind: link.linkKind,
3159
+ namespace: link.target.namespace,
3160
+ target: link.target.table,
3161
+ on: link.linkKind === "toOne" ? resolveColumnRef({ relation, ref: link.on, role: "link on" }) : link.on,
3162
+ ...link.references !== void 0 ? { references: link.linkKind === "toMany" ? resolveColumnRef({ relation, ref: link.references, role: "link references" }) : link.references } : {},
3163
+ enforce: false,
3164
+ ...link.description !== void 0 ? { description: link.description } : {}
3165
+ };
3166
+ }
3032
3167
  const target = resolveRelationRef({ ref: link.target, fail });
3033
3168
  const targetName = relationName(target);
3034
3169
  if (!relationsByName.has(targetName)) {
@@ -3085,11 +3220,11 @@ function assertAcyclicViewDependencies(views) {
3085
3220
  views.map((view) => [view.view, new Set(view.dependencies.filter((dependency) => viewNames.has(dependency)))])
3086
3221
  );
3087
3222
  while (remaining.size > 0) {
3088
- const ready = [...remaining.entries()].filter(([, dependencies]) => [...dependencies].every((dependency) => !remaining.has(dependency))).map(([name]) => name);
3223
+ const ready = [...remaining.entries()].filter(([, dependencies]) => [...dependencies].every((dependency) => !remaining.has(dependency))).map(([name2]) => name2);
3089
3224
  if (ready.length === 0) {
3090
3225
  throw new OrmDefinitionError(`view dependencies form a cycle among: ${[...remaining.keys()].sort().join(", ")}`);
3091
3226
  }
3092
- for (const name of ready) remaining.delete(name);
3227
+ for (const name2 of ready) remaining.delete(name2);
3093
3228
  }
3094
3229
  }
3095
3230
  function toCanonicalPolicy(policy) {
@@ -3135,8 +3270,8 @@ function syncedContractSurface({
3135
3270
  namespace,
3136
3271
  table,
3137
3272
  columns: Object.fromEntries(
3138
- Object.entries(columns).map(([name, column]) => [
3139
- name,
3273
+ Object.entries(columns).map(([name2, column]) => [
3274
+ name2,
3140
3275
  { type: column.type, nullable: column.nullable, key: column.key }
3141
3276
  ])
3142
3277
  ),
@@ -3157,7 +3292,7 @@ function extractOrmSyncedTableContract({
3157
3292
  }
3158
3293
  if (table.source === void 0) {
3159
3294
  throw new OrmDefinitionError(
3160
- `table "${table.table}" is not a synced table \u2014 extractOrmSyncedTableContract requires source: gold.*`
3295
+ `table "${table.table}" is not a synced table \u2014 extractOrmSyncedTableContract requires a qualified source`
3161
3296
  );
3162
3297
  }
3163
3298
  if (table.columns.length === 0) {
@@ -3304,6 +3439,53 @@ function purgeModuleCache(root) {
3304
3439
  if (key.startsWith(prefix)) delete require2.cache[key];
3305
3440
  }
3306
3441
  }
3442
+ var sqlScalarSchema = z.enum(["text", "boolean", "integer", "bigint", "numeric", "double", "uuid", "date", "timestamptz"]);
3443
+ var name = z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/).max(63).refine((value) => !["__proto__", "prototype", "constructor"].includes(value), "reserved name");
3444
+ var base = z.object({
3445
+ name,
3446
+ namespace: name,
3447
+ language: z.literal("sql"),
3448
+ kind: z.literal("query"),
3449
+ requires: z.object({ capability: z.string().min(1).max(128) }).strict(),
3450
+ ontology: z.object({ read: z.array(z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*\/[A-Za-z_][A-Za-z0-9_]*$/)).min(1).max(256) }).strict(),
3451
+ maxRows: z.number().int().min(1).max(1e4).default(1e3)
3452
+ });
3453
+ var fixed = base.extend({
3454
+ parameters: z.record(name, z.object({ type: sqlScalarSchema, required: z.boolean().default(true) }).strict()).default({}),
3455
+ sql: z.string().min(1).max(65536)
3456
+ }).strict();
3457
+ var runtime = base.extend({ mode: z.literal("runtime") }).strict();
3458
+ var sqlOperationDefinitionSchema = z.union([fixed, runtime]);
3459
+ function defineOperation(input) {
3460
+ return sqlOperationDefinitionSchema.parse(input);
3461
+ }
3462
+
3463
+ // src/authoring/catalog.ts
3464
+ var SEGMENT = /^[^./\\\s][^/\\]*[^./\\\s]$|^[^./\\\s]$/;
3465
+ function validateNamespaceCatalog(catalog, file) {
3466
+ const paths = /* @__PURE__ */ new Set([""]);
3467
+ function visit(folders, parent) {
3468
+ for (const [name2, children] of Object.entries(folders)) {
3469
+ if (!SEGMENT.test(name2) || ["__proto__", "constructor", "prototype"].includes(name2)) {
3470
+ throw new OrmDefinitionError(`invalid catalog folder name "${name2}"`, file);
3471
+ }
3472
+ const path = parent ? `${parent}/${name2}` : name2;
3473
+ paths.add(path);
3474
+ if (children !== null) {
3475
+ if (typeof children !== "object" || Array.isArray(children)) {
3476
+ throw new OrmDefinitionError(`catalog folder "${path}" must contain folders or null`, file);
3477
+ }
3478
+ visit(children, path);
3479
+ }
3480
+ }
3481
+ }
3482
+ visit(catalog.folders, "");
3483
+ for (const [object, path] of Object.entries(catalog.objects)) {
3484
+ if (!object || !paths.has(path)) {
3485
+ throw new OrmDefinitionError(`catalog object "${object}" references missing folder "${path}"`, file);
3486
+ }
3487
+ }
3488
+ }
3307
3489
 
3308
3490
  // src/codegen/types.ts
3309
3491
  var WIRE_TYPES = {
@@ -3335,9 +3517,9 @@ function generateNamespaceTypes(definition) {
3335
3517
  lines.push(` /** Synced from ${table.source} \u2014 read-only typed contract. */`);
3336
3518
  }
3337
3519
  lines.push(` ${table.table}: {`);
3338
- for (const [name, column] of columns) {
3520
+ for (const [name2, column] of columns) {
3339
3521
  if (column.deprecated) continue;
3340
- lines.push(` ${name}: ${columnWireType(column)}`);
3522
+ lines.push(` ${name2}: ${columnWireType(column)}`);
3341
3523
  }
3342
3524
  lines.push(" }");
3343
3525
  }
@@ -3348,8 +3530,8 @@ function generateNamespaceTypes(definition) {
3348
3530
  function actionTypeLines(definition) {
3349
3531
  const actions = definition.tables.flatMap((table) => Object.entries(table.actions ?? {}));
3350
3532
  const lines = [`export type ${actionsInterfaceName(definition.namespace)} = {`];
3351
- for (const [name, action] of actions.sort(([a], [b]) => a.localeCompare(b))) {
3352
- lines.push(` ${name}: { params: ${actionParamsType(action)}; result: ${actionResultType(action)} }`);
3533
+ for (const [name2, action] of actions.sort(([a], [b]) => a.localeCompare(b))) {
3534
+ lines.push(` ${name2}: { params: ${actionParamsType(action)}; result: ${actionResultType(action)} }`);
3353
3535
  }
3354
3536
  lines.push("}", "");
3355
3537
  return lines;
@@ -3357,17 +3539,17 @@ function actionTypeLines(definition) {
3357
3539
  function actionParamsType(action) {
3358
3540
  const entries = Object.entries(action.params ?? {});
3359
3541
  if (entries.length === 0) return "Record<never, never>";
3360
- const fields = entries.map(([name, param]) => {
3361
- const base = WIRE_TYPES[param.type];
3362
- return param.optional ? `${name}?: ${base} | null` : `${name}: ${base}`;
3542
+ const fields = entries.map(([name2, param]) => {
3543
+ const base2 = WIRE_TYPES[param.type];
3544
+ return param.optional ? `${name2}?: ${base2} | null` : `${name2}: ${base2}`;
3363
3545
  });
3364
3546
  return `{ ${fields.join("; ")} }`;
3365
3547
  }
3366
3548
  function actionResultType(action) {
3367
3549
  if (!action.returns) return "{ rowsAffected: number }";
3368
- const columns = Object.entries(action.returns).map(([name, type]) => {
3369
- const base = WIRE_TYPES[type];
3370
- return base === "unknown" ? `${name}: ${base}` : `${name}: ${base} | null`;
3550
+ const columns = Object.entries(action.returns).map(([name2, type]) => {
3551
+ const base2 = WIRE_TYPES[type];
3552
+ return base2 === "unknown" ? `${name2}: ${base2}` : `${name2}: ${base2} | null`;
3371
3553
  });
3372
3554
  return `{ rows: Array<{ ${columns.join("; ")} }> }`;
3373
3555
  }
@@ -3381,9 +3563,9 @@ function pascalCase(namespace) {
3381
3563
  return namespace.split("_").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
3382
3564
  }
3383
3565
  function columnWireType(column) {
3384
- const base = WIRE_TYPES[column.type];
3566
+ const base2 = WIRE_TYPES[column.type];
3385
3567
  const notNull = column.primary_key === true || column.nullable === false;
3386
- return notNull || base === "unknown" ? base : `${base} | null`;
3568
+ return notNull || base2 === "unknown" ? base2 : `${base2} | null`;
3387
3569
  }
3388
3570
 
3389
3571
  // src/predicate/ast.ts
@@ -3848,7 +4030,7 @@ function executesIssues(executes, declaredParams, hasReturns) {
3848
4030
  if (hasReturns && last && !RETURNING_PATTERN.test(last.replace(QUOTED_STRING_PATTERN, "''"))) {
3849
4031
  issues.push("the last executes statement must use RETURNING to populate the declared returns columns");
3850
4032
  }
3851
- const undeclared = extractNamedParams(statements.join("\n")).filter((name) => !declaredParams.has(name));
4033
+ const undeclared = extractNamedParams(statements.join("\n")).filter((name2) => !declaredParams.has(name2));
3852
4034
  if (undeclared.length > 0) issues.push(`executes references undeclared params: ${undeclared.join(", ")}`);
3853
4035
  return issues;
3854
4036
  }
@@ -3923,19 +4105,19 @@ var PARAM_SCHEMAS = {
3923
4105
  function buildActionParamsSchema(action) {
3924
4106
  const shape = {};
3925
4107
  const entries = Object.entries(action.params ?? {});
3926
- for (const [name, param] of entries) {
3927
- shape[name] = param.optional ? PARAM_SCHEMAS[param.type].nullish() : PARAM_SCHEMAS[param.type];
4108
+ for (const [name2, param] of entries) {
4109
+ shape[name2] = param.optional ? PARAM_SCHEMAS[param.type].nullish() : PARAM_SCHEMAS[param.type];
3928
4110
  }
3929
4111
  return z.strictObject(shape).superRefine((obj, ctx) => {
3930
- for (const [name, param] of entries) {
3931
- if (!param.optional && param.type === "jsonb" && obj[name] === void 0) {
3932
- ctx.addIssue({ code: "custom", message: "Required", path: [name] });
4112
+ for (const [name2, param] of entries) {
4113
+ if (!param.optional && param.type === "jsonb" && obj[name2] === void 0) {
4114
+ ctx.addIssue({ code: "custom", message: "Required", path: [name2] });
3933
4115
  }
3934
4116
  }
3935
4117
  });
3936
4118
  }
3937
4119
  var actionParamOrder = (action) => Object.keys(action.params ?? {});
3938
- var actionParamArg = (name) => `p_${name}`;
4120
+ var actionParamArg = (name2) => `p_${name2}`;
3939
4121
  function compileActionStatements(action, renderParam = actionParamArg) {
3940
4122
  return actionStatementSources(action.executes).map((statement) => compileStatement(statement, renderParam));
3941
4123
  }
@@ -3986,10 +4168,12 @@ function compilePredIrToSql(pred, options = {}) {
3986
4168
  case "cmp":
3987
4169
  return compileCmp(pred.op, pred.column, pred.value, options);
3988
4170
  case "capability":
3989
- return `(${capabilityExpression(pred.key)})`;
4171
+ return `(${capabilityExpression(pred.key, pred.namespace ?? options.namespace)})`;
3990
4172
  case "role":
3991
- return `(${roleExpression(pred.key)})`;
4173
+ return `(${roleExpression(pred.key, pred.namespace ?? options.namespace)})`;
3992
4174
  case "exists":
4175
+ if (options.exists) return options.exists(pred);
4176
+ throw new OrmDefinitionError("synced view read policy cannot use 'exists' without a relationship resolver");
3993
4177
  case "aggPredicate":
3994
4178
  case "dynamicFilter":
3995
4179
  throw new OrmDefinitionError(
@@ -4008,7 +4192,8 @@ function compileCmp(op, column, value, options) {
4008
4192
  const physical2 = physicalColumn(column, options);
4009
4193
  const declared = options.columnTypes?.[physical2] ?? options.columnTypes?.[column];
4010
4194
  const isEnum = typeof declared === "object" && declared !== null;
4011
- const col = isEnum ? `${quoteIdentifier(physical2)}::text` : quoteIdentifier(physical2);
4195
+ const qualified = options.alias ? `${quoteIdentifier(options.alias)}.${quoteIdentifier(physical2)}` : quoteIdentifier(physical2);
4196
+ const col = isEnum ? `${qualified}::text` : qualified;
4012
4197
  const columnType = isEnum ? "text" : declared;
4013
4198
  switch (op) {
4014
4199
  case "eq":
@@ -4092,22 +4277,22 @@ function returnProjection(returns, lastStatement) {
4092
4277
  const projection = Object.keys(returns).map(quoteIdentifier).join(", ");
4093
4278
  return `WITH orm_returning AS (${lastStatement}) SELECT ${projection} FROM orm_returning`;
4094
4279
  }
4095
- var allActions = (definition) => definition.tables.flatMap((table) => Object.entries(table.actions ?? {}).map(([name, action]) => ({ name, action }))).sort((a, b) => a.name.localeCompare(b.name));
4280
+ var allActions = (definition) => definition.tables.flatMap((table) => Object.entries(table.actions ?? {}).map(([name2, action]) => ({ name: name2, action }))).sort((a, b) => a.name.localeCompare(b.name));
4096
4281
  function actionFunctionStatements(definition) {
4097
4282
  const schema = ormSchemaName(definition.namespace);
4098
- return [dropAllActionFunctions(schema), ...allActions(definition).flatMap(({ name, action }) => createActionFunction(definition, name, action))];
4283
+ return [dropAllActionFunctions(schema), ...allActions(definition).flatMap(({ name: name2, action }) => createActionFunction(definition, name2, action))];
4099
4284
  }
4100
4285
  function actionPrepareChecks(definition) {
4101
4286
  const actions = allActions(definition);
4102
4287
  if (actions.length === 0) return [];
4103
4288
  const statements = [`SET LOCAL search_path TO ${quoteIdentifier(ormSchemaName(definition.namespace))}`];
4104
- for (const { name, action } of actions) {
4289
+ for (const { name: name2, action } of actions) {
4105
4290
  const order = actionParamOrder(action);
4106
4291
  const signature = order.length > 0 ? ` (${order.map((param) => sqlTypeName(action.params[param].type)).join(", ")})` : "";
4107
4292
  const compiled = compileActionStatements(action, (param) => `$${order.indexOf(param) + 1}`);
4108
4293
  compiled.forEach((sql7, index3) => {
4109
4294
  const checked = action.returns && index3 === compiled.length - 1 ? returnProjection(action.returns, sql7) : sql7;
4110
- statements.push(`PREPARE ${quoteIdentifier(`orm_check_${name}_${index3}`)}${signature} AS ${checked}`);
4295
+ statements.push(`PREPARE ${quoteIdentifier(`orm_check_${name2}_${index3}`)}${signature} AS ${checked}`);
4111
4296
  });
4112
4297
  }
4113
4298
  return statements;
@@ -4128,9 +4313,9 @@ BEGIN
4128
4313
  END
4129
4314
  $orm_reconcile_actions$`;
4130
4315
  }
4131
- function createActionFunction(definition, name, action) {
4316
+ function createActionFunction(definition, name2, action) {
4132
4317
  const schema = quoteIdentifier(ormSchemaName(definition.namespace));
4133
- const fn = `${schema}.${quoteIdentifier(actionFunctionName(name))}`;
4318
+ const fn = `${schema}.${quoteIdentifier(actionFunctionName(name2))}`;
4134
4319
  const order = actionParamOrder(action);
4135
4320
  const signature = order.map((paramName) => `${quoteIdentifier(actionParamArg(paramName))} ${sqlTypeName(action.params[paramName].type)}`).join(", ");
4136
4321
  const argTypes = order.map((paramName) => sqlTypeName(action.params[paramName].type)).join(", ");
@@ -4150,7 +4335,7 @@ AS $orm_action$
4150
4335
  -- columns; resolve unqualified names to the column.
4151
4336
  #variable_conflict use_column
4152
4337
  BEGIN
4153
- ${[functionGuards(definition, name, action), ...leading, ` RETURN QUERY ${returnProjection(action.returns, last)};`].filter(Boolean).join("\n")}
4338
+ ${[functionGuards(definition, name2, action), ...leading, ` RETURN QUERY ${returnProjection(action.returns, last)};`].filter(Boolean).join("\n")}
4154
4339
  END
4155
4340
  $orm_action$`
4156
4341
  ) : (
@@ -4164,7 +4349,7 @@ AS $orm_action$
4164
4349
  DECLARE
4165
4350
  v_count bigint;
4166
4351
  BEGIN
4167
- ${[functionGuards(definition, name, action), ...leading, ` ${last};`].filter(Boolean).join("\n")}
4352
+ ${[functionGuards(definition, name2, action), ...leading, ` ${last};`].filter(Boolean).join("\n")}
4168
4353
  GET DIAGNOSTICS v_count = ROW_COUNT;
4169
4354
  RETURN v_count;
4170
4355
  END
@@ -4176,13 +4361,13 @@ $orm_action$`
4176
4361
  `GRANT EXECUTE ON FUNCTION ${fn}(${argTypes}) TO ${role}`
4177
4362
  ];
4178
4363
  }
4179
- function functionGuards(definition, name, action) {
4364
+ function functionGuards(definition, name2, action) {
4180
4365
  const lines = [];
4181
4366
  const requires = compileActionRequires(action);
4182
4367
  if (requires) {
4183
4368
  lines.push(
4184
4369
  ` IF NOT (${requires}) THEN`,
4185
- ` RAISE EXCEPTION 'action ${name} requires a grant the caller does not hold' USING ERRCODE = ${quoteLiteral(ACTION_REQUIRES_DENIED_SQLSTATE)};`,
4370
+ ` RAISE EXCEPTION 'action ${name2} requires a grant the caller does not hold' USING ERRCODE = ${quoteLiteral(ACTION_REQUIRES_DENIED_SQLSTATE)};`,
4186
4371
  ` END IF;`
4187
4372
  );
4188
4373
  }
@@ -4234,7 +4419,7 @@ var tableFileSchema = z.strictObject({
4234
4419
  table: identifierSchema,
4235
4420
  description: z.string().optional(),
4236
4421
  columns: z.record(identifierSchema, columnSchema).optional(),
4237
- source: z.string().regex(SYNCED_SOURCE_PATTERN, "source must reference a gold-layer table").optional(),
4422
+ source: z.string().regex(SYNCED_SOURCE_PATTERN, "source must be a qualified lowercase schema.table identifier").optional(),
4238
4423
  links: z.record(identifierSchema, linkSchema).optional(),
4239
4424
  indexes: z.array(indexSchema).optional(),
4240
4425
  policies: policiesSchema.optional(),
@@ -4243,12 +4428,12 @@ var tableFileSchema = z.strictObject({
4243
4428
  if (RESERVED_TABLE_NAMES.has(table.table)) {
4244
4429
  ctx.addIssue({ code: "custom", message: `'${table.table}' is a reserved table name`, path: ["table"] });
4245
4430
  }
4246
- for (const name of Object.keys(table.columns ?? {})) {
4247
- if (RESERVED_COLUMN_NAMES.has(name)) {
4431
+ for (const name2 of Object.keys(table.columns ?? {})) {
4432
+ if (RESERVED_COLUMN_NAMES.has(name2)) {
4248
4433
  ctx.addIssue({
4249
4434
  code: "custom",
4250
- message: `column '${name}' collides with the Data API's reserved query parameters (select, order, limit, offset) \u2014 it could never be filtered`,
4251
- path: ["columns", name]
4435
+ message: `column '${name2}' collides with the Data API's reserved query parameters (select, order, limit, offset) \u2014 it could never be filtered`,
4436
+ path: ["columns", name2]
4252
4437
  });
4253
4438
  }
4254
4439
  }
@@ -4281,41 +4466,41 @@ function validateSyncedTable(table, ctx) {
4281
4466
  const columns = table.columns ?? {};
4282
4467
  const names = Object.keys(columns);
4283
4468
  if (names.length === 0) return;
4284
- const primaryKeys = names.filter((name) => columns[name]?.primary_key);
4469
+ const primaryKeys = names.filter((name2) => columns[name2]?.primary_key);
4285
4470
  if (primaryKeys.length !== 1) {
4286
4471
  ctx.addIssue({ code: "custom", message: "exactly one column must be primary_key", path: ["columns"] });
4287
4472
  }
4288
4473
  validateRenames(columns, names, ctx);
4289
- for (const name of names) {
4290
- const column = columns[name];
4474
+ for (const name2 of names) {
4475
+ const column = columns[name2];
4291
4476
  if (!column) continue;
4292
4477
  const cast = column.cast ? castParts(column.cast) : null;
4293
- if (column.cast && cast?.column !== name) {
4478
+ if (column.cast && cast?.column !== name2) {
4294
4479
  ctx.addIssue({
4295
4480
  code: "custom",
4296
4481
  message: "cast must reference the column it is declared on",
4297
- path: ["columns", name, "cast"]
4482
+ path: ["columns", name2, "cast"]
4298
4483
  });
4299
4484
  }
4300
4485
  if (cast && cast.type !== column.type) {
4301
4486
  ctx.addIssue({
4302
4487
  code: "custom",
4303
4488
  message: `cast target '${cast.type}' must match the declared type '${column.type}'`,
4304
- path: ["columns", name, "cast"]
4489
+ path: ["columns", name2, "cast"]
4305
4490
  });
4306
4491
  }
4307
4492
  }
4308
4493
  }
4309
4494
  function validateRenames(columns, names, ctx) {
4310
4495
  const renameSources = /* @__PURE__ */ new Map();
4311
- for (const name of names) {
4312
- const renamedFrom = columns[name]?.renamed_from;
4496
+ for (const name2 of names) {
4497
+ const renamedFrom = columns[name2]?.renamed_from;
4313
4498
  if (!renamedFrom) continue;
4314
- if (renamedFrom === name || names.includes(renamedFrom)) {
4499
+ if (renamedFrom === name2 || names.includes(renamedFrom)) {
4315
4500
  ctx.addIssue({
4316
4501
  code: "custom",
4317
4502
  message: "renamed_from must name a column that no longer exists",
4318
- path: ["columns", name, "renamed_from"]
4503
+ path: ["columns", name2, "renamed_from"]
4319
4504
  });
4320
4505
  }
4321
4506
  const claimed = renameSources.get(renamedFrom);
@@ -4323,10 +4508,10 @@ function validateRenames(columns, names, ctx) {
4323
4508
  ctx.addIssue({
4324
4509
  code: "custom",
4325
4510
  message: `renamed_from '${renamedFrom}' is already claimed by '${claimed}'`,
4326
- path: ["columns", name, "renamed_from"]
4511
+ path: ["columns", name2, "renamed_from"]
4327
4512
  });
4328
4513
  }
4329
- renameSources.set(renamedFrom, name);
4514
+ renameSources.set(renamedFrom, name2);
4330
4515
  }
4331
4516
  }
4332
4517
  function validateColumnTable(table, ctx) {
@@ -4336,27 +4521,27 @@ function validateColumnTable(table, ctx) {
4336
4521
  ctx.addIssue({ code: "custom", message: "a table must declare columns or a source", path: ["columns"] });
4337
4522
  return;
4338
4523
  }
4339
- const primaryKeys = names.filter((name) => columns[name]?.primary_key);
4524
+ const primaryKeys = names.filter((name2) => columns[name2]?.primary_key);
4340
4525
  if (primaryKeys.length !== 1) {
4341
4526
  ctx.addIssue({ code: "custom", message: "exactly one column must be primary_key", path: ["columns"] });
4342
4527
  }
4343
4528
  validateRenames(columns, names, ctx);
4344
- for (const name of names) {
4345
- const column = columns[name];
4529
+ for (const name2 of names) {
4530
+ const column = columns[name2];
4346
4531
  if (!column) continue;
4347
4532
  const cast = column.cast ? castParts(column.cast) : null;
4348
- if (column.cast && cast?.column !== name) {
4533
+ if (column.cast && cast?.column !== name2) {
4349
4534
  ctx.addIssue({
4350
4535
  code: "custom",
4351
4536
  message: "cast must reference the column it is declared on",
4352
- path: ["columns", name, "cast"]
4537
+ path: ["columns", name2, "cast"]
4353
4538
  });
4354
4539
  }
4355
4540
  if (cast && cast.type !== column.type) {
4356
4541
  ctx.addIssue({
4357
4542
  code: "custom",
4358
4543
  message: `cast target '${cast.type}' must match the declared type '${column.type}'`,
4359
- path: ["columns", name, "cast"]
4544
+ path: ["columns", name2, "cast"]
4360
4545
  });
4361
4546
  }
4362
4547
  }
@@ -4381,22 +4566,22 @@ function validateColumnTable(table, ctx) {
4381
4566
  }
4382
4567
  function validateLinks(table, ctx) {
4383
4568
  const columnNames = Object.keys(table.columns ?? {});
4384
- for (const [name, link] of Object.entries(table.links ?? {})) {
4569
+ for (const [name2, link] of Object.entries(table.links ?? {})) {
4385
4570
  if (columnNames.length > 0 && !columnNames.includes(link.on)) {
4386
- ctx.addIssue({ code: "custom", message: `link references unknown column '${link.on}'`, path: ["links", name, "on"] });
4571
+ ctx.addIssue({ code: "custom", message: `link references unknown column '${link.on}'`, path: ["links", name2, "on"] });
4387
4572
  }
4388
4573
  if (link.enforce && link.to.includes(".")) {
4389
4574
  ctx.addIssue({
4390
4575
  code: "custom",
4391
4576
  message: "enforce is only valid for links inside the namespace; cross-boundary links stay soft",
4392
- path: ["links", name, "enforce"]
4577
+ path: ["links", name2, "enforce"]
4393
4578
  });
4394
4579
  }
4395
4580
  if (link.enforce && table.source) {
4396
4581
  ctx.addIssue({
4397
4582
  code: "custom",
4398
4583
  message: "a synced table cannot enforce foreign keys \u2014 its DDL is owned by the sync",
4399
- path: ["links", name, "enforce"]
4584
+ path: ["links", name2, "enforce"]
4400
4585
  });
4401
4586
  }
4402
4587
  }
@@ -4411,32 +4596,32 @@ function validateDerivedNameLengths(table, ctx) {
4411
4596
  });
4412
4597
  }
4413
4598
  for (const [position, index3] of (table.indexes ?? []).entries()) {
4414
- const name = indexName(table.table, index3);
4415
- if (name.length > MAX_IDENTIFIER_LENGTH) {
4599
+ const name2 = indexName(table.table, index3);
4600
+ if (name2.length > MAX_IDENTIFIER_LENGTH) {
4416
4601
  ctx.addIssue({
4417
4602
  code: "custom",
4418
- message: `derived index name '${name}' exceeds Postgres's ${MAX_IDENTIFIER_LENGTH}-byte identifier limit \u2014 set a shorter explicit name`,
4603
+ message: `derived index name '${name2}' exceeds Postgres's ${MAX_IDENTIFIER_LENGTH}-byte identifier limit \u2014 set a shorter explicit name`,
4419
4604
  path: ["indexes", position]
4420
4605
  });
4421
4606
  }
4422
4607
  }
4423
- for (const [name, link] of Object.entries(table.links ?? {})) {
4424
- const constraint = foreignKeyName(table.table, name);
4608
+ for (const [name2, link] of Object.entries(table.links ?? {})) {
4609
+ const constraint = foreignKeyName(table.table, name2);
4425
4610
  if (link.enforce && constraint.length > MAX_IDENTIFIER_LENGTH) {
4426
4611
  ctx.addIssue({
4427
4612
  code: "custom",
4428
4613
  message: `derived foreign-key name '${constraint}' exceeds Postgres's ${MAX_IDENTIFIER_LENGTH}-byte identifier limit \u2014 shorten the link or table name`,
4429
- path: ["links", name]
4614
+ path: ["links", name2]
4430
4615
  });
4431
4616
  }
4432
4617
  }
4433
- for (const name of Object.keys(table.actions ?? {})) {
4434
- const fnName = `action_${name}`;
4618
+ for (const name2 of Object.keys(table.actions ?? {})) {
4619
+ const fnName = `action_${name2}`;
4435
4620
  if (fnName.length > MAX_IDENTIFIER_LENGTH) {
4436
4621
  ctx.addIssue({
4437
4622
  code: "custom",
4438
4623
  message: `derived action function name '${fnName}' exceeds Postgres's ${MAX_IDENTIFIER_LENGTH}-byte identifier limit \u2014 shorten the action name`,
4439
- path: ["actions", name]
4624
+ path: ["actions", name2]
4440
4625
  });
4441
4626
  }
4442
4627
  }
@@ -4529,7 +4714,7 @@ function policyStatements(schema, table) {
4529
4714
  const policyName2 = (suffix) => quoteIdentifier(policyName(table.table, suffix));
4530
4715
  const statements = POLICY_SUFFIXES.map((suffix) => `DROP POLICY IF EXISTS ${policyName2(suffix)} ON ${qualified}`);
4531
4716
  const columnTypes = Object.fromEntries(
4532
- Object.entries(table.columns ?? {}).map(([name, column]) => [name, column.type])
4717
+ Object.entries(table.columns ?? {}).map(([name2, column]) => [name2, column.type])
4533
4718
  );
4534
4719
  const read = table.policies?.read;
4535
4720
  if (read) {
@@ -4592,12 +4777,19 @@ function syncedViewStatements({
4592
4777
  const readPolicyIr = readPolicyIrByTable?.get(table.table);
4593
4778
  const readPolicy = table.policies?.read;
4594
4779
  const whereClause = readPolicyIr ? ` WHERE ${compilePredIrToSql(readPolicyIr, {
4780
+ namespace: definition.namespace,
4595
4781
  columnTypes,
4596
4782
  columnNames: columnNamesByTable?.get(table.table)
4597
4783
  })}` : readPolicy ? ` WHERE ${compilePredicate(readPolicy.ast, narrowToV1ColumnTypes(columnTypes))}` : " WHERE false";
4598
4784
  if (backingPrivileges === "grant") {
4599
4785
  statements.push(`GRANT USAGE ON SCHEMA ${quoteIdentifier(physical2.schema)} TO ${owner}`);
4600
4786
  statements.push(`GRANT SELECT ON ${physicalTarget} TO ${owner}`);
4787
+ statements.push(`DO ${quoteLiteral(`BEGIN
4788
+ IF NOT (pg_catalog.has_schema_privilege(${quoteLiteral(executionOwnerRole)}, ${quoteLiteral(physical2.schema)}, 'USAGE')
4789
+ AND pg_catalog.has_table_privilege(${quoteLiteral(executionOwnerRole)}, ${quoteLiteral(physicalTarget)}, 'SELECT')) THEN
4790
+ RAISE EXCEPTION 'Synced backing owner lacks effective USAGE/SELECT; repair managed serving reader access before ORM apply' USING ERRCODE = '42501';
4791
+ END IF;
4792
+ END`)}`);
4601
4793
  }
4602
4794
  statements.push(
4603
4795
  `CREATE OR REPLACE VIEW ${viewName} AS SELECT * FROM ${physicalTarget}${whereClause}`
@@ -4613,8 +4805,8 @@ function mergeSyncedViewColumnTypes({
4613
4805
  columnNames
4614
4806
  }) {
4615
4807
  const fromTable = {};
4616
- for (const [name, def] of Object.entries(table.columns ?? {})) {
4617
- if (def?.type) fromTable[name] = def.type;
4808
+ for (const [name2, def] of Object.entries(table.columns ?? {})) {
4809
+ if (def?.type) fromTable[name2] = def.type;
4618
4810
  }
4619
4811
  if (columnNames) {
4620
4812
  for (const [logical, physical2] of Object.entries(columnNames)) {
@@ -4668,21 +4860,21 @@ function syncedBackingRevokeStatements({
4668
4860
  return statements;
4669
4861
  }
4670
4862
  var FACTORIES = {
4671
- uuid: (name) => uuid(name),
4672
- text: (name) => text(name),
4673
- integer: (name) => integer(name),
4863
+ uuid: (name2) => uuid(name2),
4864
+ text: (name2) => text(name2),
4865
+ integer: (name2) => integer(name2),
4674
4866
  // Mode 'bigint' keeps int8 lossless — mode 'number' silently rounds past
4675
4867
  // 2^53. The read executor serializes BigInt to string for JSON.
4676
- bigint: (name) => bigint(name, { mode: "bigint" }),
4677
- numeric: (name) => numeric(name),
4678
- double: (name) => doublePrecision(name),
4679
- boolean: (name) => boolean(name),
4680
- timestamptz: (name) => timestamp(name, { withTimezone: true }),
4681
- date: (name) => date(name),
4682
- jsonb: (name) => jsonb(name)
4868
+ bigint: (name2) => bigint(name2, { mode: "bigint" }),
4869
+ numeric: (name2) => numeric(name2),
4870
+ double: (name2) => doublePrecision(name2),
4871
+ boolean: (name2) => boolean(name2),
4872
+ timestamptz: (name2) => timestamp(name2, { withTimezone: true }),
4873
+ date: (name2) => date(name2),
4874
+ jsonb: (name2) => jsonb(name2)
4683
4875
  };
4684
- function buildColumn(name, definition) {
4685
- let column = FACTORIES[definition.type](name);
4876
+ function buildColumn(name2, definition) {
4877
+ let column = FACTORIES[definition.type](name2);
4686
4878
  if (definition.primary_key) column = column.primaryKey();
4687
4879
  if (definition.nullable === false && !definition.primary_key) column = column.notNull();
4688
4880
  if (definition.unique && !definition.primary_key) column = column.unique();
@@ -4713,7 +4905,7 @@ function buildDrizzleEntities(definition) {
4713
4905
  }
4714
4906
  function buildTable(schema, table, built) {
4715
4907
  const columns = Object.fromEntries(
4716
- Object.entries(table.columns ?? {}).map(([name, column]) => [name, buildColumn(name, column)])
4908
+ Object.entries(table.columns ?? {}).map(([name2, column]) => [name2, buildColumn(name2, column)])
4717
4909
  );
4718
4910
  const drizzleTable = schema.table(table.table, columns, (self) => [
4719
4911
  ...buildIndexes(table, self),
@@ -4723,21 +4915,21 @@ function buildTable(schema, table, built) {
4723
4915
  }
4724
4916
  function buildIndexes(table, self) {
4725
4917
  return (table.indexes ?? []).map((definition) => {
4726
- const name = indexName(table.table, definition);
4727
- const factory = definition.unique ? uniqueIndex(name) : index(name);
4918
+ const name2 = indexName(table.table, definition);
4919
+ const factory = definition.unique ? uniqueIndex(name2) : index(name2);
4728
4920
  const columns = definition.columns.map((column) => self[column]);
4729
4921
  return factory.on(...columns);
4730
4922
  });
4731
4923
  }
4732
4924
  function buildForeignKeys(table, self, built) {
4733
- return Object.entries(table.links ?? {}).filter(([, link]) => link.enforce).map(([name, link]) => {
4925
+ return Object.entries(table.links ?? {}).filter(([, link]) => link.enforce).map(([name2, link]) => {
4734
4926
  const target = link.to === table.table ? self : built.get(link.to);
4735
4927
  const targetColumn = target && findPrimaryKeyColumn(target);
4736
4928
  if (!target || !targetColumn) {
4737
- throw new OrmDefinitionError(`enforced link '${name}' on '${table.table}' has no built target '${link.to}'`);
4929
+ throw new OrmDefinitionError(`enforced link '${name2}' on '${table.table}' has no built target '${link.to}'`);
4738
4930
  }
4739
4931
  return foreignKey({
4740
- name: foreignKeyName(table.table, name),
4932
+ name: foreignKeyName(table.table, name2),
4741
4933
  columns: [self[link.on]],
4742
4934
  foreignColumns: [targetColumn]
4743
4935
  });
@@ -4794,21 +4986,21 @@ function diffStatements(previous, current) {
4794
4986
  function assertUnambiguousDiff(previous, current) {
4795
4987
  const previousTables = tablesOf(previous);
4796
4988
  const currentTables = tablesOf(current);
4797
- const removedTables = [...previousTables.keys()].filter((name) => !currentTables.has(name));
4798
- const addedTables = [...currentTables.keys()].filter((name) => !previousTables.has(name));
4989
+ const removedTables = [...previousTables.keys()].filter((name2) => !currentTables.has(name2));
4990
+ const addedTables = [...currentTables.keys()].filter((name2) => !previousTables.has(name2));
4799
4991
  if (removedTables.length > 0 && addedTables.length > 0) {
4800
4992
  throw new OrmDefinitionError(
4801
4993
  `ambiguous diff: table(s) added (${addedTables.join(", ")}) and removed (${removedTables.join(", ")}) in the same change \u2014 ship the add and the drop as separate changes`
4802
4994
  );
4803
4995
  }
4804
- for (const [name, previousColumns] of previousTables) {
4805
- const currentColumns = currentTables.get(name);
4996
+ for (const [name2, previousColumns] of previousTables) {
4997
+ const currentColumns = currentTables.get(name2);
4806
4998
  if (!currentColumns) continue;
4807
4999
  const removed = [...previousColumns].filter((column) => !currentColumns.has(column));
4808
5000
  const added = [...currentColumns].filter((column) => !previousColumns.has(column));
4809
5001
  if (removed.length > 0 && added.length > 0) {
4810
5002
  throw new OrmDefinitionError(
4811
- `ambiguous diff on '${name}': column(s) added (${added.join(", ")}) and removed (${removed.join(", ")}) in the same change \u2014 declare \`renamed_from\` for a rename, or ship the add and the drop as separate changes`
5003
+ `ambiguous diff on '${name2}': column(s) added (${added.join(", ")}) and removed (${removed.join(", ")}) in the same change \u2014 declare \`renamed_from\` for a rename, or ship the add and the drop as separate changes`
4812
5004
  );
4813
5005
  }
4814
5006
  }
@@ -4827,33 +5019,33 @@ function applyMigrationHints(previous, definition) {
4827
5019
  for (const table of columnTables(definition)) {
4828
5020
  const snapshotTable = findTable(adjusted, schemaName, table.table);
4829
5021
  if (!snapshotTable) continue;
4830
- for (const [name, column] of Object.entries(table.columns ?? {})) {
5022
+ for (const [name2, column] of Object.entries(table.columns ?? {})) {
4831
5023
  if (column.renamed_from) {
4832
5024
  const previousColumn = snapshotTable.columns[column.renamed_from];
4833
- if (previousColumn && snapshotTable.columns[name]) {
5025
+ if (previousColumn && snapshotTable.columns[name2]) {
4834
5026
  throw new OrmDefinitionError(
4835
- `'${table.table}.${name}' declares renamed_from '${column.renamed_from}', but both columns exist in the previous schema \u2014 a rename cannot overwrite a live column`
5027
+ `'${table.table}.${name2}' declares renamed_from '${column.renamed_from}', but both columns exist in the previous schema \u2014 a rename cannot overwrite a live column`
4836
5028
  );
4837
5029
  }
4838
5030
  if (previousColumn) {
4839
5031
  statements.push(
4840
- `ALTER TABLE ${qualified(table.table)} RENAME COLUMN ${quoteIdentifier(column.renamed_from)} TO ${quoteIdentifier(name)}`
5032
+ `ALTER TABLE ${qualified(table.table)} RENAME COLUMN ${quoteIdentifier(column.renamed_from)} TO ${quoteIdentifier(name2)}`
4841
5033
  );
4842
5034
  delete snapshotTable.columns[column.renamed_from];
4843
- snapshotTable.columns[name] = { ...previousColumn, name };
4844
- } else if (!snapshotTable.columns[name]) {
5035
+ snapshotTable.columns[name2] = { ...previousColumn, name: name2 };
5036
+ } else if (!snapshotTable.columns[name2]) {
4845
5037
  throw new OrmDefinitionError(
4846
- `'${table.table}.${name}' declares renamed_from '${column.renamed_from}', but the previous schema has neither column \u2014 check the declared source name`
5038
+ `'${table.table}.${name2}' declares renamed_from '${column.renamed_from}', but the previous schema has neither column \u2014 check the declared source name`
4847
5039
  );
4848
5040
  }
4849
5041
  }
4850
5042
  const cast = column.cast ? castParts(column.cast) : null;
4851
5043
  if (cast) {
4852
- const current = snapshotTable.columns[name];
5044
+ const current = snapshotTable.columns[name2];
4853
5045
  const targetType = sqlTypeName(column.type);
4854
5046
  if (current && current.type !== targetType) {
4855
5047
  statements.push(
4856
- `ALTER TABLE ${qualified(table.table)} ALTER COLUMN ${quoteIdentifier(name)} TYPE ${targetType} USING ${quoteIdentifier(name)}::${targetType}`
5048
+ `ALTER TABLE ${qualified(table.table)} ALTER COLUMN ${quoteIdentifier(name2)} TYPE ${targetType} USING ${quoteIdentifier(name2)}::${targetType}`
4857
5049
  );
4858
5050
  current.type = targetType;
4859
5051
  }
@@ -4894,8 +5086,8 @@ function materializedRefreshFunctions(canonical) {
4894
5086
  }
4895
5087
  return functions;
4896
5088
  }
4897
- function refreshFunctionSql({ schema, name, table, compute, columns, pk }) {
4898
- const fn = `${quoteIdentifier(schema)}.${quoteIdentifier(materializedRefreshFunctionName(name))}`;
5089
+ function refreshFunctionSql({ schema, name: name2, table, compute, columns, pk }) {
5090
+ const fn = `${quoteIdentifier(schema)}.${quoteIdentifier(materializedRefreshFunctionName(name2))}`;
4899
5091
  const target = `${quoteIdentifier(schema)}.${quoteIdentifier(table)}`;
4900
5092
  const source = `${quoteIdentifier(schema)}.${quoteIdentifier(compute)}`;
4901
5093
  const list = columns.map(quoteIdentifier).join(", ");
@@ -4904,7 +5096,7 @@ function refreshFunctionSql({ schema, name, table, compute, columns, pk }) {
4904
5096
  const matches = pk.map((column) => `c.${quoteIdentifier(column)} = m.${quoteIdentifier(column)}`).join(" AND ");
4905
5097
  const onConflict = others.length === 0 ? "DO NOTHING" : `DO UPDATE SET ${others.map((column) => `${quoteIdentifier(column)} = EXCLUDED.${quoteIdentifier(column)}`).join(", ")}
4906
5098
  WHERE (${others.map((column) => `m.${quoteIdentifier(column)}`).join(", ")}) IS DISTINCT FROM (${others.map((column) => `EXCLUDED.${quoteIdentifier(column)}`).join(", ")})`;
4907
- const lockKey = quoteLiteral(materializeLockKey(schema, name));
5099
+ const lockKey = quoteLiteral(materializeLockKey(schema, name2));
4908
5100
  return `CREATE OR REPLACE FUNCTION ${fn}(wait boolean DEFAULT false)
4909
5101
  RETURNS TABLE(upserted bigint, deleted bigint, locked boolean)
4910
5102
  LANGUAGE plpgsql
@@ -4942,12 +5134,12 @@ $orm_refresh$`;
4942
5134
  function refreshFunctionStatements({ namespace, previous, current }) {
4943
5135
  const schema = quoteIdentifier(ormSchemaName(namespace));
4944
5136
  const statements = [];
4945
- for (const name of Object.keys(previous).sort()) {
4946
- if (!current.has(name)) statements.push(`DROP FUNCTION IF EXISTS ${schema}.${quoteIdentifier(materializedRefreshFunctionName(name))}(boolean)`);
5137
+ for (const name2 of Object.keys(previous).sort()) {
5138
+ if (!current.has(name2)) statements.push(`DROP FUNCTION IF EXISTS ${schema}.${quoteIdentifier(materializedRefreshFunctionName(name2))}(boolean)`);
4947
5139
  }
4948
- for (const [name, create] of [...current].sort(([a], [b]) => a.localeCompare(b))) {
4949
- if (previous[name] === create) continue;
4950
- const fn = `${schema}.${quoteIdentifier(materializedRefreshFunctionName(name))}(boolean)`;
5140
+ for (const [name2, create] of [...current].sort(([a], [b]) => a.localeCompare(b))) {
5141
+ if (previous[name2] === create) continue;
5142
+ const fn = `${schema}.${quoteIdentifier(materializedRefreshFunctionName(name2))}(boolean)`;
4951
5143
  statements.push(create, `REVOKE ALL ON FUNCTION ${fn} FROM PUBLIC`);
4952
5144
  }
4953
5145
  return statements;
@@ -4955,21 +5147,21 @@ function refreshFunctionStatements({ namespace, previous, current }) {
4955
5147
 
4956
5148
  // src/engine/canonical2.ts
4957
5149
  var FACTORIES2 = {
4958
- uuid: (name) => uuid(name),
4959
- text: (name) => text(name),
4960
- integer: (name) => integer(name),
5150
+ uuid: (name2) => uuid(name2),
5151
+ text: (name2) => text(name2),
5152
+ integer: (name2) => integer(name2),
4961
5153
  // Mode 'bigint' keeps int8 lossless — mode 'number' silently rounds past
4962
5154
  // 2^53. The read executor serializes BigInt to string for JSON.
4963
- bigint: (name) => bigint(name, { mode: "bigint" }),
4964
- numeric: (name) => numeric(name),
4965
- double: (name) => doublePrecision(name),
4966
- boolean: (name) => boolean(name),
4967
- timestamptz: (name) => timestamp(name, { withTimezone: true }),
4968
- date: (name) => date(name),
4969
- jsonb: (name) => jsonb(name)
5155
+ bigint: (name2) => bigint(name2, { mode: "bigint" }),
5156
+ numeric: (name2) => numeric(name2),
5157
+ double: (name2) => doublePrecision(name2),
5158
+ boolean: (name2) => boolean(name2),
5159
+ timestamptz: (name2) => timestamp(name2, { withTimezone: true }),
5160
+ date: (name2) => date(name2),
5161
+ jsonb: (name2) => jsonb(name2)
4970
5162
  };
4971
5163
  var SCHEMA_IMPORT_KEY2 = "$schema";
4972
- var enumImportKey = (name) => `$enum_${name}`;
5164
+ var enumImportKey = (name2) => `$enum_${name2}`;
4973
5165
  var columnTablesV2 = (definition) => definition.tables.filter((table) => !table.source);
4974
5166
  function buildDrizzleEntitiesV2(definition, options = {}) {
4975
5167
  const schemaName = ormSchemaName(definition.namespace);
@@ -5271,9 +5463,9 @@ function buildTable2(schema, table, built, enums, byName, introspection) {
5271
5463
  throw new OrmDefinitionError(`table '${table.table}' declares no primaryKey`);
5272
5464
  }
5273
5465
  const columnNames = new Set(table.columns.map((column) => column.columnName));
5274
- for (const name of primaryKeyColumns) {
5275
- if (!columnNames.has(name)) {
5276
- throw new OrmDefinitionError(`primaryKey of '${table.table}' references unknown column '${name}'`);
5466
+ for (const name2 of primaryKeyColumns) {
5467
+ if (!columnNames.has(name2)) {
5468
+ throw new OrmDefinitionError(`primaryKey of '${table.table}' references unknown column '${name2}'`);
5277
5469
  }
5278
5470
  }
5279
5471
  const singlePrimaryKey = primaryKeyColumns.length === 1 ? primaryKeyColumns[0] : void 0;
@@ -5359,8 +5551,8 @@ function buildIndexes2(table, self) {
5359
5551
  throw new OrmDefinitionError(`index on '${table.table}' references unknown column '${column}'`);
5360
5552
  }
5361
5553
  }
5362
- const name = indexName(table.table, definition);
5363
- const factory = definition.unique ? uniqueIndex(name) : index(name);
5554
+ const name2 = indexName(table.table, definition);
5555
+ const factory = definition.unique ? uniqueIndex(name2) : index(name2);
5364
5556
  const columns = definition.columns.map((column) => self[column]);
5365
5557
  return factory.on(...columns);
5366
5558
  });
@@ -5439,33 +5631,33 @@ function applyMigrationHintsV2(previous, definition) {
5439
5631
  const snapshotTable = findTable2(adjusted, schemaName, table.table);
5440
5632
  if (!snapshotTable) continue;
5441
5633
  for (const column of table.columns) {
5442
- const name = column.columnName;
5634
+ const name2 = column.columnName;
5443
5635
  if (column.renamedFrom) {
5444
5636
  const previousColumn = snapshotTable.columns[column.renamedFrom];
5445
- if (previousColumn && snapshotTable.columns[name]) {
5637
+ if (previousColumn && snapshotTable.columns[name2]) {
5446
5638
  throw new OrmDefinitionError(
5447
- `'${table.table}.${name}' declares renamedFrom '${column.renamedFrom}', but both columns exist in the previous schema \u2014 a rename cannot overwrite a live column`
5639
+ `'${table.table}.${name2}' declares renamedFrom '${column.renamedFrom}', but both columns exist in the previous schema \u2014 a rename cannot overwrite a live column`
5448
5640
  );
5449
5641
  }
5450
5642
  if (previousColumn) {
5451
5643
  statements.push(
5452
- `ALTER TABLE ${qualified(table.table)} RENAME COLUMN ${quoteIdentifier(column.renamedFrom)} TO ${quoteIdentifier(name)}`
5644
+ `ALTER TABLE ${qualified(table.table)} RENAME COLUMN ${quoteIdentifier(column.renamedFrom)} TO ${quoteIdentifier(name2)}`
5453
5645
  );
5454
5646
  delete snapshotTable.columns[column.renamedFrom];
5455
- snapshotTable.columns[name] = { ...previousColumn, name };
5456
- } else if (!snapshotTable.columns[name]) {
5647
+ snapshotTable.columns[name2] = { ...previousColumn, name: name2 };
5648
+ } else if (!snapshotTable.columns[name2]) {
5457
5649
  throw new OrmDefinitionError(
5458
- `'${table.table}.${name}' declares renamedFrom '${column.renamedFrom}', but the previous schema has neither column \u2014 check the declared source name`
5650
+ `'${table.table}.${name2}' declares renamedFrom '${column.renamedFrom}', but the previous schema has neither column \u2014 check the declared source name`
5459
5651
  );
5460
5652
  }
5461
5653
  }
5462
5654
  const cast = column.cast ? castParts(column.cast) : null;
5463
5655
  if (cast) {
5464
- const current = snapshotTable.columns[name];
5656
+ const current = snapshotTable.columns[name2];
5465
5657
  const { snapshotType, sqlType } = castTargetTypes(column, enumsByName, schemaName, table.table);
5466
5658
  if (current && current.type !== snapshotType) {
5467
5659
  statements.push(
5468
- `ALTER TABLE ${qualified(table.table)} ALTER COLUMN ${quoteIdentifier(name)} TYPE ${sqlType} USING ${quoteIdentifier(name)}::${sqlType}`
5660
+ `ALTER TABLE ${qualified(table.table)} ALTER COLUMN ${quoteIdentifier(name2)} TYPE ${sqlType} USING ${quoteIdentifier(name2)}::${sqlType}`
5469
5661
  );
5470
5662
  current.type = snapshotType;
5471
5663
  }
@@ -5476,8 +5668,8 @@ function applyMigrationHintsV2(previous, definition) {
5476
5668
  }
5477
5669
  function castTargetTypes(column, enums, schemaName, table) {
5478
5670
  if (typeof column.type === "string") {
5479
- const name = sqlTypeName(column.type);
5480
- return { snapshotType: name, sqlType: name };
5671
+ const name2 = sqlTypeName(column.type);
5672
+ return { snapshotType: name2, sqlType: name2 };
5481
5673
  }
5482
5674
  const enumName = column.type.enum;
5483
5675
  if (!enums.has(enumName)) {
@@ -5562,11 +5754,11 @@ async function planWithViewRecreation({
5562
5754
  })
5563
5755
  });
5564
5756
  const dropOrder = topologicalViewNames(
5565
- new Set([...affected].filter((name) => previousViews.has(name))),
5757
+ new Set([...affected].filter((name2) => previousViews.has(name2))),
5566
5758
  previousDependencies
5567
5759
  ).reverse();
5568
5760
  const createOrder = topologicalViewNames(
5569
- new Set([...affected].filter((name) => currentViews.has(name))),
5761
+ new Set([...affected].filter((name2) => currentViews.has(name2))),
5570
5762
  currentDependencies
5571
5763
  );
5572
5764
  const dropDdl = await generatedViewStatements({
@@ -5583,14 +5775,14 @@ async function planWithViewRecreation({
5583
5775
  });
5584
5776
  const currentViewDefinitions = new Map((canonical.views ?? []).map((view) => [view.view, view]));
5585
5777
  const statements = [
5586
- ...dropOrder.map((name) => ({ kind: "ddl", sql: requiredViewStatement(dropDdl, name, schema, "DROP") })),
5778
+ ...dropOrder.map((name2) => ({ kind: "ddl", sql: requiredViewStatement(dropDdl, name2, schema, "DROP") })),
5587
5779
  ...hints.statements.map((statement) => ({ kind: "hint", sql: statement })),
5588
5780
  ...baseDdl.map((statement) => ({ kind: "ddl", sql: statement.replace(/;\s*$/, "") })),
5589
5781
  ...foreignKeyTimingStatements(canonical, previous, baseDdl).map((sql7) => ({ kind: "ddl", sql: sql7 })),
5590
- ...createOrder.map((name) => ({ kind: "ddl", sql: requiredViewStatement(createDdl, name, schema, "CREATE") })),
5591
- ...createOrder.map((name) => {
5592
- const view = currentViewDefinitions.get(name);
5593
- if (!view) throw new OrmDefinitionError(`missing canonical definition for view '${name}'`);
5782
+ ...createOrder.map((name2) => ({ kind: "ddl", sql: requiredViewStatement(createDdl, name2, schema, "CREATE") })),
5783
+ ...createOrder.map((name2) => {
5784
+ const view = currentViewDefinitions.get(name2);
5785
+ if (!view) throw new OrmDefinitionError(`missing canonical definition for view '${name2}'`);
5594
5786
  return { kind: "ddl", sql: validateViewCatalogStatement({ canonical, view, schema }) };
5595
5787
  }),
5596
5788
  ...refreshFunctionStatements({
@@ -5620,9 +5812,9 @@ function foreignKeyTimingStatements(canonical, previous, baseDdl) {
5620
5812
  }
5621
5813
  return result;
5622
5814
  }
5623
- function foreignKeyTimingSql(schema, table, name, timing) {
5815
+ function foreignKeyTimingSql(schema, table, name2, timing) {
5624
5816
  const clause = timing === void 0 ? "NOT DEFERRABLE" : timing === "initially-deferred" ? "DEFERRABLE INITIALLY DEFERRED" : "DEFERRABLE INITIALLY IMMEDIATE";
5625
- return `ALTER TABLE ${quoteIdentifier(schema)}.${quoteIdentifier(table)} ALTER CONSTRAINT ${quoteIdentifier(name)} ${clause}`;
5817
+ return `ALTER TABLE ${quoteIdentifier(schema)}.${quoteIdentifier(table)} ALTER CONSTRAINT ${quoteIdentifier(name2)} ${clause}`;
5626
5818
  }
5627
5819
  function validateViewCatalogStatement({
5628
5820
  canonical,
@@ -5764,7 +5956,7 @@ function viewReach({
5764
5956
  if (viewRecreation === "all-on-base-change") return "all";
5765
5957
  if (baseDdl.some((statement) => DROPS_TYPE.test(statement))) return "all";
5766
5958
  const dependencies = snapshotViewDependencies(adjusted);
5767
- if ([...snapshotViews(adjusted).keys()].some((name) => dependencies[name] === void 0)) return "all";
5959
+ if ([...snapshotViews(adjusted).keys()].some((name2) => dependencies[name2] === void 0)) return "all";
5768
5960
  return baseChangesReachingViews({ previous, adjusted, current });
5769
5961
  }
5770
5962
  var SNAPSHOT_BOOKKEEPING = /* @__PURE__ */ new Set(["id", "prevId", "version", "dialect", "_meta", "views", "_sequenceOrm", "enums"]);
@@ -5813,8 +6005,8 @@ function tableChangeReachesViews({ was, is: is2 }) {
5813
6005
  if (field === "columns" || VIEW_SAFE_TABLE_FIELDS.has(field)) continue;
5814
6006
  if (stableJson(was[field]) !== stableJson(is2[field])) return true;
5815
6007
  }
5816
- return Object.entries(was.columns).some(([name, column]) => {
5817
- const next = is2.columns[name];
6008
+ return Object.entries(was.columns).some(([name2, column]) => {
6009
+ const next = is2.columns[name2];
5818
6010
  if (!next) return true;
5819
6011
  return [.../* @__PURE__ */ new Set([...Object.keys(column), ...Object.keys(next)])].some(
5820
6012
  (field) => !VIEW_SAFE_COLUMN_FIELDS.has(field) && stableJson(column[field]) !== stableJson(next[field])
@@ -5840,22 +6032,22 @@ function affectedViewNames({
5840
6032
  }) {
5841
6033
  const allNames = /* @__PURE__ */ new Set([...previousViews.keys(), ...currentViews.keys()]);
5842
6034
  if (reach === "all") return allNames;
5843
- const dependenciesOf = (name) => /* @__PURE__ */ new Set([...previousDependencies[name] ?? [], ...currentDependencies[name] ?? []]);
6035
+ const dependenciesOf = (name2) => /* @__PURE__ */ new Set([...previousDependencies[name2] ?? [], ...currentDependencies[name2] ?? []]);
5844
6036
  const affected = new Set(
5845
- [...allNames].filter((name) => {
5846
- const before = previousViews.get(name);
5847
- const after = currentViews.get(name);
6037
+ [...allNames].filter((name2) => {
6038
+ const before = previousViews.get(name2);
6039
+ const after = currentViews.get(name2);
5848
6040
  if (before === void 0 || after === void 0 || stableJson(before) !== stableJson(after)) return true;
5849
- return [...dependenciesOf(name)].some((dependency) => reach.has(dependency));
6041
+ return [...dependenciesOf(name2)].some((dependency) => reach.has(dependency));
5850
6042
  })
5851
6043
  );
5852
6044
  let grew = true;
5853
6045
  while (grew) {
5854
6046
  grew = false;
5855
- for (const name of allNames) {
5856
- if (affected.has(name)) continue;
5857
- if ([...dependenciesOf(name)].some((dependency) => affected.has(dependency))) {
5858
- affected.add(name);
6047
+ for (const name2 of allNames) {
6048
+ if (affected.has(name2)) continue;
6049
+ if ([...dependenciesOf(name2)].some((dependency) => affected.has(dependency))) {
6050
+ affected.add(name2);
5859
6051
  grew = true;
5860
6052
  }
5861
6053
  }
@@ -5866,13 +6058,13 @@ function topologicalViewNames(names, dependencies) {
5866
6058
  const remaining = new Set(names);
5867
6059
  const ordered = [];
5868
6060
  while (remaining.size > 0) {
5869
- const ready = [...remaining].filter((name) => (dependencies[name] ?? []).every((dependency) => !remaining.has(dependency))).sort();
6061
+ const ready = [...remaining].filter((name2) => (dependencies[name2] ?? []).every((dependency) => !remaining.has(dependency))).sort();
5870
6062
  if (ready.length === 0) {
5871
6063
  throw new OrmDefinitionError(`view dependencies form a cycle among: ${[...remaining].sort().join(", ")}`);
5872
6064
  }
5873
- for (const name of ready) {
5874
- ordered.push(name);
5875
- remaining.delete(name);
6065
+ for (const name2 of ready) {
6066
+ ordered.push(name2);
6067
+ remaining.delete(name2);
5876
6068
  }
5877
6069
  }
5878
6070
  return ordered;
@@ -5890,18 +6082,18 @@ async function generatedViewStatements({
5890
6082
  holder.views = Object.fromEntries(Object.entries(views).filter(([, view]) => !names.has(view.name)));
5891
6083
  const generated = mode === "drop" ? await diffStatements(snapshot, without) : await diffStatements(without, snapshot);
5892
6084
  const statements = /* @__PURE__ */ new Map();
5893
- for (const name of names) {
5894
- const qualified = `${quoteIdentifier(schema)}.${quoteIdentifier(name)}`;
6085
+ for (const name2 of names) {
6086
+ const qualified = `${quoteIdentifier(schema)}.${quoteIdentifier(name2)}`;
5895
6087
  const prefix = mode === "drop" ? "DROP VIEW" : "CREATE VIEW";
5896
6088
  const statement = generated.find((candidate) => candidate.trimStart().startsWith(`${prefix} ${qualified}`));
5897
- if (statement) statements.set(name, statement.replace(/;\s*$/, ""));
6089
+ if (statement) statements.set(name2, statement.replace(/;\s*$/, ""));
5898
6090
  }
5899
6091
  return statements;
5900
6092
  }
5901
- function requiredViewStatement(statements, name, schema, operation) {
5902
- const statement = statements.get(name);
6093
+ function requiredViewStatement(statements, name2, schema, operation) {
6094
+ const statement = statements.get(name2);
5903
6095
  if (!statement) {
5904
- throw new OrmDefinitionError(`drizzle-kit did not generate ${operation} VIEW for '${schema}.${name}'`);
6096
+ throw new OrmDefinitionError(`drizzle-kit did not generate ${operation} VIEW for '${schema}.${name2}'`);
5905
6097
  }
5906
6098
  return statement;
5907
6099
  }
@@ -6147,9 +6339,13 @@ function renderOrmMigrationExport(exported) {
6147
6339
  if (Buffer.byteLength(text4, "utf8") > ORM_MIGRATION_EXPORT_MAX_BYTES) throw new Error("ORM migration export exceeds the size limit");
6148
6340
  return text4;
6149
6341
  }
6150
- var IR_VERSION = 2;
6342
+ var IR_VERSION = 5;
6151
6343
  var LEGACY_IR_VERSION = 1;
6152
- var irVersionSchema = z.union([z.literal(LEGACY_IR_VERSION), z.literal(IR_VERSION)]);
6344
+ var GUARDED_IR_VERSION = 2;
6345
+ var COMPOSED_IR_VERSION = 3;
6346
+ var SQL_IR_VERSION = 4;
6347
+ var RUNTIME_SQL_IR_VERSION = 5;
6348
+ var irVersionSchema = z.union([z.literal(LEGACY_IR_VERSION), z.literal(GUARDED_IR_VERSION), z.literal(COMPOSED_IR_VERSION), z.literal(SQL_IR_VERSION), z.literal(RUNTIME_SQL_IR_VERSION)]);
6153
6349
  var operationVersionSchema = z.object({ irVersion: irVersionSchema });
6154
6350
  function requiredArtifactIrVersion(operations) {
6155
6351
  let required = LEGACY_IR_VERSION;
@@ -6201,8 +6397,8 @@ var predIrSchema = z.lazy(
6201
6397
  value: z.number(),
6202
6398
  where: predIrSchema.optional()
6203
6399
  }),
6204
- z.object({ kind: z.literal("capability"), key: z.string() }),
6205
- z.object({ kind: z.literal("role"), key: z.string() }),
6400
+ z.object({ kind: z.literal("capability"), key: z.string(), namespace: z.string().optional() }),
6401
+ z.object({ kind: z.literal("role"), key: z.string(), namespace: z.string().optional() }),
6206
6402
  z.object({ kind: z.literal("dynamicFilter"), slot: z.string() }),
6207
6403
  z.object({ kind: z.literal("const"), value: z.boolean() })
6208
6404
  ])
@@ -6429,7 +6625,31 @@ var variableIrSchema = z.object({
6429
6625
  /** Absent = no default declared; see {@link variableDefaultIrSchema}. */
6430
6626
  defaultValue: variableDefaultIrSchema.optional()
6431
6627
  });
6628
+ var sqlColumnSchema = z.object({ name: z.string(), type: z.enum(["text", "boolean", "integer", "bigint", "numeric", "double", "uuid", "date", "timestamptz"]), nullable: z.boolean() });
6432
6629
  var compiledOperationSchema = z.object({
6630
+ language: z.literal("sql").optional(),
6631
+ /** Server-compiled object catalog and permission ceiling, never caller SQL. */
6632
+ sqlQuery: z.object({
6633
+ catalog: z.object({
6634
+ identity: z.string(),
6635
+ objects: z.array(z.object({
6636
+ ref: z.string(),
6637
+ table: z.string(),
6638
+ columns: z.array(sqlColumnSchema.extend({ type: z.string() })).min(1),
6639
+ scan: z.string().min(1),
6640
+ read: z.array(z.string()).min(1)
6641
+ }).strict()).min(1).max(256)
6642
+ }).strict(),
6643
+ read: z.array(z.string()).min(1).max(256),
6644
+ maxRows: z.number().int().min(1).max(1e4)
6645
+ }).strict().optional(),
6646
+ sql: z.object({
6647
+ text: z.string().min(1).max(1048576),
6648
+ columns: z.array(sqlColumnSchema).min(1).max(256),
6649
+ parameters: z.array(z.string()).max(128),
6650
+ read: z.array(z.string()).min(1).max(256),
6651
+ maxRows: z.number().int().min(1).max(1e4)
6652
+ }).strict().optional(),
6433
6653
  irVersion: irVersionSchema,
6434
6654
  name: z.string(),
6435
6655
  opHash: z.string().regex(/^sha256:[0-9a-f]{64}$/),
@@ -6441,8 +6661,16 @@ var compiledOperationSchema = z.object({
6441
6661
  variables: z.array(variableIrSchema),
6442
6662
  /** Every table the op touches — data-token scoping + audit. */
6443
6663
  tableSet: z.array(z.string()).min(1),
6444
- roots: z.array(rootIrSchema).min(1)
6664
+ roots: z.array(rootIrSchema)
6445
6665
  }).superRefine((operation, ctx) => {
6666
+ if (operation.language === "sql") {
6667
+ const validPlan = operation.sqlQuery ? !operation.sql && operation.irVersion === RUNTIME_SQL_IR_VERSION : !!operation.sql && operation.irVersion === SQL_IR_VERSION;
6668
+ if (!validPlan || operation.kind !== "query" || operation.roots.length !== 0 || !operation.requires?.capability) {
6669
+ ctx.addIssue({ code: "custom", message: "SQL operations require a query-only v4 plan or v5 runtime contract, capability, and no GraphQL roots" });
6670
+ }
6671
+ } else if (operation.sql || operation.sqlQuery || operation.roots.length === 0) {
6672
+ ctx.addIssue({ code: "custom", message: "GraphQL operations require roots and cannot carry SQL" });
6673
+ }
6446
6674
  for (const [index3, root] of operation.roots.entries()) {
6447
6675
  if (root.kind !== "mutation" || root.assertAffectedRows === void 0) continue;
6448
6676
  if (operation.irVersion < 2 || operation.kind !== "mutation" || root.includeIf !== void 0) {
@@ -6489,11 +6717,16 @@ var resolvedMetaIrSchema = z.object({
6489
6717
  });
6490
6718
  var tableMetaIrSchema = z.object({
6491
6719
  table: z.string(),
6720
+ namespace: z.string().optional(),
6721
+ dependencies: z.array(z.string()).optional(),
6722
+ foreignReferences: z.array(z.object({ column: z.string(), target: z.string(), targetColumn: z.string() })).optional(),
6723
+ exportRead: z.union([z.literal(true), z.object({ capability: z.string() }), z.object({ role: z.string() })]).optional(),
6724
+ exportWrite: z.union([z.literal(true), z.object({ capability: z.string() }), z.object({ role: z.string() })]).optional(),
6492
6725
  schema: z.string(),
6493
6726
  typename: z.string(),
6494
6727
  /**
6495
6728
  * True when statements over this relation evaluate a claims-gated synced
6496
- * view: synced twins (`source: gold.*`) materialize as views whose baked
6729
+ * view: synced twins (`source: schema.table`) materialize as views whose baked
6497
6730
  * policy reads `current_setting('request.jwt.claims')`, and namespace views
6498
6731
  * inherit the gate transitively through their declared dependencies. The
6499
6732
  * executor must stamp that GUC (transaction-scoped) before any statement
@@ -6552,13 +6785,21 @@ var compiledArtifactSchema = z.object({
6552
6785
  irVersion: irVersionSchema,
6553
6786
  namespace: z.string(),
6554
6787
  schemaHash: z.string(),
6788
+ ownSchemaHash: z.string().optional(),
6789
+ dependencies: z.record(z.string(), z.string()).optional(),
6790
+ readPolicies: z.record(z.string(), predIrSchema).optional(),
6555
6791
  opsHash: z.string(),
6792
+ /** Apply-observed synced objects without a serving backing; not part of the authored schema hash. */
6793
+ unbackedTables: z.array(z.string()).optional(),
6556
6794
  tables: z.record(z.string(), tableMetaIrSchema),
6557
6795
  operations: z.record(z.string(), compiledOperationSchema)
6558
6796
  }).superRefine((artifact, ctx) => {
6559
- for (const [name, operation] of Object.entries(artifact.operations)) {
6797
+ if (Object.keys(artifact.dependencies ?? {}).length > 0 && artifact.irVersion < COMPOSED_IR_VERSION) {
6798
+ ctx.addIssue({ code: "custom", path: ["irVersion"], message: "cross-namespace dependencies require IR v3" });
6799
+ }
6800
+ for (const [name2, operation] of Object.entries(artifact.operations)) {
6560
6801
  if (operation.irVersion > artifact.irVersion) {
6561
- ctx.addIssue({ code: "custom", path: ["operations", name, "irVersion"], message: "operation requires a newer IR version than its artifact" });
6802
+ ctx.addIssue({ code: "custom", path: ["operations", name2, "irVersion"], message: "operation requires a newer IR version than its artifact" });
6562
6803
  }
6563
6804
  }
6564
6805
  });
@@ -6571,7 +6812,7 @@ var IrVersionError = class extends Error {
6571
6812
  function normalizeIr(raw) {
6572
6813
  if (!raw || typeof raw !== "object") throw new IrVersionError(void 0);
6573
6814
  const version = raw.irVersion;
6574
- if (version !== LEGACY_IR_VERSION && version !== IR_VERSION) throw new IrVersionError(version);
6815
+ if (!irVersionSchema.safeParse(version).success) throw new IrVersionError(version);
6575
6816
  return compiledArtifactSchema.parse(raw);
6576
6817
  }
6577
6818
  function indexByHash(artifact) {
@@ -6604,10 +6845,10 @@ function buildNamespaceDefinition(files, config) {
6604
6845
  }
6605
6846
  const actionsSeen = /* @__PURE__ */ new Map();
6606
6847
  for (const { file, table } of files) {
6607
- for (const name of Object.keys(table.actions ?? {})) {
6608
- const existing = actionsSeen.get(name);
6609
- if (existing) throw new OrmDefinitionError(`action '${name}' is already defined in ${existing}`, file);
6610
- actionsSeen.set(name, file);
6848
+ for (const name2 of Object.keys(table.actions ?? {})) {
6849
+ const existing = actionsSeen.get(name2);
6850
+ if (existing) throw new OrmDefinitionError(`action '${name2}' is already defined in ${existing}`, file);
6851
+ actionsSeen.set(name2, file);
6611
6852
  }
6612
6853
  }
6613
6854
  const capabilities = config?.capabilities ? { roles: config.capabilities.roles ?? EMPTY_CAPABILITIES.roles, uses: config.capabilities.uses ?? [] } : EMPTY_CAPABILITIES;
@@ -6650,12 +6891,12 @@ function validateActionValidates(files, byName) {
6650
6891
  }
6651
6892
  function validateIndexNames(files) {
6652
6893
  const seen = /* @__PURE__ */ new Map();
6653
- const claim = (name, label, file) => {
6654
- const existing = seen.get(name);
6894
+ const claim = (name2, label, file) => {
6895
+ const existing = seen.get(name2);
6655
6896
  if (existing) {
6656
- throw new OrmDefinitionError(`relation name '${name}' (${label}) collides with ${existing}`, file);
6897
+ throw new OrmDefinitionError(`relation name '${name2}' (${label}) collides with ${existing}`, file);
6657
6898
  }
6658
- seen.set(name, `${label} (${file})`);
6899
+ seen.set(name2, `${label} (${file})`);
6659
6900
  };
6660
6901
  for (const { file, table } of files) {
6661
6902
  claim(table.table, `table '${table.table}'`, file);
@@ -6663,9 +6904,9 @@ function validateIndexNames(files) {
6663
6904
  for (const { file, table } of files) {
6664
6905
  if (table.source) continue;
6665
6906
  claim(`${table.table}_pkey`, `implicit primary-key index of '${table.table}'`, file);
6666
- for (const [name, column] of Object.entries(table.columns ?? {})) {
6907
+ for (const [name2, column] of Object.entries(table.columns ?? {})) {
6667
6908
  if (column.unique && !column.primary_key) {
6668
- claim(`${table.table}_${name}_unique`, `implicit unique constraint of '${table.table}.${name}'`, file);
6909
+ claim(`${table.table}_${name2}_unique`, `implicit unique constraint of '${table.table}.${name2}'`, file);
6669
6910
  }
6670
6911
  }
6671
6912
  }
@@ -6677,20 +6918,20 @@ function validateIndexNames(files) {
6677
6918
  }
6678
6919
  function validateLocalLinks(files, byName) {
6679
6920
  for (const { file, table } of files) {
6680
- for (const [name, link] of Object.entries(table.links ?? {})) {
6921
+ for (const [name2, link] of Object.entries(table.links ?? {})) {
6681
6922
  if (isQualifiedReference(link.to)) continue;
6682
6923
  const target = byName.get(link.to);
6683
6924
  if (!target) {
6684
- throw new OrmDefinitionError(`link '${name}' references unknown table '${link.to}'`, file);
6925
+ throw new OrmDefinitionError(`link '${name2}' references unknown table '${link.to}'`, file);
6685
6926
  }
6686
6927
  if (link.enforce && target.source) {
6687
- throw new OrmDefinitionError(`link '${name}' cannot enforce a foreign key onto a synced table`, file);
6928
+ throw new OrmDefinitionError(`link '${name2}' cannot enforce a foreign key onto a synced table`, file);
6688
6929
  }
6689
6930
  const sourceType = table.columns?.[link.on]?.type;
6690
6931
  const targetPrimaryKey = Object.values(target.columns ?? {}).find((column) => column.primary_key);
6691
6932
  if (sourceType && targetPrimaryKey && columnTypeGroup(sourceType) !== columnTypeGroup(targetPrimaryKey.type)) {
6692
6933
  throw new OrmDefinitionError(
6693
- `link '${name}' can never join: '${link.on}' is ${sourceType} but '${link.to}' has a ${targetPrimaryKey.type} primary key`,
6934
+ `link '${name2}' can never join: '${link.on}' is ${sourceType} but '${link.to}' has a ${targetPrimaryKey.type} primary key`,
6694
6935
  file
6695
6936
  );
6696
6937
  }
@@ -6770,7 +7011,7 @@ function parseYaml(file, contents) {
6770
7011
  throw new OrmDefinitionError(error instanceof Error ? error.message : "invalid YAML", file);
6771
7012
  }
6772
7013
  }
6773
- var isDefinitionFile = (name) => DEFINITION_FILE_EXTENSIONS.some((extension) => extname(name) === extension);
7014
+ var isDefinitionFile = (name2) => DEFINITION_FILE_EXTENSIONS.some((extension) => extname(name2) === extension);
6774
7015
  async function listDefinitionFiles(dir) {
6775
7016
  const entries = await readdir(dir, { withFileTypes: true });
6776
7017
  return entries.filter((entry) => entry.isFile() && isDefinitionFile(entry.name)).map((entry) => entry.name).sort();
@@ -6864,13 +7105,13 @@ async function readMigrationSql(dir, entry) {
6864
7105
  var checksumOf = (text4) => createHash("sha256").update(text4).digest("hex");
6865
7106
  var migrationName = (ordinal, contentHash) => `${pad(ordinal)}_${contentHash.slice(0, 12)}`;
6866
7107
  function renderMigrationSql({
6867
- name,
7108
+ name: name2,
6868
7109
  namespace,
6869
7110
  contentHash,
6870
7111
  plan
6871
7112
  }) {
6872
7113
  const header = [
6873
- `-- ${name}`,
7114
+ `-- ${name2}`,
6874
7115
  `-- namespace: ${namespace}`,
6875
7116
  `-- content hash: ${contentHash}`,
6876
7117
  "-- generated by `seq-studio orm diff` \u2014 review and commit, do not edit"
@@ -6886,13 +7127,13 @@ async function writeMigration({
6886
7127
  }) {
6887
7128
  const tip = workspace.journal.entries.at(-1);
6888
7129
  const ordinal = (tip?.ordinal ?? 0) + 1;
6889
- const name = migrationName(ordinal, contentHash);
6890
- const sql7 = renderMigrationSql({ name, namespace: workspace.journal.namespace, contentHash, plan });
7130
+ const name2 = migrationName(ordinal, contentHash);
7131
+ const sql7 = renderMigrationSql({ name: name2, namespace: workspace.journal.namespace, contentHash, plan });
6891
7132
  const metaDir = join(dir, MIGRATIONS_DIRNAME, META_DIRNAME);
6892
7133
  await mkdir(metaDir, { recursive: true });
6893
7134
  const snapshotText = `${JSON.stringify(plan.snapshot, null, 2)}
6894
7135
  `;
6895
- await writeFile(join(dir, MIGRATIONS_DIRNAME, `${name}.sql`), sql7);
7136
+ await writeFile(join(dir, MIGRATIONS_DIRNAME, `${name2}.sql`), sql7);
6896
7137
  await writeFile(join(metaDir, `${pad(ordinal)}.snapshot.json`), snapshotText);
6897
7138
  const journal = {
6898
7139
  ...workspace.journal,
@@ -6900,7 +7141,7 @@ async function writeMigration({
6900
7141
  ...workspace.journal.entries,
6901
7142
  {
6902
7143
  ordinal,
6903
- name,
7144
+ name: name2,
6904
7145
  content_hash: contentHash,
6905
7146
  previous_content_hash: tip?.content_hash ?? null,
6906
7147
  checksum: checksumOf(sql7),
@@ -6911,7 +7152,7 @@ async function writeMigration({
6911
7152
  };
6912
7153
  await writeFile(join(metaDir, JOURNAL_FILENAME), `${JSON.stringify(journal, null, 2)}
6913
7154
  `);
6914
- return { name, ordinal, destructive };
7155
+ return { name: name2, ordinal, destructive };
6915
7156
  }
6916
7157
  var pad = (ordinal) => String(ordinal).padStart(4, "0");
6917
7158
  function parseJson(path, raw) {
@@ -7085,15 +7326,15 @@ function convertV1DefinitionToCanonical(definition) {
7085
7326
  }
7086
7327
  function convertTable(table) {
7087
7328
  const columns = Object.entries(table.columns ?? {});
7088
- const primaryKey2 = columns.filter(([, column]) => column.primary_key).map(([name]) => name);
7329
+ const primaryKey2 = columns.filter(([, column]) => column.primary_key).map(([name2]) => name2);
7089
7330
  return {
7090
7331
  table: table.table,
7091
7332
  description: table.description,
7092
7333
  source: table.source,
7093
- columns: columns.map(([name, column]) => convertColumn(name, column)),
7334
+ columns: columns.map(([name2, column]) => convertColumn(name2, column)),
7094
7335
  // Synced tables may declare a typed column/PK contract; untyped remain empty.
7095
7336
  primaryKey: primaryKey2.length > 0 ? primaryKey2 : void 0,
7096
- links: Object.entries(table.links ?? {}).map(([name, link]) => convertLink(table.table, name, link)),
7337
+ links: Object.entries(table.links ?? {}).map(([name2, link]) => convertLink(table.table, name2, link)),
7097
7338
  indexes: (table.indexes ?? []).map((index3) => ({
7098
7339
  columns: [...index3.columns],
7099
7340
  unique: index3.unique ?? false,
@@ -7110,11 +7351,11 @@ function convertTable(table) {
7110
7351
  actions: []
7111
7352
  };
7112
7353
  }
7113
- function convertColumn(name, column) {
7354
+ function convertColumn(name2, column) {
7114
7355
  const isDefaultFn = column.default !== void 0 && isFunctionDefault(column.default, column.type);
7115
7356
  return {
7116
- name,
7117
- columnName: name,
7357
+ name: name2,
7358
+ columnName: name2,
7118
7359
  type: column.type,
7119
7360
  nullable: column.primary_key ? false : column.nullable !== false,
7120
7361
  unique: column.unique === true,
@@ -7128,14 +7369,14 @@ function convertColumn(name, column) {
7128
7369
  deprecated: column.deprecated === true
7129
7370
  };
7130
7371
  }
7131
- function convertLink(table, name, link) {
7372
+ function convertLink(table, name2, link) {
7132
7373
  if (link.to.includes(".")) {
7133
7374
  throw new OrmDefinitionError(
7134
- `link '${name}' on '${table}' targets '${link.to}' \u2014 cross-namespace links have no canonical v2 representation (links are namespace-local in v2)`
7375
+ `link '${name2}' on '${table}' targets '${link.to}' \u2014 cross-namespace links have no canonical v2 representation (links are namespace-local in v2)`
7135
7376
  );
7136
7377
  }
7137
7378
  return {
7138
- name,
7379
+ name: name2,
7139
7380
  kind: "toOne",
7140
7381
  target: link.to,
7141
7382
  on: link.on,
@@ -7164,29 +7405,29 @@ function buildRebaseJournalEntry({ namespace, previousHash, newHash, ordinal, sn
7164
7405
  if (!Number.isInteger(ordinal) || ordinal < 2) {
7165
7406
  throw new OrmDefinitionError(`rebase ordinal must be an integer \u2265 2 (a rebase sits on an existing journal tip); got ${ordinal}`);
7166
7407
  }
7167
- const name = migrationName(ordinal, newHash);
7168
- const sql7 = renderRebaseMigrationSql({ name, namespace, previousHash, newHash });
7408
+ const name2 = migrationName(ordinal, newHash);
7409
+ const sql7 = renderRebaseMigrationSql({ name: name2, namespace, previousHash, newHash });
7169
7410
  const snapshotText = `${JSON.stringify(snapshot, null, 2)}
7170
7411
  `;
7171
7412
  const entry = {
7172
7413
  ordinal,
7173
- name,
7414
+ name: name2,
7174
7415
  content_hash: newHash,
7175
7416
  previous_content_hash: previousHash,
7176
7417
  checksum: checksumOf(sql7),
7177
7418
  snapshot_checksum: checksumOf(snapshotText),
7178
7419
  destructive: false
7179
7420
  };
7180
- return { name, entry, sql: sql7, snapshotText };
7421
+ return { name: name2, entry, sql: sql7, snapshotText };
7181
7422
  }
7182
7423
  function renderRebaseMigrationSql({
7183
- name,
7424
+ name: name2,
7184
7425
  namespace,
7185
7426
  previousHash,
7186
7427
  newHash
7187
7428
  }) {
7188
7429
  return [
7189
- `-- ${name}`,
7430
+ `-- ${name2}`,
7190
7431
  `-- namespace: ${namespace}`,
7191
7432
  `-- content hash: ${newHash}`,
7192
7433
  `-- rebase: v1 definitions (${previousHash}) converted to canonical v2 \u2014 verified no-op, zero statements`,
@@ -7260,8 +7501,8 @@ function canonicalActions(value) {
7260
7501
  const entries = Object.entries(value);
7261
7502
  if (entries.length === 0) return void 0;
7262
7503
  return Object.fromEntries(
7263
- entries.map(([name, action]) => [
7264
- name,
7504
+ entries.map(([name2, action]) => [
7505
+ name2,
7265
7506
  {
7266
7507
  description: action["description"] ?? void 0,
7267
7508
  requires: action["requires"] ?? void 0,
@@ -7274,7 +7515,527 @@ function canonicalActions(value) {
7274
7515
  ])
7275
7516
  );
7276
7517
  }
7518
+ var IMPORT_CONFLICT_MODES = ["error", "skip", "update"];
7519
+ var columnMapSchema = z.object({
7520
+ /** ORM property name or Postgres column name. */
7521
+ target: z.string().min(1).max(63),
7522
+ /** Column on the source relation. Identifiers only — never an expression. */
7523
+ source: z.string().min(1).max(63),
7524
+ /**
7525
+ * Used when the source value is NULL. Required columns without a database
7526
+ * default fail the load if the source contains nulls and this is omitted.
7527
+ */
7528
+ nullDefault: z.union([z.string().max(1e4), z.number(), z.boolean()]).optional()
7529
+ }).strict();
7530
+ var importSpecSchema = z.object({
7531
+ table: z.string().min(1).max(63),
7532
+ from: z.string().regex(QUALIFIED_TABLE_PATTERN),
7533
+ columns: z.array(columnMapSchema).min(1).max(500),
7534
+ onConflict: z.enum(IMPORT_CONFLICT_MODES).default("skip"),
7535
+ batchSize: z.number().int().min(1).max(2e4).default(5e3)
7536
+ }).strict();
7537
+ var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
7538
+ var DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
7539
+ var TIMESTAMPTZ_RE = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:?\d{2})$/;
7540
+ var INTEGER_RE = /^-?\d+$/;
7541
+ var NUMERIC_RE = /^-?\d+(\.\d+)?$/;
7542
+ function sourceSchemaAllowed(schema) {
7543
+ return schema !== "information_schema" && !schema.startsWith("pg_");
7544
+ }
7545
+ function isRelationIdentifier(value) {
7546
+ return value.length <= 63 && IDENTIFIER_PATTERN.test(value);
7547
+ }
7548
+ function isSourceColumn(value) {
7549
+ return value.length <= 63 && COLUMN_IDENTIFIER_PATTERN.test(value);
7550
+ }
7551
+ function splitQualifiedRelation(from) {
7552
+ const dot = from.indexOf(".");
7553
+ if (dot <= 0 || dot !== from.lastIndexOf(".")) return null;
7554
+ const schema = from.slice(0, dot);
7555
+ const table = from.slice(dot + 1);
7556
+ if (!isRelationIdentifier(schema) || !isRelationIdentifier(table)) return null;
7557
+ return { schema, table };
7558
+ }
7559
+ function postgresTypeName(type) {
7560
+ if (type === "double") return "double precision";
7561
+ if (type === "timestamptz") return "timestamp with time zone";
7562
+ return type;
7563
+ }
7564
+ function columnPostgresType(column, schemaName, enums) {
7565
+ if (typeof column.type === "string") return postgresTypeName(column.type);
7566
+ if (!enums.has(column.type.enum)) return null;
7567
+ return `${quoteIdentifier(schemaName)}.${quoteIdentifier(column.type.enum)}`;
7568
+ }
7569
+ function quoteQualified(schema, table) {
7570
+ return `${quoteIdentifier(schema)}.${quoteIdentifier(table)}`;
7571
+ }
7572
+ var INT4_MIN = -2147483648;
7573
+ var INT4_MAX = 2147483647;
7574
+ function resumeLiteralSql({
7575
+ column,
7576
+ after,
7577
+ schemaName,
7578
+ enums
7579
+ }) {
7580
+ const coerced = coerceResumeValue(column, after);
7581
+ if (!coerced.ok) return coerced;
7582
+ return literalSql({ column, value: coerced.value, schemaName, enums });
7583
+ }
7584
+ function coerceResumeValue(column, after) {
7585
+ const type = typeof column.type === "string" ? column.type : null;
7586
+ if (type === "integer") {
7587
+ if (!INTEGER_RE.test(after)) return { ok: false, error: `${column.name}: after must be an integer` };
7588
+ const parsed = Number(after);
7589
+ if (!Number.isSafeInteger(parsed) || parsed < INT4_MIN || parsed > INT4_MAX) {
7590
+ return { ok: false, error: `${column.name}: after must be an integer` };
7591
+ }
7592
+ return { ok: true, value: parsed };
7593
+ }
7594
+ if (type === "boolean") {
7595
+ if (after !== "true" && after !== "false") return { ok: false, error: `${column.name}: after must be true or false` };
7596
+ return { ok: true, value: after === "true" };
7597
+ }
7598
+ return { ok: true, value: after };
7599
+ }
7600
+ function literalSql({
7601
+ column,
7602
+ value,
7603
+ schemaName,
7604
+ enums
7605
+ }) {
7606
+ const label = column.name;
7607
+ if (typeof value === "string" && value.includes("\0")) {
7608
+ return { ok: false, error: `${label}: null default contains a NUL character` };
7609
+ }
7610
+ if (typeof column.type !== "string") {
7611
+ const enumDef = enums.get(column.type.enum);
7612
+ if (!enumDef) return { ok: false, error: `${label}: enum '${column.type.enum}' is not declared` };
7613
+ if (typeof value !== "string" || !enumDef.values.includes(value)) {
7614
+ return { ok: false, error: `${label}: null default must be one of ${enumDef.values.join(", ")}` };
7615
+ }
7616
+ const typeName = columnPostgresType(column, schemaName, enums);
7617
+ return { ok: true, sql: `${quoteLiteral(value)}::${typeName}` };
7618
+ }
7619
+ return scalarLiteral2({ column, type: column.type, value, label });
7620
+ }
7621
+ var SCALAR_LITERALS = {
7622
+ text: (value, label) => typeof value === "string" ? { ok: true, sql: quoteLiteral(value) } : { ok: false, error: `${label}: null default must be a string` },
7623
+ uuid: (value, label) => typeof value === "string" && UUID_RE.test(value) ? { ok: true, sql: `${quoteLiteral(value)}::uuid` } : { ok: false, error: `${label}: null default must be a UUID` },
7624
+ boolean: (value, label) => typeof value === "boolean" ? { ok: true, sql: value ? "TRUE" : "FALSE" } : { ok: false, error: `${label}: null default must be true or false` },
7625
+ integer: (value, label) => typeof value === "number" && Number.isSafeInteger(value) ? { ok: true, sql: String(value) } : { ok: false, error: `${label}: null default must be an integer` },
7626
+ bigint: (value, label) => typeof value === "string" && INTEGER_RE.test(value) ? { ok: true, sql: `${value}::bigint` } : { ok: false, error: `${label}: null default must be a base-10 integer string` },
7627
+ numeric: numericLiteral,
7628
+ double: numericLiteral,
7629
+ date: (value, label) => typeof value === "string" && DATE_RE.test(value) ? { ok: true, sql: `${quoteLiteral(value)}::date` } : { ok: false, error: `${label}: null default must be a YYYY-MM-DD date` },
7630
+ timestamptz: (value, label) => typeof value === "string" && TIMESTAMPTZ_RE.test(value) ? { ok: true, sql: `${quoteLiteral(value)}::${postgresTypeName("timestamptz")}` } : { ok: false, error: `${label}: null default must be an ISO-8601 timestamp` },
7631
+ jsonb: jsonbLiteral
7632
+ };
7633
+ function numericLiteral(value, label) {
7634
+ if (typeof value === "number" && Number.isFinite(value)) return { ok: true, sql: String(value) };
7635
+ if (typeof value === "string" && NUMERIC_RE.test(value)) return { ok: true, sql: value };
7636
+ return { ok: false, error: `${label}: null default must be a finite number` };
7637
+ }
7638
+ function scalarLiteral2({
7639
+ column,
7640
+ type,
7641
+ value,
7642
+ label
7643
+ }) {
7644
+ const encode = SCALAR_LITERALS[type];
7645
+ if (!encode) return { ok: false, error: `${column.name}: unsupported type '${type}'` };
7646
+ return encode(value, label);
7647
+ }
7648
+ function jsonbLiteral(value, label) {
7649
+ if (typeof value !== "string") return { ok: false, error: `${label}: null default must be a JSON string` };
7650
+ try {
7651
+ JSON.parse(value);
7652
+ } catch {
7653
+ return { ok: false, error: `${label}: null default must be valid JSON` };
7654
+ }
7655
+ return { ok: true, sql: `${quoteLiteral(value)}::jsonb` };
7656
+ }
7657
+ function dollarQuote(body) {
7658
+ const digest = createHash("sha256").update(body).digest("hex");
7659
+ const candidates = ["seq_orm_import", `seq_orm_${digest.slice(0, 16)}`, `seq_orm_${digest}`];
7660
+ const tag = candidates.find((candidate) => !body.includes(`$${candidate}$`)) ?? `seq_orm_${digest}_body`;
7661
+ return `$${tag}$${body}$${tag}$`;
7662
+ }
7663
+
7664
+ // src/import/script.ts
7665
+ function renderImportScript({
7666
+ namespace,
7667
+ schemaName,
7668
+ table,
7669
+ source,
7670
+ mapped,
7671
+ primaryKey: primaryKey2,
7672
+ onConflict,
7673
+ batchSize,
7674
+ omitted,
7675
+ resume
7676
+ }) {
7677
+ const sourceSql = `${quoteQualified(source.schema, source.table)} AS src`;
7678
+ const targetSql = quoteQualified(schemaName, table.table);
7679
+ const keys = primaryKey2.map((name2) => mapped.find((column) => column.column.columnName === name2)).filter((column) => column !== void 0);
7680
+ const probeSql = renderProbe({ sourceSql, keys, mapped });
7681
+ const procedure = renderProcedure({ targetSql, sourceSql, mapped, keys, onConflict, batchSize });
7682
+ const call = `CALL pg_temp.seq_orm_import(${resume.join(", ")});`;
7683
+ const omittedLine = omitted.length > 0 ? `-- Omitted columns keep their database default or NULL: ${omitted.join(", ")}` : "-- Every column is mapped.";
7684
+ const text4 = [
7685
+ "-- Sequence ORM data import",
7686
+ `-- namespace: ${namespace}`,
7687
+ `-- target: ${schemaName}.${table.table}`,
7688
+ `-- source: ${source.schema}.${source.table}`,
7689
+ `-- conflict: ${onConflict}`,
7690
+ `-- batch size: ${batchSize}`,
7691
+ "--",
7692
+ "-- Runs as the namespace owner. Does not evaluate insert or update policies,",
7693
+ "-- capability gates, or the operation journal. Sync the warehouse table into",
7694
+ "-- this Postgres relation first, review the probe, then run the load.",
7695
+ "-- skip and update are safe to re-run from the start after a failure. error stops on an existing key.",
7696
+ "-- Each batch commits. Do not resume from the maximum key in the target:",
7697
+ "-- a higher key that was already there would skip source rows this run never copied.",
7698
+ "-- --after is only the last key this procedure committed. This script does not print it.",
7699
+ omittedLine,
7700
+ "-- cast_* columns force every mapped value through the target type. An invalid value aborts before any insert.",
7701
+ "",
7702
+ probeSql,
7703
+ "",
7704
+ procedure,
7705
+ call,
7706
+ ""
7707
+ ].join("\n");
7708
+ return { probeSql, text: text4 };
7709
+ }
7710
+ function renderProbe({
7711
+ sourceSql,
7712
+ keys,
7713
+ mapped
7714
+ }) {
7715
+ const nullKey = keys.map((key) => `${key.expression} IS NULL`).join(" OR ");
7716
+ const distinct = keys.length === 1 ? keys[0].expression : `(${keys.map((key) => key.expression).join(", ")})`;
7717
+ const requiredNulls = nullChecked(mapped, keys).map((column) => `count(*) FILTER (WHERE src.${quoteIdentifier(column.source)} IS NULL) AS ${quoteIdentifier(`null_${column.column.columnName}`)}`);
7718
+ const selects = [
7719
+ "count(*) AS source_rows",
7720
+ `count(*) FILTER (WHERE ${nullKey}) AS null_primary_key`,
7721
+ `count(*) FILTER (WHERE NOT (${nullKey})) - count(DISTINCT ${distinct}) AS duplicate_primary_key`,
7722
+ ...requiredNulls,
7723
+ ...mapped.map((column) => `count(${column.expression}) AS ${quoteIdentifier(`cast_${column.column.columnName}`)}`)
7724
+ ];
7725
+ return `SELECT
7726
+ ${selects.join(",\n ")}
7727
+ FROM ${sourceSql};`;
7728
+ }
7729
+ function renderProcedure({
7730
+ targetSql,
7731
+ sourceSql,
7732
+ mapped,
7733
+ keys,
7734
+ onConflict,
7735
+ batchSize
7736
+ }) {
7737
+ const args = keys.map((key, index3) => `IN start_${index3} ${key.pgType} DEFAULT NULL`).join(", ");
7738
+ const declarations = [
7739
+ "DECLARE",
7740
+ " batch_scanned integer;",
7741
+ " batch_affected integer;",
7742
+ " total_rows bigint;",
7743
+ " null_keys bigint;",
7744
+ " distinct_keys bigint;",
7745
+ ...keys.map((key, index3) => ` watermark_${index3} ${key.pgType};`),
7746
+ ...requiredNullDeclarations(mapped, keys),
7747
+ ...mapped.map((column) => ` cast_${column.column.columnName} bigint;`)
7748
+ ];
7749
+ const body = [
7750
+ "BEGIN",
7751
+ ...keys.map((_, index3) => ` watermark_${index3} := start_${index3};`),
7752
+ ` ${renderGuard({ sourceSql, keys, mapped })}`,
7753
+ " LOOP",
7754
+ ` ${renderPage({ targetSql, sourceSql, mapped, keys, onConflict, batchSize })}`,
7755
+ " EXIT WHEN batch_scanned = 0;",
7756
+ " RAISE NOTICE 'orm import scanned % affected %', batch_scanned, batch_affected;",
7757
+ " COMMIT;",
7758
+ " END LOOP;",
7759
+ "END"
7760
+ ].join("\n");
7761
+ return [
7762
+ `CREATE OR REPLACE PROCEDURE pg_temp.seq_orm_import(${args})`,
7763
+ "LANGUAGE plpgsql",
7764
+ `AS ${dollarQuote(`
7765
+ ${declarations.join("\n")}
7766
+ ${body}
7767
+ `)}`,
7768
+ ";",
7769
+ ""
7770
+ ].join("\n");
7771
+ }
7772
+ function nullChecked(mapped, keys) {
7773
+ return mapped.filter((column) => !column.fillsNull && column.column.nullable === false && !keys.includes(column));
7774
+ }
7775
+ function requiredNullDeclarations(mapped, keys) {
7776
+ return nullChecked(mapped, keys).map((column) => ` null_${column.column.columnName} bigint;`);
7777
+ }
7778
+ function renderGuard({
7779
+ sourceSql,
7780
+ keys,
7781
+ mapped
7782
+ }) {
7783
+ const nullKey = keys.map((key) => `${key.expression} IS NULL`).join(" OR ");
7784
+ const distinct = keys.length === 1 ? keys[0].expression : `(${keys.map((key) => key.expression).join(", ")})`;
7785
+ const nullColumns = nullChecked(mapped, keys);
7786
+ const into = [
7787
+ "total_rows",
7788
+ "null_keys",
7789
+ "distinct_keys",
7790
+ ...nullColumns.map((column) => `null_${column.column.columnName}`),
7791
+ ...mapped.map((column) => `cast_${column.column.columnName}`)
7792
+ ];
7793
+ const selects = [
7794
+ "count(*)::bigint",
7795
+ `count(*) FILTER (WHERE ${nullKey})::bigint`,
7796
+ `count(DISTINCT ${distinct})::bigint`,
7797
+ ...nullColumns.map((column) => `count(*) FILTER (WHERE src.${quoteIdentifier(column.source)} IS NULL)::bigint`),
7798
+ ...mapped.map((column) => `count(${column.expression})::bigint`)
7799
+ ];
7800
+ const checks = [
7801
+ "IF null_keys > 0 THEN RAISE EXCEPTION 'import refused: source primary key has % null values', null_keys; END IF;",
7802
+ "IF total_rows <> distinct_keys THEN RAISE EXCEPTION 'import refused: source primary key has % duplicate values', total_rows - distinct_keys; END IF;",
7803
+ ...nullColumns.map(
7804
+ (column) => `IF null_${column.column.columnName} > 0 THEN RAISE EXCEPTION 'import refused: source column ${column.source} is null on % rows and ${column.column.columnName} is required', null_${column.column.columnName}; END IF;`
7805
+ )
7806
+ ];
7807
+ return [`SELECT ${selects.join(", ")}`, ` INTO ${into.join(", ")}`, ` FROM ${sourceSql};`, ...checks.map((check) => ` ${check}`)].join("\n");
7808
+ }
7809
+ function renderPage({
7810
+ targetSql,
7811
+ sourceSql,
7812
+ mapped,
7813
+ keys,
7814
+ onConflict,
7815
+ batchSize
7816
+ }) {
7817
+ const keyExprs = keys.map((key) => key.expression);
7818
+ const where = `watermark_0 IS NULL OR (${keyExprs.join(", ")}) > (${keys.map((_, index3) => `watermark_${index3}`).join(", ")})`;
7819
+ const order = keyExprs.join(", ");
7820
+ const pageColumns = mapped.map((column) => `${column.expression} AS ${quoteIdentifier(column.column.columnName)}`);
7821
+ const insertColumns = mapped.map((column) => quoteIdentifier(column.column.columnName)).join(", ");
7822
+ const conflict = conflictClause(onConflict, keys, mapped);
7823
+ const keyOrder = keys.map((key) => `${quoteIdentifier(key.column.columnName)} DESC`).join(", ");
7824
+ const lastKeys = keys.map((key) => `(SELECT ${quoteIdentifier(key.column.columnName)} FROM page ORDER BY ${keyOrder} LIMIT 1)`).join(", ");
7825
+ const watermarkTargets = keys.map((_, index3) => `watermark_${index3}`).join(", ");
7826
+ return [
7827
+ "WITH page AS (",
7828
+ ` SELECT ${pageColumns.join(", ")}`,
7829
+ ` FROM ${sourceSql}`,
7830
+ ` WHERE ${where}`,
7831
+ ` ORDER BY ${order}`,
7832
+ ` LIMIT ${batchSize}`,
7833
+ " ),",
7834
+ " ins AS (",
7835
+ ` INSERT INTO ${targetSql} (${insertColumns})`,
7836
+ ` SELECT ${insertColumns} FROM page`,
7837
+ ` ${conflict}`,
7838
+ " RETURNING 1",
7839
+ " )",
7840
+ ` SELECT (SELECT count(*)::int FROM page), (SELECT count(*)::int FROM ins), ${lastKeys}`,
7841
+ ` INTO batch_scanned, batch_affected, ${watermarkTargets};`
7842
+ ].join("\n");
7843
+ }
7844
+ function conflictClause(onConflict, keys, mapped) {
7845
+ if (onConflict === "error") return "";
7846
+ const target = keys.map((key) => quoteIdentifier(key.column.columnName)).join(", ");
7847
+ if (onConflict === "skip") return `ON CONFLICT (${target}) DO NOTHING`;
7848
+ const assignments = mapped.filter((column) => !keys.includes(column)).map((column) => `${quoteIdentifier(column.column.columnName)} = EXCLUDED.${quoteIdentifier(column.column.columnName)}`);
7849
+ return `ON CONFLICT (${target}) DO UPDATE SET ${assignments.join(", ")}`;
7850
+ }
7851
+
7852
+ // src/import/plan.ts
7853
+ function planTableImport({
7854
+ definition,
7855
+ spec,
7856
+ after
7857
+ }) {
7858
+ const parsedDefinition = canonicalDefinitionSchema.safeParse(definition);
7859
+ if (!parsedDefinition.success) return { ok: false, errors: ["namespace definition is not canonical ORM v2"] };
7860
+ const parsedSpec = importSpecSchema.safeParse(spec);
7861
+ if (!parsedSpec.success) {
7862
+ return { ok: false, errors: parsedSpec.error.issues.map((issue) => `${issue.path.join(".") || "spec"}: ${issue.message}`) };
7863
+ }
7864
+ return planParsed({ definition: parsedDefinition.data, spec: parsedSpec.data, after });
7865
+ }
7866
+ function planParsed({
7867
+ definition,
7868
+ spec,
7869
+ after
7870
+ }) {
7871
+ const source = splitQualifiedRelation(spec.from);
7872
+ const target = resolveTarget(definition, spec.table);
7873
+ const errors = [];
7874
+ if (!source) errors.push(`from '${spec.from}' is not a schema.table identifier`);
7875
+ else if (!sourceSchemaAllowed(source.schema)) errors.push(`from schema '${source.schema}' is not a warehouse relation`);
7876
+ if (!target.table) errors.push(...target.errors);
7877
+ if (!source || !target.table) return { ok: false, errors };
7878
+ const schemaName = ormSchemaName(definition.namespace);
7879
+ if (source.schema === schemaName && source.table === target.table.table) {
7880
+ errors.push(`from '${spec.from}' is the import target`);
7881
+ }
7882
+ const enums = new Map(definition.enums.map((entry) => [entry.name, entry]));
7883
+ const mapped = mapColumns({ table: target.table, spec, schemaName, enums, errors });
7884
+ const primaryKey2 = target.table.primaryKey ?? [];
7885
+ if (primaryKey2.length === 0) errors.push(`table '${target.table.table}' needs a primary key`);
7886
+ for (const key of primaryKey2) {
7887
+ if (!mapped.some((column) => column.column.columnName === key)) {
7888
+ errors.push(`primary key column '${key}' must be mapped so existing identities are preserved`);
7889
+ }
7890
+ }
7891
+ collectUnmapped({ table: target.table, mapped, errors });
7892
+ if (spec.onConflict === "update" && mapped.every((column) => primaryKey2.includes(column.column.columnName))) {
7893
+ errors.push('onConflict "update" needs a mapped column that is not part of the primary key');
7894
+ }
7895
+ const resume = resumeArguments({ mapped, primaryKey: primaryKey2, after, schemaName, enums, errors });
7896
+ if (errors.length > 0) return { ok: false, errors };
7897
+ const omitted = omittedColumns(target.table, mapped);
7898
+ const script = renderImportScript({
7899
+ namespace: definition.namespace,
7900
+ schemaName,
7901
+ table: target.table,
7902
+ source,
7903
+ mapped,
7904
+ primaryKey: primaryKey2,
7905
+ onConflict: spec.onConflict,
7906
+ batchSize: spec.batchSize,
7907
+ omitted,
7908
+ resume
7909
+ });
7910
+ const warnings = [
7911
+ "This load runs as the namespace owner. It does not evaluate insert or update policies.",
7912
+ ...spec.onConflict === "error" ? ['onConflict "error" is not safe to re-run: the first existing key aborts the batch.'] : []
7913
+ ];
7914
+ return {
7915
+ ok: true,
7916
+ plan: { probeSql: script.probeSql, script: script.text, batchSize: spec.batchSize, onConflict: spec.onConflict, warnings }
7917
+ };
7918
+ }
7919
+ function resolveTarget(definition, name2) {
7920
+ const table = definition.tables.find((candidate) => candidate.table === name2);
7921
+ if (!table) {
7922
+ const view = definition.views?.find((candidate) => candidate.view === name2);
7923
+ return { table: null, errors: [view ? `'${name2}' is a view, not an owned table` : `table '${name2}' is not in this namespace`] };
7924
+ }
7925
+ if (table.source !== void 0) return { table: null, errors: [`'${name2}' is a synced reflection and cannot be imported into`] };
7926
+ if (table.internal || table.materializes !== void 0) {
7927
+ return { table: null, errors: [`'${name2}' is an internal relation, not an import target`] };
7928
+ }
7929
+ return { table, errors: [] };
7930
+ }
7931
+ function mapColumns({
7932
+ table,
7933
+ spec,
7934
+ schemaName,
7935
+ enums,
7936
+ errors
7937
+ }) {
7938
+ const mapped = [];
7939
+ const seen = /* @__PURE__ */ new Set();
7940
+ for (const entry of spec.columns) {
7941
+ const column = findColumn(table, entry.target);
7942
+ if (column === "ambiguous") {
7943
+ errors.push(`target '${entry.target}' matches more than one column`);
7944
+ continue;
7945
+ }
7946
+ if (!column) {
7947
+ errors.push(`target '${entry.target}' is not a column of '${table.table}'`);
7948
+ continue;
7949
+ }
7950
+ if (column.cell !== void 0) {
7951
+ errors.push(`target '${entry.target}' is cell metadata and cannot be imported`);
7952
+ continue;
7953
+ }
7954
+ if (seen.has(column.columnName)) {
7955
+ errors.push(`column '${column.columnName}' is mapped more than once`);
7956
+ continue;
7957
+ }
7958
+ if (!isSourceColumn(entry.source)) {
7959
+ errors.push(`source '${entry.source}' is not a column identifier`);
7960
+ continue;
7961
+ }
7962
+ seen.add(column.columnName);
7963
+ const pgType = columnPostgresType(column, schemaName, enums);
7964
+ if (!pgType) {
7965
+ errors.push(`column '${column.name}' references undeclared enum '${typeof column.type === "string" ? column.type : column.type.enum}'`);
7966
+ continue;
7967
+ }
7968
+ const expression = valueExpression({ column, source: entry.source, pgType, nullDefault: entry.nullDefault, schemaName, enums, errors });
7969
+ if (expression) mapped.push({ column, source: entry.source, expression, pgType, fillsNull: entry.nullDefault !== void 0 });
7970
+ }
7971
+ return mapped;
7972
+ }
7973
+ function findColumn(table, target) {
7974
+ const matches = table.columns.filter((column) => column.name === target || column.columnName === target);
7975
+ if (matches.length > 1) return "ambiguous";
7976
+ return matches[0];
7977
+ }
7978
+ function valueExpression({
7979
+ column,
7980
+ source,
7981
+ pgType,
7982
+ nullDefault,
7983
+ schemaName,
7984
+ enums,
7985
+ errors
7986
+ }) {
7987
+ const cast = `CAST(src.${quoteIdentifier(source)} AS ${pgType})`;
7988
+ if (nullDefault === void 0) return cast;
7989
+ const literal2 = literalSql({ column, value: nullDefault, schemaName, enums });
7990
+ if (!literal2.ok) {
7991
+ errors.push(literal2.error);
7992
+ return null;
7993
+ }
7994
+ return `COALESCE(${cast}, ${literal2.sql})`;
7995
+ }
7996
+ function collectUnmapped({
7997
+ table,
7998
+ mapped,
7999
+ errors
8000
+ }) {
8001
+ const mappedNames = new Set(mapped.map((column) => column.column.columnName));
8002
+ const primaryKey2 = new Set(table.primaryKey ?? []);
8003
+ for (const column of table.columns) {
8004
+ if (mappedNames.has(column.columnName) || column.cell !== void 0) continue;
8005
+ const hasDefault = column.default !== void 0 && column.default !== null || column.defaultFn !== void 0;
8006
+ const required = column.nullable === false && !hasDefault && !primaryKey2.has(column.columnName);
8007
+ if (required) {
8008
+ errors.push(`column '${column.name}' is required and has no default \u2014 map it or set a database default before importing`);
8009
+ }
8010
+ }
8011
+ }
8012
+ function omittedColumns(table, mapped) {
8013
+ const mappedNames = new Set(mapped.map((column) => column.column.columnName));
8014
+ return table.columns.filter((column) => column.cell === void 0 && !mappedNames.has(column.columnName)).map((column) => column.columnName);
8015
+ }
8016
+ function resumeArguments({
8017
+ mapped,
8018
+ primaryKey: primaryKey2,
8019
+ after,
8020
+ schemaName,
8021
+ enums,
8022
+ errors
8023
+ }) {
8024
+ if (after === void 0) return primaryKey2.map(() => "NULL");
8025
+ if (primaryKey2.length !== 1) {
8026
+ errors.push("after resumes a single-column primary key; re-run from the start for a composite key (skip and update are idempotent)");
8027
+ return [];
8028
+ }
8029
+ const key = mapped.find((column) => column.column.columnName === primaryKey2[0]);
8030
+ if (!key) return [];
8031
+ const literal2 = resumeLiteralSql({ column: key.column, after, schemaName, enums });
8032
+ if (!literal2.ok) {
8033
+ errors.push(`after: ${literal2.error}`);
8034
+ return [];
8035
+ }
8036
+ return [literal2.sql];
8037
+ }
7277
8038
 
7278
- export { ACTION_REQUIRES_DENIED_SQLSTATE, ACTION_VALIDATES_FAILED_SQLSTATE, AUDIT_ACTIONS, CANONICAL_FORMAT, CAPABILITIES_CLAIM_KEY, CAPABILITY_KEY_PATTERN, CELLS_FIELD, CELL_PARTS, CELL_PART_SUFFIX, CLAIMS_CONTRACT, CLAIMS_SETTING, CLAIM_KEY_PATTERN, CMP_OPS, COLUMN_BRAND, COLUMN_DEFAULT_FNS, COLUMN_IDENTIFIER_PATTERN, COLUMN_TYPES2 as COLUMN_TYPES, COMPARE_OPS, CONSUMER_ROLE_SUFFIX, ColumnBuilder, DATE_BUCKETS, DEFINITION_FILE_EXTENSIONS, ENUM_BRAND, HASH_DOMAIN, IDENTIFIER_PATTERN, IDENTIFIER_RE, INPUT_REF_KINDS, IR_VERSION, IrVersionError, LEGACY_IR_VERSION, LINK_BRAND, MATERIALIZE_ACTOR, MATERIALIZE_CLAIMS_JSON, MAX_DEFINITION_FILE_BYTES, MAX_GENERATED_SDL_BYTES, MAX_IDENTIFIER_LENGTH, MAX_TRACKED_COLUMN_NAME, MIGRATIONS_DIRNAME, NAMESPACE_CONFIG_BRAND, NAMESPACE_CONFIG_FILE, NAMESPACE_CONFIG_FILENAMES, NAMESPACE_PATTERN, ORM_DATA_TOKEN_HEADER, ORM_MIGRATION_EXPORT_FILE, ORM_MIGRATION_EXPORT_MAX_BYTES, ORM_REGISTRATION_MAX_BYTES, ORM_SCHEMA_PREFIX, ORM_SERVICE_DATA_TOKEN_HEADER, ORM_TO_PIPELINE_TYPE, OrmDefinitionError, PredicateParseError, QUALIFIED_TABLE_PATTERN, RESERVED_COLUMN_NAMES, RESERVED_TABLE_NAMES, ROLES_CLAIM_KEY, SCHEMA_DIR, STATEMENT_KINDS, SYNCED_CONTRACT_HASH_DOMAIN, SYNCED_SOURCE_PATTERN, SYNCED_VIEW_EXECUTION_OWNER_ROLE, TABLE_BRAND, VIEW_BRAND, actionFunctionName, actionFunctionStatements, actionParamArg, actionParamOrder, actionParamSchema, actionPrepareChecks, actionSchema, actionWriteTargets, actionsInterfaceName, activeAuthoringContext, applyMigrationHints, applyMigrationHintsV2, beginAuthoringContext, buildActionParamsSchema, buildDrizzleEntities, buildDrizzleEntitiesV2, buildNamespaceDefinition, buildRebaseJournalEntry, canonicalActionSchema, canonicalColumnSchema, canonicalDefinitionSchema, canonicalEnumSchema, canonicalIndexSchema, canonicalLinkSchema, canonicalPoliciesSchema, canonicalRelations, canonicalTableSchema, canonicalViewSchema, canonicalizeDefinition, capabilityExpression, castParts, cellColumnName, checksumOf, claimExpression, classifyDestructive, columnSchema, columnTypeSchema2 as columnTypeSchema, compileActionRequires, compileActionStatements, compileNamespace, compilePredIrToSql, compilePredicate, compiledArtifactSchema, compiledOperationSchema, computeCanonicalHash, computeDefinitionHash, computeSyncedContractHash, consumerRoleName, convertV1DefinitionToCanonical, createOrmMigrationExport, custom, declaredCapabilityKeys, defineEnum, defineNamespace, defineResolvedTable, defineSyncedTable, defineTable, defineView, deriveColumnName, diffCommand, diffStatements, emptyJournal, emptySnapshot, endAuthoringContext, etlSource, extractNamedParams, extractOrmSyncedTableContract, generateNamespaceTypes, generateSnapshot, generateSnapshotV2, highest, identifierSchema, indexByHash, isColumnBuilder, isEnumRef, isFunctionDefault, isOwnedStatement, isOwnedStatementV2, isQualifiedReference, isSeqLink, isSeqNamespaceConfig, isSeqTable, isSeqView, latest, limitIrSchema, loadCommittedMigrations, loadCommittedTipMigration, loadNamespaceDefinition, loadNamespaceFromDir, lowest, managedFn, manualSource, materializeLockKey, materializedRefreshFunctionName, migrationName, namespaceConfigSchema, namespaceSchema, nonNullFirst, normalizeCanonical, normalizeIr, normalizeSnapshot, orderIrSchema, ormMigrationExportSchema, ormSchemaName, overlayWinsUnion, overrideRowMutation, parseCanonicalDefinition, parseDefinitionSources, parseOrmMigrationExport, parsePredicate, parseTableFile, parsedPredicateSchema, pendingKitStatements, pendingKitStatementsV2, planCommittedMigrationV2, planMigration, planMigrationV2, policyExpressionSchema, policyVariantSchema, predIrSchema, predicateOperands, prefetchPlanIrSchema, prefetchSource, priority, quoteIdentifier, quoteLiteral, readMigrationSql, readMigrationWorkspace, readSnapshot, rebaseViolations, referencedCapabilities, referencedColumns, renderMigrationSql, renderOrmMigrationExport, requiredArtifactIrVersion, resolvedMetaIrSchema, resolvedSourceIrSchema, revertOverlayMutation, rewriteSyncedSourceRelationsInViewQuery, roleExpression, rootIrSchema, securityStatements, selectionIrSchema, serializeNamespace, sqlTypeName, stableJson, syncedBackingRevokeStatements, syncedContractSurface, syncedTables, syncedViewDropStatements, syncedViewStatements, t, tableFileSchema, tableMetaIrSchema, tableReferenceSchema, toMany, toOne, toPlatformUser, typesInterfaceName, validateViewCatalogStatement, valueIrSchema, variableDefaultIrSchema, variableIrSchema, verifyRebaseIsNoop, walkPredicate, writeMigration };
8039
+ export { ACTION_REQUIRES_DENIED_SQLSTATE, ACTION_VALIDATES_FAILED_SQLSTATE, AUDIT_ACTIONS, CANONICAL_FORMAT, CAPABILITIES_CLAIM_KEY, CAPABILITY_KEY_PATTERN, CELLS_FIELD, CELL_PARTS, CELL_PART_SUFFIX, CLAIMS_CONTRACT, CLAIMS_SETTING, CLAIM_KEY_PATTERN, CMP_OPS, COLUMN_BRAND, COLUMN_DEFAULT_FNS, COLUMN_IDENTIFIER_PATTERN, COLUMN_TYPES2 as COLUMN_TYPES, COMPARE_OPS, COMPOSED_IR_VERSION, CONSUMER_ROLE_SUFFIX, ColumnBuilder, DATE_BUCKETS, DEFINITION_FILE_EXTENSIONS, ENUM_BRAND, GUARDED_IR_VERSION, HASH_DOMAIN, IDENTIFIER_PATTERN, IDENTIFIER_RE, IMPORT_CONFLICT_MODES, INPUT_REF_KINDS, IR_VERSION, IrVersionError, LEGACY_IR_VERSION, LINK_BRAND, MATERIALIZE_ACTOR, MATERIALIZE_CLAIMS_JSON, MAX_DEFINITION_FILE_BYTES, MAX_GENERATED_SDL_BYTES, MAX_IDENTIFIER_LENGTH, MAX_TRACKED_COLUMN_NAME, MIGRATIONS_DIRNAME, NAMESPACE_CONFIG_BRAND, NAMESPACE_CONFIG_FILE, NAMESPACE_CONFIG_FILENAMES, NAMESPACE_PATTERN, ORM_DATA_TOKEN_HEADER, ORM_MIGRATION_EXPORT_FILE, ORM_MIGRATION_EXPORT_MAX_BYTES, ORM_REGISTRATION_MAX_BYTES, ORM_SCHEMA_PREFIX, ORM_SERVICE_DATA_TOKEN_HEADER, ORM_TO_PIPELINE_TYPE, OrmDefinitionError, PredicateParseError, QUALIFIED_TABLE_PATTERN, RESERVED_COLUMN_NAMES, RESERVED_TABLE_NAMES, ROLES_CLAIM_KEY, RUNTIME_SQL_IR_VERSION, SCHEMA_DIR, SQL_IR_VERSION, STATEMENT_KINDS, SYNCED_CONTRACT_HASH_DOMAIN, SYNCED_SOURCE_PATTERN, SYNCED_VIEW_EXECUTION_OWNER_ROLE, TABLE_BRAND, VIEW_BRAND, actionFunctionName, actionFunctionStatements, actionParamArg, actionParamOrder, actionParamSchema, actionPrepareChecks, actionSchema, actionWriteTargets, actionsInterfaceName, activeAuthoringContext, applyMigrationHints, applyMigrationHintsV2, beginAuthoringContext, buildActionParamsSchema, buildDrizzleEntities, buildDrizzleEntitiesV2, buildNamespaceDefinition, buildRebaseJournalEntry, canonicalActionSchema, canonicalColumnSchema, canonicalDefinitionSchema, canonicalEnumSchema, canonicalIndexSchema, canonicalLinkSchema, canonicalPoliciesSchema, canonicalRelations, canonicalTableSchema, canonicalViewSchema, canonicalizeDefinition, capabilityExpression, castParts, cellColumnName, checksumOf, claimExpression, classifyDestructive, columnSchema, columnTypeSchema2 as columnTypeSchema, compileActionRequires, compileActionStatements, compileNamespace, compilePredIrToSql, compilePredicate, compiledArtifactSchema, compiledOperationSchema, computeCanonicalHash, computeDefinitionHash, computeSyncedContractHash, consumerRoleName, convertV1DefinitionToCanonical, createOrmMigrationExport, custom, declaredCapabilityKeys, defineEnum, defineNamespace, defineOperation, defineResolvedTable, defineSyncedTable, defineTable, defineView, deriveColumnName, diffCommand, diffStatements, emptyJournal, emptySnapshot, endAuthoringContext, etlSource, extractNamedParams, extractOrmSyncedTableContract, generateNamespaceTypes, generateSnapshot, generateSnapshotV2, highest, identifierSchema, importSpecSchema, indexByHash, isColumnBuilder, isEnumRef, isFunctionDefault, isOwnedStatement, isOwnedStatementV2, isQualifiedReference, isSeqLink, isSeqNamespaceConfig, isSeqTable, isSeqView, latest, limitIrSchema, loadCommittedMigrations, loadCommittedTipMigration, loadNamespaceDefinition, loadNamespaceFromDir, lowest, managedFn, manualSource, materializeLockKey, materializedRefreshFunctionName, migrationName, namespaceConfigSchema, namespaceSchema, nonNullFirst, normalizeCanonical, normalizeIr, normalizeSnapshot, objectRef, ontologyContractSchema, orderIrSchema, ormMigrationExportSchema, ormSchemaName, overlayWinsUnion, overrideRowMutation, parseCanonicalDefinition, parseDefinitionSources, parseOrmMigrationExport, parsePredicate, parseTableFile, parsedPredicateSchema, pendingKitStatements, pendingKitStatementsV2, planCommittedMigrationV2, planMigration, planMigrationV2, planTableImport, policyExpressionSchema, policyVariantSchema, predIrSchema, predicateOperands, prefetchPlanIrSchema, prefetchSource, priority, quoteIdentifier, quoteLiteral, readMigrationSql, readMigrationWorkspace, readOntologyContract, readSnapshot, rebaseViolations, referencedCapabilities, referencedColumns, renderMigrationSql, renderOrmMigrationExport, requiredArtifactIrVersion, resolvedMetaIrSchema, resolvedSourceIrSchema, revertOverlayMutation, rewriteSyncedSourceRelationsInViewQuery, roleExpression, rootIrSchema, securityStatements, selectionIrSchema, serializeNamespace, sqlTypeName, stableJson, syncedBackingRevokeStatements, syncedContractSurface, syncedTables, syncedViewDropStatements, syncedViewStatements, t, tableFileSchema, tableMetaIrSchema, tableReferenceSchema, toMany, toOne, toPlatformUser, typesInterfaceName, validateNamespaceCatalog, validateViewCatalogStatement, valueIrSchema, variableDefaultIrSchema, variableIrSchema, verifyRebaseIsNoop, walkPredicate, writeMigration };
7279
8040
  //# sourceMappingURL=index.js.map
7280
8041
  //# sourceMappingURL=index.js.map