@sequenceholdings/orm 2.1.1 → 2.3.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 +5876 -4198
  15. package/dist/cli.cjs.map +1 -1
  16. package/dist/cli.js +5876 -4198
  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 +1275 -264
  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 +1268 -265
  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 +1103 -322
  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 +1090 -323
  45. package/dist/index.js.map +1 -1
  46. package/dist/ir.cjs +93 -11
  47. package/dist/ir.cjs.map +1 -1
  48. package/dist/ir.d.cts +226 -15
  49. package/dist/ir.d.ts +226 -15
  50. package/dist/ir.js +88 -12
  51. package/dist/ir.js.map +1 -1
  52. package/dist/predicate-v2.cjs +116 -10
  53. package/dist/predicate-v2.cjs.map +1 -1
  54. package/dist/predicate-v2.d.cts +11 -3
  55. package/dist/predicate-v2.d.ts +11 -3
  56. package/dist/predicate-v2.js +116 -10
  57. package/dist/predicate-v2.js.map +1 -1
  58. package/dist/sdl.cjs +158 -22
  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 +158 -22
  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/sdl.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { B as BUCKETABLE_COLUMN_TYPES, C as CELL_TYPENAMES, a as CUSTOM_SCALARS, D as DATE_BUCKET_ENUM, N as NUMERICISH_COLUMN_TYPES, O as ORDER_BY_ENUM, b as ORDER_BY_ENUM_VALUES, P as PLATFORM_USER_TYPENAME, T as TableNames, V as VARIABLE_SCALAR_NAMES, c as camelCase, d as cellsTypename, e as columnTypeForScalar, f as comparisonExpName, g as enumTypeName, h as fieldName, i as graphqlScalarFor, p as pascalCase, t as tableNames, j as typeName } from './naming-CU9ThP_E.cjs';
2
2
  import { CanonicalDefinition, CanonicalRelation, CanonicalColumn } from './canonical.cjs';
3
3
  import { z } from 'zod';
4
- import './constants-YoFGjIBM.cjs';
4
+ import './constants-C6EG6Wq7.cjs';
5
5
  import './policy-1iZbGnZZ.cjs';
6
6
 
7
7
  /**
@@ -30,6 +30,13 @@ interface GenerateSdlOptions {
30
30
  * Postgres `columnName`.
31
31
  */
32
32
  pinnedColumns?: Record<string, string[]>;
33
+ /**
34
+ * Declare `_like`/`_ilike` on String only, as @sequenceholdings/orm 2.1.x
35
+ * generated it, before integer and uuid columns took pattern filters. Atlas
36
+ * regenerates this shape only to recognize a schema.graphql pushed by a
37
+ * released CLI; operations always compile against the default shape.
38
+ */
39
+ stringOnlyPatternOperators?: boolean;
33
40
  }
34
41
  declare function generateSdl(canonical: CanonicalDefinition, options?: GenerateSdlOptions): string;
35
42
  /** Columns a resolved-table mutation may write: authored data columns, never the view's system columns. */
package/dist/sdl.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { B as BUCKETABLE_COLUMN_TYPES, C as CELL_TYPENAMES, a as CUSTOM_SCALARS, D as DATE_BUCKET_ENUM, N as NUMERICISH_COLUMN_TYPES, O as ORDER_BY_ENUM, b as ORDER_BY_ENUM_VALUES, P as PLATFORM_USER_TYPENAME, T as TableNames, V as VARIABLE_SCALAR_NAMES, c as camelCase, d as cellsTypename, e as columnTypeForScalar, f as comparisonExpName, g as enumTypeName, h as fieldName, i as graphqlScalarFor, p as pascalCase, t as tableNames, j as typeName } from './naming-CPfx7EfF.js';
2
2
  import { CanonicalDefinition, CanonicalRelation, CanonicalColumn } from './canonical.js';
3
3
  import { z } from 'zod';
4
- import './constants-YoFGjIBM.js';
4
+ import './constants-C6EG6Wq7.js';
5
5
  import './policy-1iZbGnZZ.js';
