@sequenceholdings/orm 2.11.0 → 2.11.1
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 -4
- package/dist/authoring.d.cts +1 -1
- package/dist/authoring.d.ts +1 -1
- package/dist/canonical.d.cts +43 -43
- package/dist/canonical.d.ts +43 -43
- package/dist/cli.cjs +147 -195
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +148 -196
- package/dist/cli.js.map +1 -1
- package/dist/client.cjs +5 -10
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +2 -13
- package/dist/client.d.ts +2 -13
- package/dist/client.js +6 -10
- package/dist/client.js.map +1 -1
- package/dist/compiler.cjs +14 -67
- package/dist/compiler.cjs.map +1 -1
- package/dist/compiler.d.cts +6 -17
- package/dist/compiler.d.ts +6 -17
- package/dist/compiler.js +16 -66
- package/dist/compiler.js.map +1 -1
- package/dist/index.cjs +242 -189
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +541 -36
- package/dist/index.d.ts +541 -36
- package/dist/index.js +237 -189
- package/dist/index.js.map +1 -1
- package/dist/ir.cjs +6 -11
- package/dist/ir.cjs.map +1 -1
- package/dist/ir.d.cts +61 -64
- package/dist/ir.d.ts +61 -64
- package/dist/ir.js +6 -11
- package/dist/ir.js.map +1 -1
- package/dist/predicate-v2.cjs +3 -8
- package/dist/predicate-v2.cjs.map +1 -1
- package/dist/predicate-v2.js +3 -8
- package/dist/predicate-v2.js.map +1 -1
- package/dist/sdl.cjs +4 -11
- package/dist/sdl.cjs.map +1 -1
- package/dist/sdl.d.cts +1 -5
- package/dist/sdl.d.ts +1 -5
- package/dist/sdl.js +4 -11
- package/dist/sdl.js.map +1 -1
- package/package.json +1 -1
- package/src/codegen-gql/server-fns.cjs +1 -1
- package/dist/{definition-CevES7lM.d.cts → definition-B99BsOAO.d.cts} +2 -2
- package/dist/{definition-CevES7lM.d.ts → definition-B99BsOAO.d.ts} +2 -2
package/dist/cli.cjs
CHANGED
|
@@ -2293,9 +2293,6 @@ function normalizeCanonical(definition) {
|
|
|
2293
2293
|
return normalized;
|
|
2294
2294
|
}
|
|
2295
2295
|
|
|
2296
|
-
// src/client/sql.ts
|
|
2297
|
-
var BUILTIN_SQL_READ_HASH = "sha256:a50c477c952a5e0fe68ed158a4530e4aab573c09bcbb1a8ac454dc88a39a6258";
|
|
2298
|
-
|
|
2299
2296
|
// src/ir/index.ts
|
|
2300
2297
|
var IR_VERSION = 6;
|
|
2301
2298
|
var LEGACY_IR_VERSION = 1;
|
|
@@ -2624,8 +2621,7 @@ var compiledOperationSchema = zod.z.object({
|
|
|
2624
2621
|
maxRows: zod.z.number().int().min(1).max(1e4)
|
|
2625
2622
|
}).strict().optional(),
|
|
2626
2623
|
irVersion: irVersionSchema,
|
|
2627
|
-
name: zod.z.string(),
|
|
2628
|
-
opHash: zod.z.string().regex(/^sha256:[0-9a-f]{64}$/),
|
|
2624
|
+
name: zod.z.string().regex(/^[_A-Za-z][_0-9A-Za-z]{0,254}$/),
|
|
2629
2625
|
kind: zod.z.enum(["query", "mutation"]),
|
|
2630
2626
|
requires: zod.z.object({
|
|
2631
2627
|
capability: zod.z.string().optional(),
|
|
@@ -2641,7 +2637,7 @@ var compiledOperationSchema = zod.z.object({
|
|
|
2641
2637
|
}
|
|
2642
2638
|
if (operation.language === "sql") {
|
|
2643
2639
|
const validPlan = operation.sqlQuery ? !operation.sql && operation.irVersion === RUNTIME_SQL_IR_VERSION : !!operation.sql && operation.irVersion === SQL_IR_VERSION;
|
|
2644
|
-
const builtin = operation.name === "BuiltinSqlRead" && operation.
|
|
2640
|
+
const builtin = operation.name === "BuiltinSqlRead" && operation.requires === null;
|
|
2645
2641
|
if (!validPlan || operation.kind !== "query" || operation.roots.length !== 0 || !builtin && !operation.requires?.capability) {
|
|
2646
2642
|
ctx.addIssue({ code: "custom", message: "SQL operations require a query-only v4 plan or v5 runtime contract, capability, and no GraphQL roots" });
|
|
2647
2643
|
}
|
|
@@ -2656,7 +2652,7 @@ var compiledOperationSchema = zod.z.object({
|
|
|
2656
2652
|
}
|
|
2657
2653
|
});
|
|
2658
2654
|
var resolvedSourceIrSchema = zod.z.object({
|
|
2659
|
-
name: zod.z.string(),
|
|
2655
|
+
name: zod.z.string().regex(/^[_A-Za-z][_0-9A-Za-z]{0,254}$/),
|
|
2660
2656
|
kind: zod.z.enum(["manual", "etl", "prefetch"]),
|
|
2661
2657
|
/** Logical table key of the backing relation. */
|
|
2662
2658
|
table: zod.z.string(),
|
|
@@ -2770,7 +2766,6 @@ var compiledArtifactSchema = zod.z.object({
|
|
|
2770
2766
|
ownSchemaHash: zod.z.string().optional(),
|
|
2771
2767
|
dependencies: zod.z.record(zod.z.string(), zod.z.string()).optional(),
|
|
2772
2768
|
readPolicies: zod.z.record(zod.z.string(), predIrSchema).optional(),
|
|
2773
|
-
opsHash: zod.z.string(),
|
|
2774
2769
|
/** Apply-observed synced objects without a serving backing; not part of the authored schema hash. */
|
|
2775
2770
|
unbackedTables: zod.z.array(zod.z.string()).optional(),
|
|
2776
2771
|
tables: zod.z.record(zod.z.string(), tableMetaIrSchema),
|
|
@@ -4437,24 +4432,6 @@ function flattenOperation({
|
|
|
4437
4432
|
}) {
|
|
4438
4433
|
return { ...operation, selectionSet: flattenSelectionSet(operation.selectionSet, fragments, []) };
|
|
4439
4434
|
}
|
|
4440
|
-
var COMPILER_MAJOR = 1;
|
|
4441
|
-
var OP_HASH_DOMAIN = "sequence-orm-op\0";
|
|
4442
|
-
var OPS_HASH_DOMAIN = "sequence-orm-opset\0";
|
|
4443
|
-
function canonicalOperationText(definition) {
|
|
4444
|
-
const document = { kind: graphql.Kind.DOCUMENT, definitions: [definition] };
|
|
4445
|
-
return graphql.print(document);
|
|
4446
|
-
}
|
|
4447
|
-
function computeOpHash({
|
|
4448
|
-
definition,
|
|
4449
|
-
schemaHash
|
|
4450
|
-
}) {
|
|
4451
|
-
const digest = crypto.createHash("sha256").update(OP_HASH_DOMAIN).update(`${COMPILER_MAJOR}\0${schemaHash}\0`).update(canonicalOperationText(definition)).digest("hex");
|
|
4452
|
-
return `sha256:${digest}`;
|
|
4453
|
-
}
|
|
4454
|
-
function computeOpsHash(opHashes) {
|
|
4455
|
-
const digest = crypto.createHash("sha256").update(OPS_HASH_DOMAIN).update([...opHashes].sort().join("\n")).digest("hex");
|
|
4456
|
-
return `sha256:${digest}`;
|
|
4457
|
-
}
|
|
4458
4435
|
var SOURCE_DIRECTIVES = /* @__PURE__ */ new Set(["prefetch", "writeback", "localOnly"]);
|
|
4459
4436
|
var fail = (message, code) => {
|
|
4460
4437
|
throw new DocumentCompileError(message, code);
|
|
@@ -5950,7 +5927,6 @@ function compileNamespace({ canonical, sdl, documents }) {
|
|
|
5950
5927
|
operations[restricted.name] = {
|
|
5951
5928
|
irVersion: usesServicePrincipal(roots) ? SERVICE_PRINCIPAL_IR_VERSION : canonical.imports?.length ? COMPOSED_IR_VERSION : roots.some((root) => root.kind === "mutation" && root.assertAffectedRows !== void 0) ? GUARDED_IR_VERSION : LEGACY_IR_VERSION,
|
|
5952
5929
|
name: restricted.name,
|
|
5953
|
-
opHash: computeOpHash({ definition: flattened, schemaHash }),
|
|
5954
5930
|
kind: restricted.kind,
|
|
5955
5931
|
requires: restricted.requires,
|
|
5956
5932
|
variables: restricted.variables,
|
|
@@ -5983,7 +5959,6 @@ function compileNamespace({ canonical, sdl, documents }) {
|
|
|
5983
5959
|
dependencies: Object.fromEntries(canonical.imports.map((owner) => [owner.namespace, computeSchemaHash(localContract(owner))]))
|
|
5984
5960
|
} : {},
|
|
5985
5961
|
readPolicies: Object.fromEntries(ctx.readPolicies),
|
|
5986
|
-
opsHash: computeOpsHash(Object.values(operations).map((op) => op.opHash)),
|
|
5987
5962
|
tables: ctx.tables,
|
|
5988
5963
|
operations
|
|
5989
5964
|
};
|
|
@@ -5991,11 +5966,10 @@ function compileNamespace({ canonical, sdl, documents }) {
|
|
|
5991
5966
|
const manifest = {
|
|
5992
5967
|
namespace: ctx.namespace,
|
|
5993
5968
|
schemaHash,
|
|
5994
|
-
opsHash: normalized.opsHash,
|
|
5995
5969
|
operations: Object.fromEntries(
|
|
5996
5970
|
Object.values(normalized.operations).map((op) => [
|
|
5997
5971
|
op.name,
|
|
5998
|
-
|
|
5972
|
+
op
|
|
5999
5973
|
])
|
|
6000
5974
|
)
|
|
6001
5975
|
};
|
|
@@ -6177,7 +6151,6 @@ function createSqlCatalog({ canonical, publishedObjects, executionTarget }) {
|
|
|
6177
6151
|
}
|
|
6178
6152
|
function createSqlCatalogFromContext({ canonical, publishedObjects, executionTarget, ctx, identity: suppliedIdentity }) {
|
|
6179
6153
|
if (!publishedObjects.length || new Set(publishedObjects).size !== publishedObjects.length) throw new Error("SQL objects must be explicitly declared and unique");
|
|
6180
|
-
const identity = suppliedIdentity ?? sqlHash(`ontology-sql-v1\0${computeSchemaHash(canonical)}\0${executionTarget}`);
|
|
6181
6154
|
const logicalNames = new Map(Object.entries(ctx.tables).map(([key, meta]) => [meta, key]));
|
|
6182
6155
|
const refOf = (meta) => `${meta.namespace ?? canonical.namespace}/${logicalNames.get(meta)}`;
|
|
6183
6156
|
const definitions = [canonical, ...canonical.imports ?? []];
|
|
@@ -6202,7 +6175,7 @@ function createSqlCatalogFromContext({ canonical, publishedObjects, executionTar
|
|
|
6202
6175
|
const scan = `SELECT ${projection} FROM ${quoteIdentifier(meta.schema)}.${quoteIdentifier(meta.table)} AS ${quoteIdentifier("p0")} WHERE ${compileStaticPolicySql({ table: meta, predicate: policy, tables: ctx.tables, namespace: canonical.namespace, alias: "p0", onRead: (target) => reads.add(refOf(target)) })}`;
|
|
6203
6176
|
return { ref, table: meta.table, columns, scan, read: [...reads].sort() };
|
|
6204
6177
|
});
|
|
6205
|
-
return { identity, objects };
|
|
6178
|
+
return { identity: suppliedIdentity ?? sqlHash(JSON.stringify(["ontology-sql-catalog-v2", executionTarget, objects])), objects };
|
|
6206
6179
|
}
|
|
6207
6180
|
|
|
6208
6181
|
// src/sql/ast.ts
|
|
@@ -6730,20 +6703,10 @@ async function compileSqlDocuments({ input, result, sqlDocuments }) {
|
|
|
6730
6703
|
const catalog = createSqlCatalog({ canonical: input.canonical, publishedObjects: read, executionTarget: "registered-operation" });
|
|
6731
6704
|
if ("mode" in definition) {
|
|
6732
6705
|
if (catalog.objects.some((object) => object.read.some((ref) => !read.includes(ref)))) throw new Error("SQL policy accesses an undeclared ontology object");
|
|
6733
|
-
const opHash2 = sqlHash(JSON.stringify([
|
|
6734
|
-
"sequence-runtime-sql-operation-v1",
|
|
6735
|
-
definition.name,
|
|
6736
|
-
definition.namespace,
|
|
6737
|
-
definition.requires.capability,
|
|
6738
|
-
read,
|
|
6739
|
-
catalog.identity,
|
|
6740
|
-
definition.maxRows
|
|
6741
|
-
]));
|
|
6742
6706
|
result.artifact.operations[definition.name] = compiledOperationSchema.parse({
|
|
6743
6707
|
irVersion: RUNTIME_SQL_IR_VERSION,
|
|
6744
6708
|
language: "sql",
|
|
6745
6709
|
name: definition.name,
|
|
6746
|
-
opHash: opHash2,
|
|
6747
6710
|
kind: "query",
|
|
6748
6711
|
requires: definition.requires,
|
|
6749
6712
|
variables: [
|
|
@@ -6754,7 +6717,7 @@ async function compileSqlDocuments({ input, result, sqlDocuments }) {
|
|
|
6754
6717
|
tableSet: read.map((ref) => ref.split("/")[1]).sort(),
|
|
6755
6718
|
sqlQuery: { catalog, read, maxRows: definition.maxRows }
|
|
6756
6719
|
});
|
|
6757
|
-
result.manifest.operations[definition.name] =
|
|
6720
|
+
result.manifest.operations[definition.name] = result.artifact.operations[definition.name];
|
|
6758
6721
|
continue;
|
|
6759
6722
|
}
|
|
6760
6723
|
const names = Object.keys(definition.parameters).sort();
|
|
@@ -6772,20 +6735,10 @@ async function compileSqlDocuments({ input, result, sqlDocuments }) {
|
|
|
6772
6735
|
nullable: !definition.parameters[name2].required,
|
|
6773
6736
|
list: false
|
|
6774
6737
|
}));
|
|
6775
|
-
const opHash = sqlHash(JSON.stringify([
|
|
6776
|
-
"sequence-sql-operation-v1",
|
|
6777
|
-
definition.name,
|
|
6778
|
-
definition.namespace,
|
|
6779
|
-
definition.requires.capability,
|
|
6780
|
-
read,
|
|
6781
|
-
variables,
|
|
6782
|
-
plan.queryHash
|
|
6783
|
-
]));
|
|
6784
6738
|
const operation = compiledOperationSchema.parse({
|
|
6785
6739
|
irVersion: SQL_IR_VERSION,
|
|
6786
6740
|
language: "sql",
|
|
6787
6741
|
name: definition.name,
|
|
6788
|
-
opHash,
|
|
6789
6742
|
kind: "query",
|
|
6790
6743
|
requires: definition.requires,
|
|
6791
6744
|
variables,
|
|
@@ -6794,7 +6747,7 @@ async function compileSqlDocuments({ input, result, sqlDocuments }) {
|
|
|
6794
6747
|
sql: { text: plan.text, columns: plan.columns, parameters: names, read, maxRows: plan.maxRows }
|
|
6795
6748
|
});
|
|
6796
6749
|
result.artifact.operations[definition.name] = operation;
|
|
6797
|
-
result.manifest.operations[definition.name] =
|
|
6750
|
+
result.manifest.operations[definition.name] = result.artifact.operations[definition.name];
|
|
6798
6751
|
} catch (error) {
|
|
6799
6752
|
return { ok: false, diagnostics: [...result.diagnostics, {
|
|
6800
6753
|
severity: "error",
|
|
@@ -6806,8 +6759,6 @@ async function compileSqlDocuments({ input, result, sqlDocuments }) {
|
|
|
6806
6759
|
}
|
|
6807
6760
|
const required = requiredArtifactIrVersion(Object.values(result.artifact.operations));
|
|
6808
6761
|
if (required > result.artifact.irVersion) result.artifact.irVersion = required;
|
|
6809
|
-
result.artifact.opsHash = computeOpsHash(Object.values(result.artifact.operations).map((op) => op.opHash));
|
|
6810
|
-
result.manifest.opsHash = result.artifact.opsHash;
|
|
6811
6762
|
return { ...result, artifact: normalizeIr(result.artifact) };
|
|
6812
6763
|
}
|
|
6813
6764
|
async function managedViewDiagnostics(canonical) {
|
|
@@ -7668,7 +7619,7 @@ var manifestOperationSchema = zod.z.object({
|
|
|
7668
7619
|
requires: manifestRequiresSchema
|
|
7669
7620
|
});
|
|
7670
7621
|
var operationsManifestSchema = zod.z.object({
|
|
7671
|
-
manifestVersion: zod.z.
|
|
7622
|
+
manifestVersion: zod.z.literal(MANIFEST_VERSION),
|
|
7672
7623
|
operations: zod.z.record(zod.z.string().regex(GRAPHQL_NAME_RE), manifestOperationSchema)
|
|
7673
7624
|
});
|
|
7674
7625
|
function buildOperationsManifest({
|
|
@@ -8635,6 +8586,132 @@ function compilePredicate(predicate, columnTypes, options = {}) {
|
|
|
8635
8586
|
return `(${options.statementClaimChecks ? "SELECT " : ""}${capabilityExpression(predicate.key)})`;
|
|
8636
8587
|
}
|
|
8637
8588
|
}
|
|
8589
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
8590
|
+
var DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
8591
|
+
var TIMESTAMPTZ_RE = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:?\d{2})$/;
|
|
8592
|
+
var INTEGER_RE = /^-?\d+$/;
|
|
8593
|
+
var NUMERIC_RE = /^-?\d+(\.\d+)?$/;
|
|
8594
|
+
function sourceSchemaAllowed(schema) {
|
|
8595
|
+
return schema !== "information_schema" && !schema.startsWith("pg_");
|
|
8596
|
+
}
|
|
8597
|
+
function isRelationIdentifier(value) {
|
|
8598
|
+
return value.length <= 63 && IDENTIFIER_PATTERN.test(value);
|
|
8599
|
+
}
|
|
8600
|
+
function isSourceColumn(value) {
|
|
8601
|
+
return value.length <= 63 && COLUMN_IDENTIFIER_PATTERN.test(value);
|
|
8602
|
+
}
|
|
8603
|
+
function splitQualifiedRelation(from) {
|
|
8604
|
+
const dot = from.indexOf(".");
|
|
8605
|
+
if (dot <= 0 || dot !== from.lastIndexOf(".")) return null;
|
|
8606
|
+
const schema = from.slice(0, dot);
|
|
8607
|
+
const table = from.slice(dot + 1);
|
|
8608
|
+
if (!isRelationIdentifier(schema) || !isRelationIdentifier(table)) return null;
|
|
8609
|
+
return { schema, table };
|
|
8610
|
+
}
|
|
8611
|
+
function postgresTypeName(type) {
|
|
8612
|
+
if (type === "double") return "double precision";
|
|
8613
|
+
if (type === "timestamptz") return "timestamp with time zone";
|
|
8614
|
+
return type;
|
|
8615
|
+
}
|
|
8616
|
+
function columnPostgresType(column, schemaName, enums) {
|
|
8617
|
+
if (typeof column.type === "string") return postgresTypeName(column.type);
|
|
8618
|
+
if (!enums.has(column.type.enum)) return null;
|
|
8619
|
+
return `${quoteIdentifier(schemaName)}.${quoteIdentifier(column.type.enum)}`;
|
|
8620
|
+
}
|
|
8621
|
+
function quoteQualified(schema, table) {
|
|
8622
|
+
return `${quoteIdentifier(schema)}.${quoteIdentifier(table)}`;
|
|
8623
|
+
}
|
|
8624
|
+
var INT4_MIN = -2147483648;
|
|
8625
|
+
var INT4_MAX = 2147483647;
|
|
8626
|
+
function resumeLiteralSql({
|
|
8627
|
+
column,
|
|
8628
|
+
after,
|
|
8629
|
+
schemaName,
|
|
8630
|
+
enums
|
|
8631
|
+
}) {
|
|
8632
|
+
const coerced = coerceResumeValue(column, after);
|
|
8633
|
+
if (!coerced.ok) return coerced;
|
|
8634
|
+
return literalSql({ column, value: coerced.value, schemaName, enums });
|
|
8635
|
+
}
|
|
8636
|
+
function coerceResumeValue(column, after) {
|
|
8637
|
+
const type = typeof column.type === "string" ? column.type : null;
|
|
8638
|
+
if (type === "integer") {
|
|
8639
|
+
if (!INTEGER_RE.test(after)) return { ok: false, error: `${column.name}: after must be an integer` };
|
|
8640
|
+
const parsed = Number(after);
|
|
8641
|
+
if (!Number.isSafeInteger(parsed) || parsed < INT4_MIN || parsed > INT4_MAX) {
|
|
8642
|
+
return { ok: false, error: `${column.name}: after must be an integer` };
|
|
8643
|
+
}
|
|
8644
|
+
return { ok: true, value: parsed };
|
|
8645
|
+
}
|
|
8646
|
+
if (type === "boolean") {
|
|
8647
|
+
if (after !== "true" && after !== "false") return { ok: false, error: `${column.name}: after must be true or false` };
|
|
8648
|
+
return { ok: true, value: after === "true" };
|
|
8649
|
+
}
|
|
8650
|
+
return { ok: true, value: after };
|
|
8651
|
+
}
|
|
8652
|
+
function literalSql({
|
|
8653
|
+
column,
|
|
8654
|
+
value,
|
|
8655
|
+
schemaName,
|
|
8656
|
+
enums
|
|
8657
|
+
}) {
|
|
8658
|
+
const label = column.name;
|
|
8659
|
+
if (typeof value === "string" && value.includes("\0")) {
|
|
8660
|
+
return { ok: false, error: `${label}: null default contains a NUL character` };
|
|
8661
|
+
}
|
|
8662
|
+
if (typeof column.type !== "string") {
|
|
8663
|
+
const enumDef = enums.get(column.type.enum);
|
|
8664
|
+
if (!enumDef) return { ok: false, error: `${label}: enum '${column.type.enum}' is not declared` };
|
|
8665
|
+
if (typeof value !== "string" || !enumDef.values.includes(value)) {
|
|
8666
|
+
return { ok: false, error: `${label}: null default must be one of ${enumDef.values.join(", ")}` };
|
|
8667
|
+
}
|
|
8668
|
+
const typeName2 = columnPostgresType(column, schemaName, enums);
|
|
8669
|
+
return { ok: true, sql: `${quoteLiteral(value)}::${typeName2}` };
|
|
8670
|
+
}
|
|
8671
|
+
return scalarLiteral2({ column, type: column.type, value, label });
|
|
8672
|
+
}
|
|
8673
|
+
var SCALAR_LITERALS = {
|
|
8674
|
+
text: (value, label) => typeof value === "string" ? { ok: true, sql: quoteLiteral(value) } : { ok: false, error: `${label}: null default must be a string` },
|
|
8675
|
+
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` },
|
|
8676
|
+
boolean: (value, label) => typeof value === "boolean" ? { ok: true, sql: value ? "TRUE" : "FALSE" } : { ok: false, error: `${label}: null default must be true or false` },
|
|
8677
|
+
integer: (value, label) => typeof value === "number" && Number.isSafeInteger(value) ? { ok: true, sql: String(value) } : { ok: false, error: `${label}: null default must be an integer` },
|
|
8678
|
+
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` },
|
|
8679
|
+
numeric: numericLiteral,
|
|
8680
|
+
double: numericLiteral,
|
|
8681
|
+
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` },
|
|
8682
|
+
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` },
|
|
8683
|
+
jsonb: jsonbLiteral
|
|
8684
|
+
};
|
|
8685
|
+
function numericLiteral(value, label) {
|
|
8686
|
+
if (typeof value === "number" && Number.isFinite(value)) return { ok: true, sql: String(value) };
|
|
8687
|
+
if (typeof value === "string" && NUMERIC_RE.test(value)) return { ok: true, sql: value };
|
|
8688
|
+
return { ok: false, error: `${label}: null default must be a finite number` };
|
|
8689
|
+
}
|
|
8690
|
+
function scalarLiteral2({
|
|
8691
|
+
column,
|
|
8692
|
+
type,
|
|
8693
|
+
value,
|
|
8694
|
+
label
|
|
8695
|
+
}) {
|
|
8696
|
+
const encode = SCALAR_LITERALS[type];
|
|
8697
|
+
if (!encode) return { ok: false, error: `${column.name}: unsupported type '${type}'` };
|
|
8698
|
+
return encode(value, label);
|
|
8699
|
+
}
|
|
8700
|
+
function jsonbLiteral(value, label) {
|
|
8701
|
+
if (typeof value !== "string") return { ok: false, error: `${label}: null default must be a JSON string` };
|
|
8702
|
+
try {
|
|
8703
|
+
JSON.parse(value);
|
|
8704
|
+
} catch {
|
|
8705
|
+
return { ok: false, error: `${label}: null default must be valid JSON` };
|
|
8706
|
+
}
|
|
8707
|
+
return { ok: true, sql: `${quoteLiteral(value)}::jsonb` };
|
|
8708
|
+
}
|
|
8709
|
+
function dollarQuote(body) {
|
|
8710
|
+
const digest = crypto.createHash("sha256").update(body).digest("hex");
|
|
8711
|
+
const candidates = ["seq_orm_import", `seq_orm_${digest.slice(0, 16)}`, `seq_orm_${digest}`];
|
|
8712
|
+
const tag = candidates.find((candidate) => !body.includes(`$${candidate}$`)) ?? `seq_orm_${digest}_body`;
|
|
8713
|
+
return `$${tag}$${body}$${tag}$`;
|
|
8714
|
+
}
|
|
8638
8715
|
|
|
8639
8716
|
// src/engine/security.ts
|
|
8640
8717
|
var CONSUMER_TABLE_PRIVILEGES = ["SELECT", "INSERT", "UPDATE", "DELETE"];
|
|
@@ -9451,11 +9528,13 @@ function applyMigrationHintsV2(previous, definition) {
|
|
|
9451
9528
|
if (column.renamedFrom) {
|
|
9452
9529
|
const previousColumn = snapshotTable.columns[column.renamedFrom];
|
|
9453
9530
|
if (previousColumn && snapshotTable.columns[name2]) {
|
|
9454
|
-
|
|
9455
|
-
|
|
9456
|
-
|
|
9457
|
-
|
|
9458
|
-
|
|
9531
|
+
const reused = table.columns.some((candidate) => candidate.columnName === column.renamedFrom);
|
|
9532
|
+
if (!reused) {
|
|
9533
|
+
throw new OrmDefinitionError(
|
|
9534
|
+
`'${table.table}.${name2}' declares renamedFrom '${column.renamedFrom}', but both columns exist in the previous schema \u2014 a rename cannot overwrite a live column`
|
|
9535
|
+
);
|
|
9536
|
+
}
|
|
9537
|
+
} else if (previousColumn) {
|
|
9459
9538
|
statements.push(
|
|
9460
9539
|
`ALTER TABLE ${qualified(table.table)} RENAME COLUMN ${quoteIdentifier(column.renamedFrom)} TO ${quoteIdentifier(name2)}`
|
|
9461
9540
|
);
|
|
@@ -9548,7 +9627,7 @@ async function planWithViewRecreation({
|
|
|
9548
9627
|
const schema = ormSchemaName(canonical.namespace);
|
|
9549
9628
|
const previous = previousSnapshot ? normalizeSnapshot(previousSnapshot) : emptySnapshot(canonical.namespace);
|
|
9550
9629
|
assertValidViewDependencies(canonical);
|
|
9551
|
-
const hints = applyMigrationHintsV2(previous, canonical);
|
|
9630
|
+
const hints = previousSnapshot === void 0 ? { statements: [], adjusted: previous } : applyMigrationHintsV2(previous, canonical);
|
|
9552
9631
|
const snapshot = generateSnapshotV2(canonical, previousId(previous));
|
|
9553
9632
|
const generatedBaseDdl = await diffStatements(withoutViews(hints.adjusted), withoutViews(snapshot));
|
|
9554
9633
|
const baseDdl = orderForeignKeyAdditions(canonical, generatedBaseDdl);
|
|
@@ -10778,7 +10857,7 @@ var hash = zod.z.string().regex(/^sha256:[0-9a-f]{64}$/);
|
|
|
10778
10857
|
var ormMigrationPayloadSchema = zod.z.object({
|
|
10779
10858
|
canonical_definition: canonicalDefinitionSchema,
|
|
10780
10859
|
documents: zod.z.array(zod.z.object({ path: zod.z.string().min(1).max(2048), contents: zod.z.string().max(1e6) }).strict()).max(5e3),
|
|
10781
|
-
client_manifest: zod.z.object({
|
|
10860
|
+
client_manifest: zod.z.object({ operations: zod.z.record(zod.z.string(), compiledOperationSchema) }).strict(),
|
|
10782
10861
|
sdl: zod.z.string().refine((value) => Buffer.byteLength(value, "utf8") <= MAX_GENERATED_SDL_BYTES, {
|
|
10783
10862
|
message: `sdl exceeds ${MAX_GENERATED_SDL_BYTES} bytes`
|
|
10784
10863
|
}),
|
|
@@ -10877,132 +10956,6 @@ var importSpecSchema = zod.z.object({
|
|
|
10877
10956
|
onConflict: zod.z.enum(IMPORT_CONFLICT_MODES).default("skip"),
|
|
10878
10957
|
batchSize: zod.z.number().int().min(1).max(2e4).default(5e3)
|
|
10879
10958
|
}).strict();
|
|
10880
|
-
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
10881
|
-
var DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
10882
|
-
var TIMESTAMPTZ_RE = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:?\d{2})$/;
|
|
10883
|
-
var INTEGER_RE = /^-?\d+$/;
|
|
10884
|
-
var NUMERIC_RE = /^-?\d+(\.\d+)?$/;
|
|
10885
|
-
function sourceSchemaAllowed(schema) {
|
|
10886
|
-
return schema !== "information_schema" && !schema.startsWith("pg_");
|
|
10887
|
-
}
|
|
10888
|
-
function isRelationIdentifier(value) {
|
|
10889
|
-
return value.length <= 63 && IDENTIFIER_PATTERN.test(value);
|
|
10890
|
-
}
|
|
10891
|
-
function isSourceColumn(value) {
|
|
10892
|
-
return value.length <= 63 && COLUMN_IDENTIFIER_PATTERN.test(value);
|
|
10893
|
-
}
|
|
10894
|
-
function splitQualifiedRelation(from) {
|
|
10895
|
-
const dot = from.indexOf(".");
|
|
10896
|
-
if (dot <= 0 || dot !== from.lastIndexOf(".")) return null;
|
|
10897
|
-
const schema = from.slice(0, dot);
|
|
10898
|
-
const table = from.slice(dot + 1);
|
|
10899
|
-
if (!isRelationIdentifier(schema) || !isRelationIdentifier(table)) return null;
|
|
10900
|
-
return { schema, table };
|
|
10901
|
-
}
|
|
10902
|
-
function postgresTypeName(type) {
|
|
10903
|
-
if (type === "double") return "double precision";
|
|
10904
|
-
if (type === "timestamptz") return "timestamp with time zone";
|
|
10905
|
-
return type;
|
|
10906
|
-
}
|
|
10907
|
-
function columnPostgresType(column, schemaName, enums) {
|
|
10908
|
-
if (typeof column.type === "string") return postgresTypeName(column.type);
|
|
10909
|
-
if (!enums.has(column.type.enum)) return null;
|
|
10910
|
-
return `${quoteIdentifier(schemaName)}.${quoteIdentifier(column.type.enum)}`;
|
|
10911
|
-
}
|
|
10912
|
-
function quoteQualified(schema, table) {
|
|
10913
|
-
return `${quoteIdentifier(schema)}.${quoteIdentifier(table)}`;
|
|
10914
|
-
}
|
|
10915
|
-
var INT4_MIN = -2147483648;
|
|
10916
|
-
var INT4_MAX = 2147483647;
|
|
10917
|
-
function resumeLiteralSql({
|
|
10918
|
-
column,
|
|
10919
|
-
after,
|
|
10920
|
-
schemaName,
|
|
10921
|
-
enums
|
|
10922
|
-
}) {
|
|
10923
|
-
const coerced = coerceResumeValue(column, after);
|
|
10924
|
-
if (!coerced.ok) return coerced;
|
|
10925
|
-
return literalSql({ column, value: coerced.value, schemaName, enums });
|
|
10926
|
-
}
|
|
10927
|
-
function coerceResumeValue(column, after) {
|
|
10928
|
-
const type = typeof column.type === "string" ? column.type : null;
|
|
10929
|
-
if (type === "integer") {
|
|
10930
|
-
if (!INTEGER_RE.test(after)) return { ok: false, error: `${column.name}: after must be an integer` };
|
|
10931
|
-
const parsed = Number(after);
|
|
10932
|
-
if (!Number.isSafeInteger(parsed) || parsed < INT4_MIN || parsed > INT4_MAX) {
|
|
10933
|
-
return { ok: false, error: `${column.name}: after must be an integer` };
|
|
10934
|
-
}
|
|
10935
|
-
return { ok: true, value: parsed };
|
|
10936
|
-
}
|
|
10937
|
-
if (type === "boolean") {
|
|
10938
|
-
if (after !== "true" && after !== "false") return { ok: false, error: `${column.name}: after must be true or false` };
|
|
10939
|
-
return { ok: true, value: after === "true" };
|
|
10940
|
-
}
|
|
10941
|
-
return { ok: true, value: after };
|
|
10942
|
-
}
|
|
10943
|
-
function literalSql({
|
|
10944
|
-
column,
|
|
10945
|
-
value,
|
|
10946
|
-
schemaName,
|
|
10947
|
-
enums
|
|
10948
|
-
}) {
|
|
10949
|
-
const label = column.name;
|
|
10950
|
-
if (typeof value === "string" && value.includes("\0")) {
|
|
10951
|
-
return { ok: false, error: `${label}: null default contains a NUL character` };
|
|
10952
|
-
}
|
|
10953
|
-
if (typeof column.type !== "string") {
|
|
10954
|
-
const enumDef = enums.get(column.type.enum);
|
|
10955
|
-
if (!enumDef) return { ok: false, error: `${label}: enum '${column.type.enum}' is not declared` };
|
|
10956
|
-
if (typeof value !== "string" || !enumDef.values.includes(value)) {
|
|
10957
|
-
return { ok: false, error: `${label}: null default must be one of ${enumDef.values.join(", ")}` };
|
|
10958
|
-
}
|
|
10959
|
-
const typeName2 = columnPostgresType(column, schemaName, enums);
|
|
10960
|
-
return { ok: true, sql: `${quoteLiteral(value)}::${typeName2}` };
|
|
10961
|
-
}
|
|
10962
|
-
return scalarLiteral2({ column, type: column.type, value, label });
|
|
10963
|
-
}
|
|
10964
|
-
var SCALAR_LITERALS = {
|
|
10965
|
-
text: (value, label) => typeof value === "string" ? { ok: true, sql: quoteLiteral(value) } : { ok: false, error: `${label}: null default must be a string` },
|
|
10966
|
-
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` },
|
|
10967
|
-
boolean: (value, label) => typeof value === "boolean" ? { ok: true, sql: value ? "TRUE" : "FALSE" } : { ok: false, error: `${label}: null default must be true or false` },
|
|
10968
|
-
integer: (value, label) => typeof value === "number" && Number.isSafeInteger(value) ? { ok: true, sql: String(value) } : { ok: false, error: `${label}: null default must be an integer` },
|
|
10969
|
-
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` },
|
|
10970
|
-
numeric: numericLiteral,
|
|
10971
|
-
double: numericLiteral,
|
|
10972
|
-
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` },
|
|
10973
|
-
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` },
|
|
10974
|
-
jsonb: jsonbLiteral
|
|
10975
|
-
};
|
|
10976
|
-
function numericLiteral(value, label) {
|
|
10977
|
-
if (typeof value === "number" && Number.isFinite(value)) return { ok: true, sql: String(value) };
|
|
10978
|
-
if (typeof value === "string" && NUMERIC_RE.test(value)) return { ok: true, sql: value };
|
|
10979
|
-
return { ok: false, error: `${label}: null default must be a finite number` };
|
|
10980
|
-
}
|
|
10981
|
-
function scalarLiteral2({
|
|
10982
|
-
column,
|
|
10983
|
-
type,
|
|
10984
|
-
value,
|
|
10985
|
-
label
|
|
10986
|
-
}) {
|
|
10987
|
-
const encode = SCALAR_LITERALS[type];
|
|
10988
|
-
if (!encode) return { ok: false, error: `${column.name}: unsupported type '${type}'` };
|
|
10989
|
-
return encode(value, label);
|
|
10990
|
-
}
|
|
10991
|
-
function jsonbLiteral(value, label) {
|
|
10992
|
-
if (typeof value !== "string") return { ok: false, error: `${label}: null default must be a JSON string` };
|
|
10993
|
-
try {
|
|
10994
|
-
JSON.parse(value);
|
|
10995
|
-
} catch {
|
|
10996
|
-
return { ok: false, error: `${label}: null default must be valid JSON` };
|
|
10997
|
-
}
|
|
10998
|
-
return { ok: true, sql: `${quoteLiteral(value)}::jsonb` };
|
|
10999
|
-
}
|
|
11000
|
-
function dollarQuote(body) {
|
|
11001
|
-
const digest = crypto.createHash("sha256").update(body).digest("hex");
|
|
11002
|
-
const candidates = ["seq_orm_import", `seq_orm_${digest.slice(0, 16)}`, `seq_orm_${digest}`];
|
|
11003
|
-
const tag = candidates.find((candidate) => !body.includes(`$${candidate}$`)) ?? `seq_orm_${digest}_body`;
|
|
11004
|
-
return `$${tag}$${body}$${tag}$`;
|
|
11005
|
-
}
|
|
11006
10959
|
|
|
11007
10960
|
// src/import/script.ts
|
|
11008
10961
|
function renderImportScript({
|
|
@@ -11516,7 +11469,7 @@ var USAGE = `usage:
|
|
|
11516
11469
|
seq-studio orm generate [dir] --migration-export [--check]
|
|
11517
11470
|
export reviewed ORM inputs for a coordinated pipeline migration; --check verifies without writing
|
|
11518
11471
|
seq-studio orm validate [dir] parse + validate definitions and verify committed migrations are in sync
|
|
11519
|
-
seq-studio orm plan [dir] -e <env>
|
|
11472
|
+
seq-studio orm plan [dir] -e <env> preview fresh-schema DDL and compare registry versions (no live migration diff, no writes)
|
|
11520
11473
|
seq-studio orm apply [dir] -e <env> author the migration, register, apply, and refresh the generated outputs (the everyday command)
|
|
11521
11474
|
seq-studio orm apply --dry-run -e <env> rehearse the migration on a copy of the environment's real data, then discard it (no real apply)
|
|
11522
11475
|
seq-studio orm apply --no-create -e <env> apply only if the namespace is already registered (CI guard; never provisions a new namespace)
|
|
@@ -11802,7 +11755,7 @@ async function generateCommand(rest) {
|
|
|
11802
11755
|
canonical_definition: loaded2.canonical,
|
|
11803
11756
|
documents,
|
|
11804
11757
|
sdl,
|
|
11805
|
-
client_manifest: {
|
|
11758
|
+
client_manifest: { operations: manifest2.operations },
|
|
11806
11759
|
schema_snapshot: workspace.tipSnapshot,
|
|
11807
11760
|
...migration ? { migration } : {}
|
|
11808
11761
|
} });
|
|
@@ -12249,8 +12202,7 @@ async function applyV2Command(rest, dir) {
|
|
|
12249
12202
|
canonical_definition: loaded.canonical,
|
|
12250
12203
|
documents,
|
|
12251
12204
|
client_manifest: {
|
|
12252
|
-
|
|
12253
|
-
operations: Object.fromEntries(Object.entries(manifest.operations).map(([name2, op]) => [name2, op.opHash]))
|
|
12205
|
+
operations: manifest.operations
|
|
12254
12206
|
},
|
|
12255
12207
|
sdl,
|
|
12256
12208
|
...workspace.tipSnapshot !== void 0 ? { schema_snapshot: workspace.tipSnapshot } : {},
|
|
@@ -12260,7 +12212,7 @@ async function applyV2Command(rest, dir) {
|
|
|
12260
12212
|
...noCreate ? { no_create: true } : {}
|
|
12261
12213
|
});
|
|
12262
12214
|
console.log(
|
|
12263
|
-
(registered.created ? `registered ${namespace}@${registered.content_hash.slice(0, 12)}` : `already registered ${namespace}@${registered.content_hash.slice(0, 12)}`) + (
|
|
12215
|
+
(registered.created ? `registered ${namespace}@${registered.content_hash.slice(0, 12)}` : `already registered ${namespace}@${registered.content_hash.slice(0, 12)}`) + (migration ? ` with committed migration ${migration.name}` : "")
|
|
12264
12216
|
);
|
|
12265
12217
|
if (dryRun) return dryRunRehearsal({ namespace, versionId: registered.version_id, contentHash: registered.content_hash });
|
|
12266
12218
|
const registry = await fetchRegistryState(namespace, registered.content_hash);
|