@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.
- package/README.md +3 -1
- package/dist/authoring.cjs +284 -99
- package/dist/authoring.cjs.map +1 -1
- package/dist/authoring.d.cts +31 -8
- package/dist/authoring.d.ts +31 -8
- package/dist/authoring.js +282 -100
- package/dist/authoring.js.map +1 -1
- package/dist/canonical.cjs +51 -3
- package/dist/canonical.cjs.map +1 -1
- package/dist/canonical.d.cts +838 -12
- package/dist/canonical.d.ts +838 -12
- package/dist/canonical.js +47 -4
- package/dist/canonical.js.map +1 -1
- package/dist/cli.cjs +5876 -4198
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +5876 -4198
- package/dist/cli.js.map +1 -1
- package/dist/client.cjs +49 -32
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +49 -6
- package/dist/client.d.ts +49 -6
- package/dist/client.js +49 -32
- package/dist/client.js.map +1 -1
- package/dist/compiler.cjs +1275 -264
- package/dist/compiler.cjs.map +1 -1
- package/dist/compiler.d.cts +57 -3
- package/dist/compiler.d.ts +57 -3
- package/dist/compiler.js +1268 -265
- package/dist/compiler.js.map +1 -1
- package/dist/{constants-YoFGjIBM.d.cts → constants-C6EG6Wq7.d.cts} +1 -1
- package/dist/{constants-YoFGjIBM.d.ts → constants-C6EG6Wq7.d.ts} +1 -1
- package/dist/definition-DjfC7Lll.d.cts +91 -0
- package/dist/definition-DjfC7Lll.d.ts +91 -0
- package/dist/dynamic-input.cjs +2 -1
- package/dist/dynamic-input.cjs.map +1 -1
- package/dist/dynamic-input.d.cts +9 -2
- package/dist/dynamic-input.d.ts +9 -2
- package/dist/dynamic-input.js +2 -1
- package/dist/dynamic-input.js.map +1 -1
- package/dist/index.cjs +1103 -322
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +479 -19
- package/dist/index.d.ts +479 -19
- package/dist/index.js +1090 -323
- package/dist/index.js.map +1 -1
- package/dist/ir.cjs +93 -11
- package/dist/ir.cjs.map +1 -1
- package/dist/ir.d.cts +226 -15
- package/dist/ir.d.ts +226 -15
- package/dist/ir.js +88 -12
- package/dist/ir.js.map +1 -1
- package/dist/predicate-v2.cjs +116 -10
- package/dist/predicate-v2.cjs.map +1 -1
- package/dist/predicate-v2.d.cts +11 -3
- package/dist/predicate-v2.d.ts +11 -3
- package/dist/predicate-v2.js +116 -10
- package/dist/predicate-v2.js.map +1 -1
- package/dist/sdl.cjs +158 -22
- package/dist/sdl.cjs.map +1 -1
- package/dist/sdl.d.cts +8 -1
- package/dist/sdl.d.ts +8 -1
- package/dist/sdl.js +158 -22
- package/dist/sdl.js.map +1 -1
- package/package.json +5 -4
- package/src/codegen-gql/server-fns.cjs +2 -2
- package/templates/orm-namespace/AGENTS.md +10 -0
- package/templates/orm-namespace/CLAUDE.md +1 -84
- 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-
|
|
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-
|
|
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:
|
|
644
|
-
source: z.string().regex(
|
|
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
|
|
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
|
|
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)
|
|
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:
|
|
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
|
-
|
|
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
|
|
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)) {
|