6
6
 
7
7
  /**
@@ -30,6 +30,13 @@ interface GenerateSdlOptions {
30
30
  * Postgres `columnName`.
31
31
  */
32
32
  pinnedColumns?: Record<string, string[]>;
33
+ /**
34
+ * Declare `_like`/`_ilike` on String only, as @sequenceholdings/orm 2.1.x
35
+ * generated it, before integer and uuid columns took pattern filters. Atlas
36
+ * regenerates this shape only to recognize a schema.graphql pushed by a
37
+ * released CLI; operations always compile against the default shape.
38
+ */
39
+ stringOnlyPatternOperators?: boolean;
33
40
  }
34
41
  declare function generateSdl(canonical: CanonicalDefinition, options?: GenerateSdlOptions): string;
35
42
  /** Columns a resolved-table mutation may write: authored data columns, never the view's system columns. */
package/dist/sdl.js CHANGED
@@ -204,6 +204,7 @@ function compileCheckExpression(source, columns) {
204
204
  // src/constants.ts
205
205
  var COLUMN_IDENTIFIER_PATTERN = /^_?[a-z][a-z0-9_]*$/;
206
206
  var MAX_IDENTIFIER_LENGTH = 63;
207
+ var QUALIFIED_TABLE_PATTERN = /^[a-z][a-z0-9_]{0,62}\.[a-z][a-z0-9_]{0,62}$/;
207
208
  var CELL_PARTS = ["at", "by", "rev", "source", "conflicts"];
208
209
  var CELL_PART_SUFFIX = {
209
210
  at: "__at",
@@ -536,6 +537,8 @@ var canonicalLinkSchema = z.object({
536
537
  kind: z.enum(["toOne", "toMany", "toPlatformUser"]),
537
538
  /** Target table name (namespace-local). Absent for toPlatformUser. */
538
539
  target: identifier2.optional(),
540
+ /** Owning namespace of an imported target; omitted for local links. */
541
+ namespace: identifier2.max(41).optional(),
539
542
  /** FK column on the owning side (toOne/toPlatformUser: on this table; toMany: on the target). */
540
543
  on: columnIdentifier,
541
544
  /** Referenced column on the target (default: target's PK / platform user `sub`). */
@@ -637,11 +640,12 @@ var canonicalForeignKeySchema = z.object({
637
640
  }).strict();
638
641
  var canonicalTableSchema = z.object({
639
642
  table: identifier2,
643
+ displayName: z.string().trim().min(1).max(120).optional(),
640
644
  description: z.string().max(2e3).optional(),
641
645
  /** Table-level rename hint (new in v2). */
642
646
  renamedFrom: identifier2.optional(),
643
- /** Synced/reflected read-only tables (`source: gold.*`) — v1 semantics. */
644
- source: z.string().regex(/^gold\.[a-z][a-z0-9_]*$/).optional(),
647
+ /** Synced/reflected read-only tables (`source: schema.table`) — v1 semantics. */
648
+ source: z.string().regex(QUALIFIED_TABLE_PATTERN).optional(),
645
649
  columns: z.array(canonicalColumnSchema).default([]),
646
650
  primaryKey: z.array(columnIdentifier).min(1).max(8).optional(),
647
651
  links: z.array(canonicalLinkSchema).default([]),
@@ -794,7 +798,9 @@ function validateCellMetadata(table, index, ctx) {
794
798
  }
795
799
  }
796
800
  }
797
- var canonicalDefinitionSchema = z.object({
801
+ var exportGateSchema = z.union([z.literal(true), z.object({ capability: z.string().min(1) }).strict(), z.object({ role: z.string().min(1) }).strict()]);
802
+ var relationExportSchema = z.object({ read: exportGateSchema, write: exportGateSchema.optional() }).strict();
803
+ var localDefinitionSchema = z.object({
798
804
  definition_format: z.literal(CANONICAL_FORMAT),
799
805
  namespace: identifier2.max(41),
800
806
  description: z.string().max(2e3).optional(),
@@ -802,6 +808,8 @@ var canonicalDefinitionSchema = z.object({
802
808
  tables: z.array(canonicalTableSchema).min(0).max(500),
803
809
  /** Optional to preserve byte-identical hashes for pre-view canonical v2 documents. */
804
810
  views: z.array(canonicalViewSchema).max(500).optional(),
811
+ /** Target-owned cross-namespace access contract, using existing namespace grants. */
812
+ exports: z.record(identifier2, relationExportSchema).optional(),
805
813
  /** Verbatim custom-roles grammar (@sequenceholdings/custom-roles-manifest). */
806
814
  capabilities: z.object({
807
815
  roles: z.unknown().optional(),
@@ -828,7 +836,16 @@ var canonicalDefinitionSchema = z.object({
828
836
  }
829
837
  }
830
838
  const fkTables = new Map(definition.tables.map((table) => [table.table, table]));
839
+ const relations = /* @__PURE__ */ new Set([...fkTables.keys(), ...(definition.views ?? []).map((view) => view.view)]);
840
+ for (const name of Object.keys(definition.exports ?? {})) {
841
+ if (!relations.has(name)) ctx.addIssue({ code: "custom", path: ["exports", name], message: `export '${name}' is not a local object` });
842
+ }
831
843
  for (const [tableIndex, table] of definition.tables.entries()) {
844
+ for (const [linkIndex, link] of table.links.entries()) {
845
+ if (link.enforce && link.namespace !== void 0 && link.namespace !== definition.namespace) {
846
+ ctx.addIssue({ code: "custom", path: ["tables", tableIndex, "links", linkIndex], message: "physical foreign keys require a local target; use an ORM link without enforce" });
847
+ }
848
+ }
832
849
  const names = /* @__PURE__ */ new Set([
833
850
  ...table.primaryKey?.length ? [`${table.table}_pkey`] : [],
834
851
  ...table.columns.filter((column) => column.unique && !(table.primaryKey?.length === 1 && table.primaryKey[0] === column.columnName)).map((column) => `${table.table}_${column.columnName}_unique`),
@@ -998,6 +1015,10 @@ var canonicalDefinitionSchema = z.object({
998
1015
  };
999
1016
  for (const view of views) visit(view.view, []);
1000
1017
  });
1018
+ var canonicalDefinitionSchema = localDefinitionSchema.safeExtend({
1019
+ /** Flattened, pinned snapshots. Imported relations never participate in this namespace's DDL. */
1020
+ imports: z.array(localDefinitionSchema).max(32).optional()
1021
+ });
1001
1022
  function canonicalRelations(definition) {
1002
1023
  const views = (definition.views ?? []).map((view) => ({
1003
1024
  table: view.view,
@@ -1041,6 +1062,11 @@ function normalizeCanonical(definition) {
1041
1062
  dependencies: [...view.dependencies].sort()
1042
1063
  }));
1043
1064
  }
1065
+ if (definition.imports?.length) {
1066
+ normalized.imports = definition.imports.map(normalizeCanonical).sort((a, b) => a.namespace.localeCompare(b.namespace));
1067
+ } else {
1068
+ delete normalized.imports;
1069
+ }
1044
1070
  return normalized;
1045
1071
  }
1046
1072
 
@@ -1171,15 +1197,19 @@ var CELL_TYPENAMES = {
1171
1197
  function cellsTypename(typename) {
1172
1198
  return `${typename}Cells`;
1173
1199
  }
1174
- var IR_VERSION = 2;
1175
1200
  var LEGACY_IR_VERSION = 1;
1176
- var irVersionSchema = z.union([z.literal(LEGACY_IR_VERSION), z.literal(IR_VERSION)]);
1201
+ var GUARDED_IR_VERSION = 2;
1202
+ var COMPOSED_IR_VERSION = 3;
1203
+ var SQL_IR_VERSION = 4;
1204
+ var RUNTIME_SQL_IR_VERSION = 5;
1205
+ 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)]);
1177
1206
  z.object({ irVersion: irVersionSchema });
1207
+ var EXTERNAL_POLICY_CLAIM_KEYS = ["ext_subject", "ext_email"];
1178
1208
  var scalarLiteral = z.union([z.string(), z.number(), z.boolean(), z.null()]);
1179
1209
  var valueIrSchema = z.discriminatedUnion("kind", [
1180
1210
  z.object({ kind: z.literal("literal"), value: z.union([scalarLiteral, z.array(scalarLiteral)]) }),
1181
1211
  z.object({ kind: z.literal("variable"), name: z.string() }),
1182
- z.object({ kind: z.literal("claim"), key: z.enum(["sub", "org"]) })
1212
+ z.object({ kind: z.literal("claim"), key: z.enum(["sub", "org", ...EXTERNAL_POLICY_CLAIM_KEYS]) })
1183
1213
  ]);
1184
1214
  var CMP_OPS = [
1185
1215
  "eq",
@@ -1211,8 +1241,8 @@ var predIrSchema = z.lazy(
1211
1241
  value: z.number(),
1212
1242
  where: predIrSchema.optional()
1213
1243
  }),
1214
- z.object({ kind: z.literal("capability"), key: z.string() }),
1215
- z.object({ kind: z.literal("role"), key: z.string() }),
1244
+ z.object({ kind: z.literal("capability"), key: z.string(), namespace: z.string().optional() }),
1245
+ z.object({ kind: z.literal("role"), key: z.string(), namespace: z.string().optional() }),
1216
1246
  z.object({ kind: z.literal("dynamicFilter"), slot: z.string() }),
1217
1247
  z.object({ kind: z.literal("const"), value: z.boolean() })
1218
1248
  ])
@@ -1439,7 +1469,31 @@ var variableIrSchema = z.object({
1439
1469
  /** Absent = no default declared; see {@link variableDefaultIrSchema}. */
1440
1470
  defaultValue: variableDefaultIrSchema.optional()
1441
1471
  });
1472
+ var sqlColumnSchema = z.object({ name: z.string(), type: z.enum(["text", "boolean", "integer", "bigint", "numeric", "double", "uuid", "date", "timestamptz"]), nullable: z.boolean() });
1442
1473
  var compiledOperationSchema = z.object({
1474
+ language: z.literal("sql").optional(),
1475
+ /** Server-compiled object catalog and permission ceiling, never caller SQL. */
1476
+ sqlQuery: z.object({
1477
+ catalog: z.object({
1478
+ identity: z.string(),
1479
+ objects: z.array(z.object({
1480
+ ref: z.string(),
1481
+ table: z.string(),
1482
+ columns: z.array(sqlColumnSchema.extend({ type: z.string() })).min(1),
1483
+ scan: z.string().min(1),
1484
+ read: z.array(z.string()).min(1)
1485
+ }).strict()).min(1).max(256)
1486
+ }).strict(),
1487
+ read: z.array(z.string()).min(1).max(256),
1488
+ maxRows: z.number().int().min(1).max(1e4)
1489
+ }).strict().optional(),
1490
+ sql: z.object({
1491
+ text: z.string().min(1).max(1048576),
1492
+ columns: z.array(sqlColumnSchema).min(1).max(256),
1493
+ parameters: z.array(z.string()).max(128),
1494
+ read: z.array(z.string()).min(1).max(256),
1495
+ maxRows: z.number().int().min(1).max(1e4)
1496
+ }).strict().optional(),
1443
1497
  irVersion: irVersionSchema,
1444
1498
  name: z.string(),
1445
1499
  opHash: z.string().regex(/^sha256:[0-9a-f]{64}$/),
@@ -1451,8 +1505,16 @@ var compiledOperationSchema = z.object({
1451
1505
  variables: z.array(variableIrSchema),
1452
1506
  /** Every table the op touches — data-token scoping + audit. */
1453
1507
  tableSet: z.array(z.string()).min(1),
1454
- roots: z.array(rootIrSchema).min(1)
1508
+ roots: z.array(rootIrSchema)
1455
1509
  }).superRefine((operation, ctx) => {
1510
+ if (operation.language === "sql") {
1511
+ const validPlan = operation.sqlQuery ? !operation.sql && operation.irVersion === RUNTIME_SQL_IR_VERSION : !!operation.sql && operation.irVersion === SQL_IR_VERSION;
1512
+ if (!validPlan || operation.kind !== "query" || operation.roots.length !== 0 || !operation.requires?.capability) {
1513
+ ctx.addIssue({ code: "custom", message: "SQL operations require a query-only v4 plan or v5 runtime contract, capability, and no GraphQL roots" });
1514
+ }
1515
+ } else if (operation.sql || operation.sqlQuery || operation.roots.length === 0) {
1516
+ ctx.addIssue({ code: "custom", message: "GraphQL operations require roots and cannot carry SQL" });
1517
+ }
1456
1518
  for (const [index, root] of operation.roots.entries()) {
1457
1519
  if (root.kind !== "mutation" || root.assertAffectedRows === void 0) continue;
1458
1520
  if (operation.irVersion < 2 || operation.kind !== "mutation" || root.includeIf !== void 0) {
@@ -1499,11 +1561,16 @@ var resolvedMetaIrSchema = z.object({
1499
1561
  });
1500
1562
  var tableMetaIrSchema = z.object({
1501
1563
  table: z.string(),
1564
+ namespace: z.string().optional(),
1565
+ dependencies: z.array(z.string()).optional(),
1566
+ foreignReferences: z.array(z.object({ column: z.string(), target: z.string(), targetColumn: z.string() })).optional(),
1567
+ exportRead: z.union([z.literal(true), z.object({ capability: z.string() }), z.object({ role: z.string() })]).optional(),
1568
+ exportWrite: z.union([z.literal(true), z.object({ capability: z.string() }), z.object({ role: z.string() })]).optional(),
1502
1569
  schema: z.string(),
1503
1570
  typename: z.string(),
1504
1571
  /**
1505
1572
  * True when statements over this relation evaluate a claims-gated synced
1506
- * view: synced twins (`source: gold.*`) materialize as views whose baked
1573
+ * view: synced twins (`source: schema.table`) materialize as views whose baked
1507
1574
  * policy reads `current_setting('request.jwt.claims')`, and namespace views
1508
1575
  * inherit the gate transitively through their declared dependencies. The
1509
1576
  * executor must stamp that GUC (transaction-scoped) before any statement
@@ -1562,10 +1629,18 @@ z.object({
1562
1629
  irVersion: irVersionSchema,
1563
1630
  namespace: z.string(),
1564
1631
  schemaHash: z.string(),
1632
+ ownSchemaHash: z.string().optional(),
1633
+ dependencies: z.record(z.string(), z.string()).optional(),
1634
+ readPolicies: z.record(z.string(), predIrSchema).optional(),
1565
1635
  opsHash: z.string(),
1636
+ /** Apply-observed synced objects without a serving backing; not part of the authored schema hash. */
1637
+ unbackedTables: z.array(z.string()).optional(),
1566
1638
  tables: z.record(z.string(), tableMetaIrSchema),
1567
1639
  operations: z.record(z.string(), compiledOperationSchema)
1568
1640
  }).superRefine((artifact, ctx) => {
1641
+ if (Object.keys(artifact.dependencies ?? {}).length > 0 && artifact.irVersion < COMPOSED_IR_VERSION) {
1642
+ ctx.addIssue({ code: "custom", path: ["irVersion"], message: "cross-namespace dependencies require IR v3" });
1643
+ }
1569
1644
  for (const [name, operation] of Object.entries(artifact.operations)) {
1570
1645
  if (operation.irVersion > artifact.irVersion) {
1571
1646
  ctx.addIssue({ code: "custom", path: ["operations", name, "irVersion"], message: "operation requires a newer IR version than its artifact" });
@@ -1573,6 +1648,70 @@ z.object({
1573
1648
  }
1574
1649
  });
1575
1650
 
1651
+ // src/errors.ts
1652
+ var OrmDefinitionError = class extends Error {
1653
+ constructor(message, file) {
1654
+ super(file ? `${file}: ${message}` : message);
1655
+ this.file = file;
1656
+ }
1657
+ name = "OrmDefinitionError";
1658
+ };
1659
+ function stableJson(value) {
1660
+ if (value === null || typeof value !== "object") return JSON.stringify(value);
1661
+ if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
1662
+ const entries = Object.entries(value).filter(([, entryValue]) => entryValue !== void 0).sort(([a], [b]) => a < b ? -1 : 1).map(([key, entryValue]) => `${JSON.stringify(key)}:${stableJson(entryValue)}`);
1663
+ return `{${entries.join(",")}}`;
1664
+ }
1665
+
1666
+ // src/canonical/composition.ts
1667
+ function localContract(definition) {
1668
+ return normalizeCanonical(localDefinitionSchema.parse(definition));
1669
+ }
1670
+ function composeNamespace(definition) {
1671
+ const all = [localContract(definition), ...definition.imports ?? []];
1672
+ const owners = /* @__PURE__ */ new Map();
1673
+ const namespaces = /* @__PURE__ */ new Set();
1674
+ const enums = /* @__PURE__ */ new Map();
1675
+ for (const owner of all) {
1676
+ if (namespaces.has(owner.namespace)) throw new OrmDefinitionError(`duplicate imported namespace '${owner.namespace}'`);
1677
+ namespaces.add(owner.namespace);
1678
+ for (const value of owner.enums) {
1679
+ const previous = enums.get(value.name);
1680
+ if (previous && stableJson(previous) !== stableJson(value)) {
1681
+ throw new OrmDefinitionError(`conflicting imported enum '${value.name}'`);
1682
+ }
1683
+ enums.set(value.name, value);
1684
+ }
1685
+ for (const relation of canonicalRelations(owner)) {
1686
+ if (owners.has(relation.table)) throw new OrmDefinitionError(`ambiguous imported relation '${relation.table}'`);
1687
+ owners.set(relation.table, owner);
1688
+ }
1689
+ }
1690
+ for (const owner of definition.imports?.length ? all : []) {
1691
+ for (const relation of canonicalRelations(owner)) {
1692
+ for (const link of relation.links) {
1693
+ if (link.kind === "toPlatformUser") continue;
1694
+ const target = owners.get(link.target ?? "");
1695
+ if (!target || target.namespace !== (link.namespace ?? owner.namespace)) {
1696
+ throw new OrmDefinitionError(`link '${owner.namespace}/${relation.table}.${link.name}' has no matching imported target`);
1697
+ }
1698
+ if (target.namespace !== owner.namespace && !target.exports?.[link.target ?? ""]) {
1699
+ throw new OrmDefinitionError(`target '${target.namespace}/${link.target}' is not exported`);
1700
+ }
1701
+ }
1702
+ }
1703
+ }
1704
+ return {
1705
+ owners,
1706
+ definition: {
1707
+ ...localContract(definition),
1708
+ tables: all.flatMap((item) => item.tables),
1709
+ views: all.flatMap((item) => item.views ?? []),
1710
+ enums: [...enums.values()]
1711
+ }
1712
+ };
1713
+ }
1714
+
1576
1715
  // src/sdl/generate.ts
1577
1716
  var SdlGenerationError = class extends Error {
1578
1717
  constructor(message) {
@@ -1593,7 +1732,7 @@ var PLATFORM_USER_FIELDS = [
1593
1732
  { name: "accountEnabled", gqlType: "Boolean", nullable: false }
1594
1733
  ];
1595
1734
  function generateSdl(canonical, options = {}) {
1596
- const def = normalizeCanonical(canonicalDefinitionSchema.parse(canonical));
1735
+ const def = composeNamespace(normalizeCanonical(canonicalDefinitionSchema.parse(canonical))).definition;
1597
1736
  const exposed = canonicalRelations(def).filter((table) => table.source === void 0 && table.internal !== true);
1598
1737
  const cellsByTable = new Map(exposed.map((table) => [table.table, trackedCells(table)]));
1599
1738
  const tables = exposed.map((table) => ({ ...table, columns: table.columns.filter((column) => column.cell === void 0) }));
@@ -1666,11 +1805,12 @@ function generateSdl(canonical, options = {}) {
1666
1805
  for (const value of entry.values) assertEnumValue(value, `enum "${enumName}"`);
1667
1806
  blocks.push(renderEnum(enumTypeName(enumName), entry.values));
1668
1807
  }
1808
+ const patternTypes = options.stringOnlyPatternOperators ? STRING_PATTERN_COMPARISON_TYPES : PATTERN_COMPARISON_TYPES;
1669
1809
  for (const scalar of [...usedComparisonScalars].sort()) {
1670
- blocks.push(renderComparisonExp(scalar));
1810
+ blocks.push(renderComparisonExp({ gqlTypeName: scalar, patternTypes }));
1671
1811
  }
1672
1812
  for (const enumName of [...usedEnums].sort()) {
1673
- blocks.push(renderComparisonExp(enumTypeName(enumName)));
1813
+ blocks.push(renderComparisonExp({ gqlTypeName: enumTypeName(enumName), patternTypes }));
1674
1814
  }
1675
1815
  if (hasPlatformUser) blocks.push(...renderPlatformUserBlocks());
1676
1816
  for (const table of tables) {
@@ -1724,7 +1864,9 @@ function descriptionLines(text, indent) {
1724
1864
  const escaped = text.replace(/"""/g, '\\"""');
1725
1865
  return [`${indent}"""`, ...escaped.split("\n").map((line) => `${indent}${line}`), `${indent}"""`];
1726
1866
  }
1727
- function renderComparisonExp(gqlTypeName) {
1867
+ var PATTERN_COMPARISON_TYPES = /* @__PURE__ */ new Set(["String", "Int", "bigint", "uuid"]);
1868
+ var STRING_PATTERN_COMPARISON_TYPES = /* @__PURE__ */ new Set(["String"]);
1869
+ function renderComparisonExp({ gqlTypeName, patternTypes }) {
1728
1870
  const fields = [
1729
1871
  ["_eq", gqlTypeName],
1730
1872
  ["_neq", gqlTypeName],
@@ -1736,7 +1878,7 @@ function renderComparisonExp(gqlTypeName) {
1736
1878
  ["_nin", `[${gqlTypeName}!]`],
1737
1879
  ["_isNull", "Boolean"]
1738
1880
  ];
1739
- if (gqlTypeName === "String") {
1881
+ if (patternTypes.has(gqlTypeName)) {
1740
1882
  fields.push(["_like", "String"], ["_ilike", "String"]);
1741
1883
  }
1742
1884
  if (gqlTypeName === "jsonb") {
@@ -2235,12 +2377,6 @@ function renderCowMutationFields(table, names) {
2235
2377
  }
2236
2378
  return lines;
2237
2379
  }
2238
- function stableJson(value) {
2239
- if (value === null || typeof value !== "object") return JSON.stringify(value);
2240
- if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
2241
- const entries = Object.entries(value).filter(([, entryValue]) => entryValue !== void 0).sort(([a], [b]) => a < b ? -1 : 1).map(([key, entryValue]) => `${JSON.stringify(key)}:${stableJson(entryValue)}`);
2242
- return `{${entries.join(",")}}`;
2243
- }
2244
2380
 
2245
2381
  // src/codegen-gql/errors.ts
2246
2382
  var CodegenGqlError = class extends Error {
@@ -2311,7 +2447,7 @@ function normalizeRequires(requires) {
2311
2447
 
2312
2448
  // src/codegen-gql/type-policies.ts
2313
2449
  function generateTypePolicies(canonical) {
2314
- const def = normalizeCanonical(canonicalDefinitionSchema.parse(canonical));
2450
+ const def = composeNamespace(normalizeCanonical(canonicalDefinitionSchema.parse(canonical))).definition;
2315
2451
  const entries = [];
2316
2452
  let hasPlatformUser = false;
2317
2453
  for (const table of canonicalRelations(def)) {