@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.
- 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 +5838 -4197
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +5838 -4197
- 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 +1237 -263
- 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 +1230 -264
- 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 +1094 -321
- 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 +1083 -322
- package/dist/index.js.map +1 -1
- package/dist/ir.cjs +84 -10
- package/dist/ir.cjs.map +1 -1
- package/dist/ir.d.cts +138 -13
- package/dist/ir.d.ts +138 -13
- package/dist/ir.js +81 -11
- package/dist/ir.js.map +1 -1
- package/dist/predicate-v2.cjs +78 -9
- package/dist/predicate-v2.cjs.map +1 -1
- package/dist/predicate-v2.d.cts +1 -1
- package/dist/predicate-v2.d.ts +1 -1
- package/dist/predicate-v2.js +78 -9
- package/dist/predicate-v2.js.map +1 -1
- package/dist/sdl.cjs +156 -21
- 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 +156 -21
- 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,9 +1197,12 @@ 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 });
|
|
1178
1207
|
var scalarLiteral = z.union([z.string(), z.number(), z.boolean(), z.null()]);
|
|
1179
1208
|
var valueIrSchema = z.discriminatedUnion("kind", [
|
|
@@ -1211,8 +1240,8 @@ var predIrSchema = z.lazy(
|
|
|
1211
1240
|
value: z.number(),
|
|
1212
1241
|
where: predIrSchema.optional()
|
|
1213
1242
|
}),
|
|
1214
|
-
z.object({ kind: z.literal("capability"), key: z.string() }),
|
|
1215
|
-
z.object({ kind: z.literal("role"), key: z.string() }),
|
|
1243
|
+
z.object({ kind: z.literal("capability"), key: z.string(), namespace: z.string().optional() }),
|
|
1244
|
+
z.object({ kind: z.literal("role"), key: z.string(), namespace: z.string().optional() }),
|
|
1216
1245
|
z.object({ kind: z.literal("dynamicFilter"), slot: z.string() }),
|
|
1217
1246
|
z.object({ kind: z.literal("const"), value: z.boolean() })
|
|
1218
1247
|
])
|
|
@@ -1439,7 +1468,31 @@ var variableIrSchema = z.object({
|
|
|
1439
1468
|
/** Absent = no default declared; see {@link variableDefaultIrSchema}. */
|
|
1440
1469
|
defaultValue: variableDefaultIrSchema.optional()
|
|
1441
1470
|
});
|
|
1471
|
+
var sqlColumnSchema = z.object({ name: z.string(), type: z.enum(["text", "boolean", "integer", "bigint", "numeric", "double", "uuid", "date", "timestamptz"]), nullable: z.boolean() });
|
|
1442
1472
|
var compiledOperationSchema = z.object({
|
|
1473
|
+
language: z.literal("sql").optional(),
|
|
1474
|
+
/** Server-compiled object catalog and permission ceiling, never caller SQL. */
|
|
1475
|
+
sqlQuery: z.object({
|
|
1476
|
+
catalog: z.object({
|
|
1477
|
+
identity: z.string(),
|
|
1478
|
+
objects: z.array(z.object({
|
|
1479
|
+
ref: z.string(),
|
|
1480
|
+
table: z.string(),
|
|
1481
|
+
columns: z.array(sqlColumnSchema.extend({ type: z.string() })).min(1),
|
|
1482
|
+
scan: z.string().min(1),
|
|
1483
|
+
read: z.array(z.string()).min(1)
|
|
1484
|
+
}).strict()).min(1).max(256)
|
|
1485
|
+
}).strict(),
|
|
1486
|
+
read: z.array(z.string()).min(1).max(256),
|
|
1487
|
+
maxRows: z.number().int().min(1).max(1e4)
|
|
1488
|
+
}).strict().optional(),
|
|
1489
|
+
sql: z.object({
|
|
1490
|
+
text: z.string().min(1).max(1048576),
|
|
1491
|
+
columns: z.array(sqlColumnSchema).min(1).max(256),
|
|
1492
|
+
parameters: z.array(z.string()).max(128),
|
|
1493
|
+
read: z.array(z.string()).min(1).max(256),
|
|
1494
|
+
maxRows: z.number().int().min(1).max(1e4)
|
|
1495
|
+
}).strict().optional(),
|
|
1443
1496
|
irVersion: irVersionSchema,
|
|
1444
1497
|
name: z.string(),
|
|
1445
1498
|
opHash: z.string().regex(/^sha256:[0-9a-f]{64}$/),
|
|
@@ -1451,8 +1504,16 @@ var compiledOperationSchema = z.object({
|
|
|
1451
1504
|
variables: z.array(variableIrSchema),
|
|
1452
1505
|
/** Every table the op touches — data-token scoping + audit. */
|
|
1453
1506
|
tableSet: z.array(z.string()).min(1),
|
|
1454
|
-
roots: z.array(rootIrSchema)
|
|
1507
|
+
roots: z.array(rootIrSchema)
|
|
1455
1508
|
}).superRefine((operation, ctx) => {
|
|
1509
|
+
if (operation.language === "sql") {
|
|
1510
|
+
const validPlan = operation.sqlQuery ? !operation.sql && operation.irVersion === RUNTIME_SQL_IR_VERSION : !!operation.sql && operation.irVersion === SQL_IR_VERSION;
|
|
1511
|
+
if (!validPlan || operation.kind !== "query" || operation.roots.length !== 0 || !operation.requires?.capability) {
|
|
1512
|
+
ctx.addIssue({ code: "custom", message: "SQL operations require a query-only v4 plan or v5 runtime contract, capability, and no GraphQL roots" });
|
|
1513
|
+
}
|
|
1514
|
+
} else if (operation.sql || operation.sqlQuery || operation.roots.length === 0) {
|
|
1515
|
+
ctx.addIssue({ code: "custom", message: "GraphQL operations require roots and cannot carry SQL" });
|
|
1516
|
+
}
|
|
1456
1517
|
for (const [index, root] of operation.roots.entries()) {
|
|
1457
1518
|
if (root.kind !== "mutation" || root.assertAffectedRows === void 0) continue;
|
|
1458
1519
|
if (operation.irVersion < 2 || operation.kind !== "mutation" || root.includeIf !== void 0) {
|
|
@@ -1499,11 +1560,16 @@ var resolvedMetaIrSchema = z.object({
|
|
|
1499
1560
|
});
|
|
1500
1561
|
var tableMetaIrSchema = z.object({
|
|
1501
1562
|
table: z.string(),
|
|
1563
|
+
namespace: z.string().optional(),
|
|
1564
|
+
dependencies: z.array(z.string()).optional(),
|
|
1565
|
+
foreignReferences: z.array(z.object({ column: z.string(), target: z.string(), targetColumn: z.string() })).optional(),
|
|
1566
|
+
exportRead: z.union([z.literal(true), z.object({ capability: z.string() }), z.object({ role: z.string() })]).optional(),
|
|
1567
|
+
exportWrite: z.union([z.literal(true), z.object({ capability: z.string() }), z.object({ role: z.string() })]).optional(),
|
|
1502
1568
|
schema: z.string(),
|
|
1503
1569
|
typename: z.string(),
|
|
1504
1570
|
/**
|
|
1505
1571
|
* True when statements over this relation evaluate a claims-gated synced
|
|
1506
|
-
* view: synced twins (`source:
|
|
1572
|
+
* view: synced twins (`source: schema.table`) materialize as views whose baked
|
|
1507
1573
|
* policy reads `current_setting('request.jwt.claims')`, and namespace views
|
|
1508
1574
|
* inherit the gate transitively through their declared dependencies. The
|
|
1509
1575
|
* executor must stamp that GUC (transaction-scoped) before any statement
|
|
@@ -1562,10 +1628,18 @@ z.object({
|
|
|
1562
1628
|
irVersion: irVersionSchema,
|
|
1563
1629
|
namespace: z.string(),
|
|
1564
1630
|
schemaHash: z.string(),
|
|
1631
|
+
ownSchemaHash: z.string().optional(),
|
|
1632
|
+
dependencies: z.record(z.string(), z.string()).optional(),
|
|
1633
|
+
readPolicies: z.record(z.string(), predIrSchema).optional(),
|
|
1565
1634
|
opsHash: z.string(),
|
|
1635
|
+
/** Apply-observed synced objects without a serving backing; not part of the authored schema hash. */
|
|
1636
|
+
unbackedTables: z.array(z.string()).optional(),
|
|
1566
1637
|
tables: z.record(z.string(), tableMetaIrSchema),
|
|
1567
1638
|
operations: z.record(z.string(), compiledOperationSchema)
|
|
1568
1639
|
}).superRefine((artifact, ctx) => {
|
|
1640
|
+
if (Object.keys(artifact.dependencies ?? {}).length > 0 && artifact.irVersion < COMPOSED_IR_VERSION) {
|
|
1641
|
+
ctx.addIssue({ code: "custom", path: ["irVersion"], message: "cross-namespace dependencies require IR v3" });
|
|
1642
|
+
}
|
|
1569
1643
|
for (const [name, operation] of Object.entries(artifact.operations)) {
|
|
1570
1644
|
if (operation.irVersion > artifact.irVersion) {
|
|
1571
1645
|
ctx.addIssue({ code: "custom", path: ["operations", name, "irVersion"], message: "operation requires a newer IR version than its artifact" });
|
|
@@ -1573,6 +1647,70 @@ z.object({
|
|
|
1573
1647
|
}
|
|
1574
1648
|
});
|
|
1575
1649
|
|
|
1650
|
+
// src/errors.ts
|
|
1651
|
+
var OrmDefinitionError = class extends Error {
|
|
1652
|
+
constructor(message, file) {
|
|
1653
|
+
super(file ? `${file}: ${message}` : message);
|
|
1654
|
+
this.file = file;
|
|
1655
|
+
}
|
|
1656
|
+
name = "OrmDefinitionError";
|
|
1657
|
+
};
|
|
1658
|
+
function stableJson(value) {
|
|
1659
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
1660
|
+
if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
|
|
1661
|
+
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)}`);
|
|
1662
|
+
return `{${entries.join(",")}}`;
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
// src/canonical/composition.ts
|
|
1666
|
+
function localContract(definition) {
|
|
1667
|
+
return normalizeCanonical(localDefinitionSchema.parse(definition));
|
|
1668
|
+
}
|
|
1669
|
+
function composeNamespace(definition) {
|
|
1670
|
+
const all = [localContract(definition), ...definition.imports ?? []];
|
|
1671
|
+
const owners = /* @__PURE__ */ new Map();
|
|
1672
|
+
const namespaces = /* @__PURE__ */ new Set();
|
|
1673
|
+
const enums = /* @__PURE__ */ new Map();
|
|
1674
|
+
for (const owner of all) {
|
|
1675
|
+
if (namespaces.has(owner.namespace)) throw new OrmDefinitionError(`duplicate imported namespace '${owner.namespace}'`);
|
|
1676
|
+
namespaces.add(owner.namespace);
|
|
1677
|
+
for (const value of owner.enums) {
|
|
1678
|
+
const previous = enums.get(value.name);
|
|
1679
|
+
if (previous && stableJson(previous) !== stableJson(value)) {
|
|
1680
|
+
throw new OrmDefinitionError(`conflicting imported enum '${value.name}'`);
|
|
1681
|
+
}
|
|
1682
|
+
enums.set(value.name, value);
|
|
1683
|
+
}
|
|
1684
|
+
for (const relation of canonicalRelations(owner)) {
|
|
1685
|
+
if (owners.has(relation.table)) throw new OrmDefinitionError(`ambiguous imported relation '${relation.table}'`);
|
|
1686
|
+
owners.set(relation.table, owner);
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
for (const owner of definition.imports?.length ? all : []) {
|
|
1690
|
+
for (const relation of canonicalRelations(owner)) {
|
|
1691
|
+
for (const link of relation.links) {
|
|
1692
|
+
if (link.kind === "toPlatformUser") continue;
|
|
1693
|
+
const target = owners.get(link.target ?? "");
|
|
1694
|
+
if (!target || target.namespace !== (link.namespace ?? owner.namespace)) {
|
|
1695
|
+
throw new OrmDefinitionError(`link '${owner.namespace}/${relation.table}.${link.name}' has no matching imported target`);
|
|
1696
|
+
}
|
|
1697
|
+
if (target.namespace !== owner.namespace && !target.exports?.[link.target ?? ""]) {
|
|
1698
|
+
throw new OrmDefinitionError(`target '${target.namespace}/${link.target}' is not exported`);
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
return {
|
|
1704
|
+
owners,
|
|
1705
|
+
definition: {
|
|
1706
|
+
...localContract(definition),
|
|
1707
|
+
tables: all.flatMap((item) => item.tables),
|
|
1708
|
+
views: all.flatMap((item) => item.views ?? []),
|
|
1709
|
+
enums: [...enums.values()]
|
|
1710
|
+
}
|
|
1711
|
+
};
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1576
1714
|
// src/sdl/generate.ts
|
|
1577
1715
|
var SdlGenerationError = class extends Error {
|
|
1578
1716
|
constructor(message) {
|
|
@@ -1593,7 +1731,7 @@ var PLATFORM_USER_FIELDS = [
|
|
|
1593
1731
|
{ name: "accountEnabled", gqlType: "Boolean", nullable: false }
|
|
1594
1732
|
];
|
|
1595
1733
|
function generateSdl(canonical, options = {}) {
|
|
1596
|
-
const def = normalizeCanonical(canonicalDefinitionSchema.parse(canonical));
|
|
1734
|
+
const def = composeNamespace(normalizeCanonical(canonicalDefinitionSchema.parse(canonical))).definition;
|
|
1597
1735
|
const exposed = canonicalRelations(def).filter((table) => table.source === void 0 && table.internal !== true);
|
|
1598
1736
|
const cellsByTable = new Map(exposed.map((table) => [table.table, trackedCells(table)]));
|
|
1599
1737
|
const tables = exposed.map((table) => ({ ...table, columns: table.columns.filter((column) => column.cell === void 0) }));
|
|
@@ -1666,11 +1804,12 @@ function generateSdl(canonical, options = {}) {
|
|
|
1666
1804
|
for (const value of entry.values) assertEnumValue(value, `enum "${enumName}"`);
|
|
1667
1805
|
blocks.push(renderEnum(enumTypeName(enumName), entry.values));
|
|
1668
1806
|
}
|
|
1807
|
+
const patternTypes = options.stringOnlyPatternOperators ? STRING_PATTERN_COMPARISON_TYPES : PATTERN_COMPARISON_TYPES;
|
|
1669
1808
|
for (const scalar of [...usedComparisonScalars].sort()) {
|
|
1670
|
-
blocks.push(renderComparisonExp(scalar));
|
|
1809
|
+
blocks.push(renderComparisonExp({ gqlTypeName: scalar, patternTypes }));
|
|
1671
1810
|
}
|
|
1672
1811
|
for (const enumName of [...usedEnums].sort()) {
|
|
1673
|
-
blocks.push(renderComparisonExp(enumTypeName(enumName)));
|
|
1812
|
+
blocks.push(renderComparisonExp({ gqlTypeName: enumTypeName(enumName), patternTypes }));
|
|
1674
1813
|
}
|
|
1675
1814
|
if (hasPlatformUser) blocks.push(...renderPlatformUserBlocks());
|
|
1676
1815
|
for (const table of tables) {
|
|
@@ -1724,7 +1863,9 @@ function descriptionLines(text, indent) {
|
|
|
1724
1863
|
const escaped = text.replace(/"""/g, '\\"""');
|
|
1725
1864
|
return [`${indent}"""`, ...escaped.split("\n").map((line) => `${indent}${line}`), `${indent}"""`];
|
|
1726
1865
|
}
|
|
1727
|
-
|
|
1866
|
+
var PATTERN_COMPARISON_TYPES = /* @__PURE__ */ new Set(["String", "Int", "bigint", "uuid"]);
|
|
1867
|
+
var STRING_PATTERN_COMPARISON_TYPES = /* @__PURE__ */ new Set(["String"]);
|
|
1868
|
+
function renderComparisonExp({ gqlTypeName, patternTypes }) {
|
|
1728
1869
|
const fields = [
|
|
1729
1870
|
["_eq", gqlTypeName],
|
|
1730
1871
|
["_neq", gqlTypeName],
|
|
@@ -1736,7 +1877,7 @@ function renderComparisonExp(gqlTypeName) {
|
|
|
1736
1877
|
["_nin", `[${gqlTypeName}!]`],
|
|
1737
1878
|
["_isNull", "Boolean"]
|
|
1738
1879
|
];
|
|
1739
|
-
if (gqlTypeName
|
|
1880
|
+
if (patternTypes.has(gqlTypeName)) {
|
|
1740
1881
|
fields.push(["_like", "String"], ["_ilike", "String"]);
|
|
1741
1882
|
}
|
|
1742
1883
|
if (gqlTypeName === "jsonb") {
|
|
@@ -2235,12 +2376,6 @@ function renderCowMutationFields(table, names) {
|
|
|
2235
2376
|
}
|
|
2236
2377
|
return lines;
|
|
2237
2378
|
}
|
|
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
2379
|
|
|
2245
2380
|
// src/codegen-gql/errors.ts
|
|
2246
2381
|
var CodegenGqlError = class extends Error {
|
|
@@ -2311,7 +2446,7 @@ function normalizeRequires(requires) {
|
|
|
2311
2446
|
|
|
2312
2447
|
// src/codegen-gql/type-policies.ts
|
|
2313
2448
|
function generateTypePolicies(canonical) {
|
|
2314
|
-
const def = normalizeCanonical(canonicalDefinitionSchema.parse(canonical));
|
|
2449
|
+
const def = composeNamespace(normalizeCanonical(canonicalDefinitionSchema.parse(canonical))).definition;
|
|
2315
2450
|
const entries = [];
|
|
2316
2451
|
let hasPlatformUser = false;
|
|
2317
2452
|
for (const table of canonicalRelations(def)) {
|