@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.js
CHANGED
|
@@ -6,7 +6,7 @@ import { fileURLToPath, pathToFileURL } from 'url';
|
|
|
6
6
|
import { createJiti } from 'jiti';
|
|
7
7
|
import { createHash } from 'crypto';
|
|
8
8
|
import { z } from 'zod';
|
|
9
|
-
import { buildSchema, parse, validate, Kind, valueFromASTUntyped, visit
|
|
9
|
+
import { buildSchema, parse, validate, Kind, valueFromASTUntyped, visit } from 'graphql';
|
|
10
10
|
import { PgParser } from '@supabase/pg-parser';
|
|
11
11
|
import { sql } from 'drizzle-orm';
|
|
12
12
|
import { pgSchema, PgDialect, QueryBuilder, getViewConfig, extractUsedTable, check, foreignKey, uniqueIndex, index, primaryKey, jsonb, date, timestamp, boolean, doublePrecision, numeric, bigint, integer, text as text$1, uuid } from 'drizzle-orm/pg-core';
|
|
@@ -2290,9 +2290,6 @@ function normalizeCanonical(definition) {
|
|
|
2290
2290
|
return normalized;
|
|
2291
2291
|
}
|
|
2292
2292
|
|
|
2293
|
-
// src/client/sql.ts
|
|
2294
|
-
var BUILTIN_SQL_READ_HASH = "sha256:a50c477c952a5e0fe68ed158a4530e4aab573c09bcbb1a8ac454dc88a39a6258";
|
|
2295
|
-
|
|
2296
2293
|
// src/ir/index.ts
|
|
2297
2294
|
var IR_VERSION = 6;
|
|
2298
2295
|
var LEGACY_IR_VERSION = 1;
|
|
@@ -2621,8 +2618,7 @@ var compiledOperationSchema = z.object({
|
|
|
2621
2618
|
maxRows: z.number().int().min(1).max(1e4)
|
|
2622
2619
|
}).strict().optional(),
|
|
2623
2620
|
irVersion: irVersionSchema,
|
|
2624
|
-
name: z.string(),
|
|
2625
|
-
opHash: z.string().regex(/^sha256:[0-9a-f]{64}$/),
|
|
2621
|
+
name: z.string().regex(/^[_A-Za-z][_0-9A-Za-z]{0,254}$/),
|
|
2626
2622
|
kind: z.enum(["query", "mutation"]),
|
|
2627
2623
|
requires: z.object({
|
|
2628
2624
|
capability: z.string().optional(),
|
|
@@ -2638,7 +2634,7 @@ var compiledOperationSchema = z.object({
|
|
|
2638
2634
|
}
|
|
2639
2635
|
if (operation.language === "sql") {
|
|
2640
2636
|
const validPlan = operation.sqlQuery ? !operation.sql && operation.irVersion === RUNTIME_SQL_IR_VERSION : !!operation.sql && operation.irVersion === SQL_IR_VERSION;
|
|
2641
|
-
const builtin = operation.name === "BuiltinSqlRead" && operation.
|
|
2637
|
+
const builtin = operation.name === "BuiltinSqlRead" && operation.requires === null;
|
|
2642
2638
|
if (!validPlan || operation.kind !== "query" || operation.roots.length !== 0 || !builtin && !operation.requires?.capability) {
|
|
2643
2639
|
ctx.addIssue({ code: "custom", message: "SQL operations require a query-only v4 plan or v5 runtime contract, capability, and no GraphQL roots" });
|
|
2644
2640
|
}
|
|
@@ -2653,7 +2649,7 @@ var compiledOperationSchema = z.object({
|
|
|
2653
2649
|
}
|
|
2654
2650
|
});
|
|
2655
2651
|
var resolvedSourceIrSchema = z.object({
|
|
2656
|
-
name: z.string(),
|
|
2652
|
+
name: z.string().regex(/^[_A-Za-z][_0-9A-Za-z]{0,254}$/),
|
|
2657
2653
|
kind: z.enum(["manual", "etl", "prefetch"]),
|
|
2658
2654
|
/** Logical table key of the backing relation. */
|
|
2659
2655
|
table: z.string(),
|
|
@@ -2767,7 +2763,6 @@ var compiledArtifactSchema = z.object({
|
|
|
2767
2763
|
ownSchemaHash: z.string().optional(),
|
|
2768
2764
|
dependencies: z.record(z.string(), z.string()).optional(),
|
|
2769
2765
|
readPolicies: z.record(z.string(), predIrSchema).optional(),
|
|
2770
|
-
opsHash: z.string(),
|
|
2771
2766
|
/** Apply-observed synced objects without a serving backing; not part of the authored schema hash. */
|
|
2772
2767
|
unbackedTables: z.array(z.string()).optional(),
|
|
2773
2768
|
tables: z.record(z.string(), tableMetaIrSchema),
|
|
@@ -4434,24 +4429,6 @@ function flattenOperation({
|
|
|
4434
4429
|
}) {
|
|
4435
4430
|
return { ...operation, selectionSet: flattenSelectionSet(operation.selectionSet, fragments, []) };
|
|
4436
4431
|
}
|
|
4437
|
-
var COMPILER_MAJOR = 1;
|
|
4438
|
-
var OP_HASH_DOMAIN = "sequence-orm-op\0";
|
|
4439
|
-
var OPS_HASH_DOMAIN = "sequence-orm-opset\0";
|
|
4440
|
-
function canonicalOperationText(definition) {
|
|
4441
|
-
const document = { kind: Kind.DOCUMENT, definitions: [definition] };
|
|
4442
|
-
return print(document);
|
|
4443
|
-
}
|
|
4444
|
-
function computeOpHash({
|
|
4445
|
-
definition,
|
|
4446
|
-
schemaHash
|
|
4447
|
-
}) {
|
|
4448
|
-
const digest = createHash("sha256").update(OP_HASH_DOMAIN).update(`${COMPILER_MAJOR}\0${schemaHash}\0`).update(canonicalOperationText(definition)).digest("hex");
|
|
4449
|
-
return `sha256:${digest}`;
|
|
4450
|
-
}
|
|
4451
|
-
function computeOpsHash(opHashes) {
|
|
4452
|
-
const digest = createHash("sha256").update(OPS_HASH_DOMAIN).update([...opHashes].sort().join("\n")).digest("hex");
|
|
4453
|
-
return `sha256:${digest}`;
|
|
4454
|
-
}
|
|
4455
4432
|
var SOURCE_DIRECTIVES = /* @__PURE__ */ new Set(["prefetch", "writeback", "localOnly"]);
|
|
4456
4433
|
var fail = (message, code) => {
|
|
4457
4434
|
throw new DocumentCompileError(message, code);
|
|
@@ -5947,7 +5924,6 @@ function compileNamespace({ canonical, sdl, documents }) {
|
|
|
5947
5924
|
operations[restricted.name] = {
|
|
5948
5925
|
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,
|
|
5949
5926
|
name: restricted.name,
|
|
5950
|
-
opHash: computeOpHash({ definition: flattened, schemaHash }),
|
|
5951
5927
|
kind: restricted.kind,
|
|
5952
5928
|
requires: restricted.requires,
|
|
5953
5929
|
variables: restricted.variables,
|
|
@@ -5980,7 +5956,6 @@ function compileNamespace({ canonical, sdl, documents }) {
|
|
|
5980
5956
|
dependencies: Object.fromEntries(canonical.imports.map((owner) => [owner.namespace, computeSchemaHash(localContract(owner))]))
|
|
5981
5957
|
} : {},
|
|
5982
5958
|
readPolicies: Object.fromEntries(ctx.readPolicies),
|
|
5983
|
-
opsHash: computeOpsHash(Object.values(operations).map((op) => op.opHash)),
|
|
5984
5959
|
tables: ctx.tables,
|
|
5985
5960
|
operations
|
|
5986
5961
|
};
|
|
@@ -5988,11 +5963,10 @@ function compileNamespace({ canonical, sdl, documents }) {
|
|
|
5988
5963
|
const manifest = {
|
|
5989
5964
|
namespace: ctx.namespace,
|
|
5990
5965
|
schemaHash,
|
|
5991
|
-
opsHash: normalized.opsHash,
|
|
5992
5966
|
operations: Object.fromEntries(
|
|
5993
5967
|
Object.values(normalized.operations).map((op) => [
|
|
5994
5968
|
op.name,
|
|
5995
|
-
|
|
5969
|
+
op
|
|
5996
5970
|
])
|
|
5997
5971
|
)
|
|
5998
5972
|
};
|
|
@@ -6174,7 +6148,6 @@ function createSqlCatalog({ canonical, publishedObjects, executionTarget }) {
|
|
|
6174
6148
|
}
|
|
6175
6149
|
function createSqlCatalogFromContext({ canonical, publishedObjects, executionTarget, ctx, identity: suppliedIdentity }) {
|
|
6176
6150
|
if (!publishedObjects.length || new Set(publishedObjects).size !== publishedObjects.length) throw new Error("SQL objects must be explicitly declared and unique");
|
|
6177
|
-
const identity = suppliedIdentity ?? sqlHash(`ontology-sql-v1\0${computeSchemaHash(canonical)}\0${executionTarget}`);
|
|
6178
6151
|
const logicalNames = new Map(Object.entries(ctx.tables).map(([key, meta]) => [meta, key]));
|
|
6179
6152
|
const refOf = (meta) => `${meta.namespace ?? canonical.namespace}/${logicalNames.get(meta)}`;
|
|
6180
6153
|
const definitions = [canonical, ...canonical.imports ?? []];
|
|
@@ -6199,7 +6172,7 @@ function createSqlCatalogFromContext({ canonical, publishedObjects, executionTar
|
|
|
6199
6172
|
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)) })}`;
|
|
6200
6173
|
return { ref, table: meta.table, columns, scan, read: [...reads].sort() };
|
|
6201
6174
|
});
|
|
6202
|
-
return { identity, objects };
|
|
6175
|
+
return { identity: suppliedIdentity ?? sqlHash(JSON.stringify(["ontology-sql-catalog-v2", executionTarget, objects])), objects };
|
|
6203
6176
|
}
|
|
6204
6177
|
|
|
6205
6178
|
// src/sql/ast.ts
|
|
@@ -6727,20 +6700,10 @@ async function compileSqlDocuments({ input, result, sqlDocuments }) {
|
|
|
6727
6700
|
const catalog = createSqlCatalog({ canonical: input.canonical, publishedObjects: read, executionTarget: "registered-operation" });
|
|
6728
6701
|
if ("mode" in definition) {
|
|
6729
6702
|
if (catalog.objects.some((object) => object.read.some((ref) => !read.includes(ref)))) throw new Error("SQL policy accesses an undeclared ontology object");
|
|
6730
|
-
const opHash2 = sqlHash(JSON.stringify([
|
|
6731
|
-
"sequence-runtime-sql-operation-v1",
|
|
6732
|
-
definition.name,
|
|
6733
|
-
definition.namespace,
|
|
6734
|
-
definition.requires.capability,
|
|
6735
|
-
read,
|
|
6736
|
-
catalog.identity,
|
|
6737
|
-
definition.maxRows
|
|
6738
|
-
]));
|
|
6739
6703
|
result.artifact.operations[definition.name] = compiledOperationSchema.parse({
|
|
6740
6704
|
irVersion: RUNTIME_SQL_IR_VERSION,
|
|
6741
6705
|
language: "sql",
|
|
6742
6706
|
name: definition.name,
|
|
6743
|
-
opHash: opHash2,
|
|
6744
6707
|
kind: "query",
|
|
6745
6708
|
requires: definition.requires,
|
|
6746
6709
|
variables: [
|
|
@@ -6751,7 +6714,7 @@ async function compileSqlDocuments({ input, result, sqlDocuments }) {
|
|
|
6751
6714
|
tableSet: read.map((ref) => ref.split("/")[1]).sort(),
|
|
6752
6715
|
sqlQuery: { catalog, read, maxRows: definition.maxRows }
|
|
6753
6716
|
});
|
|
6754
|
-
result.manifest.operations[definition.name] =
|
|
6717
|
+
result.manifest.operations[definition.name] = result.artifact.operations[definition.name];
|
|
6755
6718
|
continue;
|
|
6756
6719
|
}
|
|
6757
6720
|
const names = Object.keys(definition.parameters).sort();
|
|
@@ -6769,20 +6732,10 @@ async function compileSqlDocuments({ input, result, sqlDocuments }) {
|
|
|
6769
6732
|
nullable: !definition.parameters[name2].required,
|
|
6770
6733
|
list: false
|
|
6771
6734
|
}));
|
|
6772
|
-
const opHash = sqlHash(JSON.stringify([
|
|
6773
|
-
"sequence-sql-operation-v1",
|
|
6774
|
-
definition.name,
|
|
6775
|
-
definition.namespace,
|
|
6776
|
-
definition.requires.capability,
|
|
6777
|
-
read,
|
|
6778
|
-
variables,
|
|
6779
|
-
plan.queryHash
|
|
6780
|
-
]));
|
|
6781
6735
|
const operation = compiledOperationSchema.parse({
|
|
6782
6736
|
irVersion: SQL_IR_VERSION,
|
|
6783
6737
|
language: "sql",
|
|
6784
6738
|
name: definition.name,
|
|
6785
|
-
opHash,
|
|
6786
6739
|
kind: "query",
|
|
6787
6740
|
requires: definition.requires,
|
|
6788
6741
|
variables,
|
|
@@ -6791,7 +6744,7 @@ async function compileSqlDocuments({ input, result, sqlDocuments }) {
|
|
|
6791
6744
|
sql: { text: plan.text, columns: plan.columns, parameters: names, read, maxRows: plan.maxRows }
|
|
6792
6745
|
});
|
|
6793
6746
|
result.artifact.operations[definition.name] = operation;
|
|
6794
|
-
result.manifest.operations[definition.name] =
|
|
6747
|
+
result.manifest.operations[definition.name] = result.artifact.operations[definition.name];
|
|
6795
6748
|
} catch (error) {
|
|
6796
6749
|
return { ok: false, diagnostics: [...result.diagnostics, {
|
|
6797
6750
|
severity: "error",
|
|
@@ -6803,8 +6756,6 @@ async function compileSqlDocuments({ input, result, sqlDocuments }) {
|
|
|
6803
6756
|
}
|
|
6804
6757
|
const required = requiredArtifactIrVersion(Object.values(result.artifact.operations));
|
|
6805
6758
|
if (required > result.artifact.irVersion) result.artifact.irVersion = required;
|
|
6806
|
-
result.artifact.opsHash = computeOpsHash(Object.values(result.artifact.operations).map((op) => op.opHash));
|
|
6807
|
-
result.manifest.opsHash = result.artifact.opsHash;
|
|
6808
6759
|
return { ...result, artifact: normalizeIr(result.artifact) };
|
|
6809
6760
|
}
|
|
6810
6761
|
async function managedViewDiagnostics(canonical) {
|
|
@@ -7665,7 +7616,7 @@ var manifestOperationSchema = z.object({
|
|
|
7665
7616
|
requires: manifestRequiresSchema
|
|
7666
7617
|
});
|
|
7667
7618
|
var operationsManifestSchema = z.object({
|
|
7668
|
-
manifestVersion: z.
|
|
7619
|
+
manifestVersion: z.literal(MANIFEST_VERSION),
|
|
7669
7620
|
operations: z.record(z.string().regex(GRAPHQL_NAME_RE), manifestOperationSchema)
|
|
7670
7621
|
});
|
|
7671
7622
|
function buildOperationsManifest({
|
|
@@ -8632,6 +8583,132 @@ function compilePredicate(predicate, columnTypes, options = {}) {
|
|
|
8632
8583
|
return `(${options.statementClaimChecks ? "SELECT " : ""}${capabilityExpression(predicate.key)})`;
|
|
8633
8584
|
}
|
|
8634
8585
|
}
|
|
8586
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
8587
|
+
var DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
8588
|
+
var TIMESTAMPTZ_RE = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:?\d{2})$/;
|
|
8589
|
+
var INTEGER_RE = /^-?\d+$/;
|
|
8590
|
+
var NUMERIC_RE = /^-?\d+(\.\d+)?$/;
|
|
8591
|
+
function sourceSchemaAllowed(schema) {
|
|
8592
|
+
return schema !== "information_schema" && !schema.startsWith("pg_");
|
|
8593
|
+
}
|
|
8594
|
+
function isRelationIdentifier(value) {
|
|
8595
|
+
return value.length <= 63 && IDENTIFIER_PATTERN.test(value);
|
|
8596
|
+
}
|
|
8597
|
+
function isSourceColumn(value) {
|
|
8598
|
+
return value.length <= 63 && COLUMN_IDENTIFIER_PATTERN.test(value);
|
|
8599
|
+
}
|
|
8600
|
+
function splitQualifiedRelation(from) {
|
|
8601
|
+
const dot = from.indexOf(".");
|
|
8602
|
+
if (dot <= 0 || dot !== from.lastIndexOf(".")) return null;
|
|
8603
|
+
const schema = from.slice(0, dot);
|
|
8604
|
+
const table = from.slice(dot + 1);
|
|
8605
|
+
if (!isRelationIdentifier(schema) || !isRelationIdentifier(table)) return null;
|
|
8606
|
+
return { schema, table };
|
|
8607
|
+
}
|
|
8608
|
+
function postgresTypeName(type) {
|
|
8609
|
+
if (type === "double") return "double precision";
|
|
8610
|
+
if (type === "timestamptz") return "timestamp with time zone";
|
|
8611
|
+
return type;
|
|
8612
|
+
}
|
|
8613
|
+
function columnPostgresType(column, schemaName, enums) {
|
|
8614
|
+
if (typeof column.type === "string") return postgresTypeName(column.type);
|
|
8615
|
+
if (!enums.has(column.type.enum)) return null;
|
|
8616
|
+
return `${quoteIdentifier(schemaName)}.${quoteIdentifier(column.type.enum)}`;
|
|
8617
|
+
}
|
|
8618
|
+
function quoteQualified(schema, table) {
|
|
8619
|
+
return `${quoteIdentifier(schema)}.${quoteIdentifier(table)}`;
|
|
8620
|
+
}
|
|
8621
|
+
var INT4_MIN = -2147483648;
|
|
8622
|
+
var INT4_MAX = 2147483647;
|
|
8623
|
+
function resumeLiteralSql({
|
|
8624
|
+
column,
|
|
8625
|
+
after,
|
|
8626
|
+
schemaName,
|
|
8627
|
+
enums
|
|
8628
|
+
}) {
|
|
8629
|
+
const coerced = coerceResumeValue(column, after);
|
|
8630
|
+
if (!coerced.ok) return coerced;
|
|
8631
|
+
return literalSql({ column, value: coerced.value, schemaName, enums });
|
|
8632
|
+
}
|
|
8633
|
+
function coerceResumeValue(column, after) {
|
|
8634
|
+
const type = typeof column.type === "string" ? column.type : null;
|
|
8635
|
+
if (type === "integer") {
|
|
8636
|
+
if (!INTEGER_RE.test(after)) return { ok: false, error: `${column.name}: after must be an integer` };
|
|
8637
|
+
const parsed = Number(after);
|
|
8638
|
+
if (!Number.isSafeInteger(parsed) || parsed < INT4_MIN || parsed > INT4_MAX) {
|
|
8639
|
+
return { ok: false, error: `${column.name}: after must be an integer` };
|
|
8640
|
+
}
|
|
8641
|
+
return { ok: true, value: parsed };
|
|
8642
|
+
}
|
|
8643
|
+
if (type === "boolean") {
|
|
8644
|
+
if (after !== "true" && after !== "false") return { ok: false, error: `${column.name}: after must be true or false` };
|
|
8645
|
+
return { ok: true, value: after === "true" };
|
|
8646
|
+
}
|
|
8647
|
+
return { ok: true, value: after };
|
|
8648
|
+
}
|
|
8649
|
+
function literalSql({
|
|
8650
|
+
column,
|
|
8651
|
+
value,
|
|
8652
|
+
schemaName,
|
|
8653
|
+
enums
|
|
8654
|
+
}) {
|
|
8655
|
+
const label = column.name;
|
|
8656
|
+
if (typeof value === "string" && value.includes("\0")) {
|
|
8657
|
+
return { ok: false, error: `${label}: null default contains a NUL character` };
|
|
8658
|
+
}
|
|
8659
|
+
if (typeof column.type !== "string") {
|
|
8660
|
+
const enumDef = enums.get(column.type.enum);
|
|
8661
|
+
if (!enumDef) return { ok: false, error: `${label}: enum '${column.type.enum}' is not declared` };
|
|
8662
|
+
if (typeof value !== "string" || !enumDef.values.includes(value)) {
|
|
8663
|
+
return { ok: false, error: `${label}: null default must be one of ${enumDef.values.join(", ")}` };
|
|
8664
|
+
}
|
|
8665
|
+
const typeName2 = columnPostgresType(column, schemaName, enums);
|
|
8666
|
+
return { ok: true, sql: `${quoteLiteral(value)}::${typeName2}` };
|
|
8667
|
+
}
|
|
8668
|
+
return scalarLiteral2({ column, type: column.type, value, label });
|
|
8669
|
+
}
|
|
8670
|
+
var SCALAR_LITERALS = {
|
|
8671
|
+
text: (value, label) => typeof value === "string" ? { ok: true, sql: quoteLiteral(value) } : { ok: false, error: `${label}: null default must be a string` },
|
|
8672
|
+
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` },
|
|
8673
|
+
boolean: (value, label) => typeof value === "boolean" ? { ok: true, sql: value ? "TRUE" : "FALSE" } : { ok: false, error: `${label}: null default must be true or false` },
|
|
8674
|
+
integer: (value, label) => typeof value === "number" && Number.isSafeInteger(value) ? { ok: true, sql: String(value) } : { ok: false, error: `${label}: null default must be an integer` },
|
|
8675
|
+
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` },
|
|
8676
|
+
numeric: numericLiteral,
|
|
8677
|
+
double: numericLiteral,
|
|
8678
|
+
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` },
|
|
8679
|
+
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` },
|
|
8680
|
+
jsonb: jsonbLiteral
|
|
8681
|
+
};
|
|
8682
|
+
function numericLiteral(value, label) {
|
|
8683
|
+
if (typeof value === "number" && Number.isFinite(value)) return { ok: true, sql: String(value) };
|
|
8684
|
+
if (typeof value === "string" && NUMERIC_RE.test(value)) return { ok: true, sql: value };
|
|
8685
|
+
return { ok: false, error: `${label}: null default must be a finite number` };
|
|
8686
|
+
}
|
|
8687
|
+
function scalarLiteral2({
|
|
8688
|
+
column,
|
|
8689
|
+
type,
|
|
8690
|
+
value,
|
|
8691
|
+
label
|
|
8692
|
+
}) {
|
|
8693
|
+
const encode = SCALAR_LITERALS[type];
|
|
8694
|
+
if (!encode) return { ok: false, error: `${column.name}: unsupported type '${type}'` };
|
|
8695
|
+
return encode(value, label);
|
|
8696
|
+
}
|
|
8697
|
+
function jsonbLiteral(value, label) {
|
|
8698
|
+
if (typeof value !== "string") return { ok: false, error: `${label}: null default must be a JSON string` };
|
|
8699
|
+
try {
|
|
8700
|
+
JSON.parse(value);
|
|
8701
|
+
} catch {
|
|
8702
|
+
return { ok: false, error: `${label}: null default must be valid JSON` };
|
|
8703
|
+
}
|
|
8704
|
+
return { ok: true, sql: `${quoteLiteral(value)}::jsonb` };
|
|
8705
|
+
}
|
|
8706
|
+
function dollarQuote(body) {
|
|
8707
|
+
const digest = createHash("sha256").update(body).digest("hex");
|
|
8708
|
+
const candidates = ["seq_orm_import", `seq_orm_${digest.slice(0, 16)}`, `seq_orm_${digest}`];
|
|
8709
|
+
const tag = candidates.find((candidate) => !body.includes(`$${candidate}$`)) ?? `seq_orm_${digest}_body`;
|
|
8710
|
+
return `$${tag}$${body}$${tag}$`;
|
|
8711
|
+
}
|
|
8635
8712
|
|
|
8636
8713
|
// src/engine/security.ts
|
|
8637
8714
|
var CONSUMER_TABLE_PRIVILEGES = ["SELECT", "INSERT", "UPDATE", "DELETE"];
|
|
@@ -9448,11 +9525,13 @@ function applyMigrationHintsV2(previous, definition) {
|
|
|
9448
9525
|
if (column.renamedFrom) {
|
|
9449
9526
|
const previousColumn = snapshotTable.columns[column.renamedFrom];
|
|
9450
9527
|
if (previousColumn && snapshotTable.columns[name2]) {
|
|
9451
|
-
|
|
9452
|
-
|
|
9453
|
-
|
|
9454
|
-
|
|
9455
|
-
|
|
9528
|
+
const reused = table.columns.some((candidate) => candidate.columnName === column.renamedFrom);
|
|
9529
|
+
if (!reused) {
|
|
9530
|
+
throw new OrmDefinitionError(
|
|
9531
|
+
`'${table.table}.${name2}' declares renamedFrom '${column.renamedFrom}', but both columns exist in the previous schema \u2014 a rename cannot overwrite a live column`
|
|
9532
|
+
);
|
|
9533
|
+
}
|
|
9534
|
+
} else if (previousColumn) {
|
|
9456
9535
|
statements.push(
|
|
9457
9536
|
`ALTER TABLE ${qualified(table.table)} RENAME COLUMN ${quoteIdentifier(column.renamedFrom)} TO ${quoteIdentifier(name2)}`
|
|
9458
9537
|
);
|
|
@@ -9545,7 +9624,7 @@ async function planWithViewRecreation({
|
|
|
9545
9624
|
const schema = ormSchemaName(canonical.namespace);
|
|
9546
9625
|
const previous = previousSnapshot ? normalizeSnapshot(previousSnapshot) : emptySnapshot(canonical.namespace);
|
|
9547
9626
|
assertValidViewDependencies(canonical);
|
|
9548
|
-
const hints = applyMigrationHintsV2(previous, canonical);
|
|
9627
|
+
const hints = previousSnapshot === void 0 ? { statements: [], adjusted: previous } : applyMigrationHintsV2(previous, canonical);
|
|
9549
9628
|
const snapshot = generateSnapshotV2(canonical, previousId(previous));
|
|
9550
9629
|
const generatedBaseDdl = await diffStatements(withoutViews(hints.adjusted), withoutViews(snapshot));
|
|
9551
9630
|
const baseDdl = orderForeignKeyAdditions(canonical, generatedBaseDdl);
|
|
@@ -10775,7 +10854,7 @@ var hash = z.string().regex(/^sha256:[0-9a-f]{64}$/);
|
|
|
10775
10854
|
var ormMigrationPayloadSchema = z.object({
|
|
10776
10855
|
canonical_definition: canonicalDefinitionSchema,
|
|
10777
10856
|
documents: z.array(z.object({ path: z.string().min(1).max(2048), contents: z.string().max(1e6) }).strict()).max(5e3),
|
|
10778
|
-
client_manifest: z.object({
|
|
10857
|
+
client_manifest: z.object({ operations: z.record(z.string(), compiledOperationSchema) }).strict(),
|
|
10779
10858
|
sdl: z.string().refine((value) => Buffer.byteLength(value, "utf8") <= MAX_GENERATED_SDL_BYTES, {
|
|
10780
10859
|
message: `sdl exceeds ${MAX_GENERATED_SDL_BYTES} bytes`
|
|
10781
10860
|
}),
|
|
@@ -10874,132 +10953,6 @@ var importSpecSchema = z.object({
|
|
|
10874
10953
|
onConflict: z.enum(IMPORT_CONFLICT_MODES).default("skip"),
|
|
10875
10954
|
batchSize: z.number().int().min(1).max(2e4).default(5e3)
|
|
10876
10955
|
}).strict();
|
|
10877
|
-
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
10878
|
-
var DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
10879
|
-
var TIMESTAMPTZ_RE = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:?\d{2})$/;
|
|
10880
|
-
var INTEGER_RE = /^-?\d+$/;
|
|
10881
|
-
var NUMERIC_RE = /^-?\d+(\.\d+)?$/;
|
|
10882
|
-
function sourceSchemaAllowed(schema) {
|
|
10883
|
-
return schema !== "information_schema" && !schema.startsWith("pg_");
|
|
10884
|
-
}
|
|
10885
|
-
function isRelationIdentifier(value) {
|
|
10886
|
-
return value.length <= 63 && IDENTIFIER_PATTERN.test(value);
|
|
10887
|
-
}
|
|
10888
|
-
function isSourceColumn(value) {
|
|
10889
|
-
return value.length <= 63 && COLUMN_IDENTIFIER_PATTERN.test(value);
|
|
10890
|
-
}
|
|
10891
|
-
function splitQualifiedRelation(from) {
|
|
10892
|
-
const dot = from.indexOf(".");
|
|
10893
|
-
if (dot <= 0 || dot !== from.lastIndexOf(".")) return null;
|
|
10894
|
-
const schema = from.slice(0, dot);
|
|
10895
|
-
const table = from.slice(dot + 1);
|
|
10896
|
-
if (!isRelationIdentifier(schema) || !isRelationIdentifier(table)) return null;
|
|
10897
|
-
return { schema, table };
|
|
10898
|
-
}
|
|
10899
|
-
function postgresTypeName(type) {
|
|
10900
|
-
if (type === "double") return "double precision";
|
|
10901
|
-
if (type === "timestamptz") return "timestamp with time zone";
|
|
10902
|
-
return type;
|
|
10903
|
-
}
|
|
10904
|
-
function columnPostgresType(column, schemaName, enums) {
|
|
10905
|
-
if (typeof column.type === "string") return postgresTypeName(column.type);
|
|
10906
|
-
if (!enums.has(column.type.enum)) return null;
|
|
10907
|
-
return `${quoteIdentifier(schemaName)}.${quoteIdentifier(column.type.enum)}`;
|
|
10908
|
-
}
|
|
10909
|
-
function quoteQualified(schema, table) {
|
|
10910
|
-
return `${quoteIdentifier(schema)}.${quoteIdentifier(table)}`;
|
|
10911
|
-
}
|
|
10912
|
-
var INT4_MIN = -2147483648;
|
|
10913
|
-
var INT4_MAX = 2147483647;
|
|
10914
|
-
function resumeLiteralSql({
|
|
10915
|
-
column,
|
|
10916
|
-
after,
|
|
10917
|
-
schemaName,
|
|
10918
|
-
enums
|
|
10919
|
-
}) {
|
|
10920
|
-
const coerced = coerceResumeValue(column, after);
|
|
10921
|
-
if (!coerced.ok) return coerced;
|
|
10922
|
-
return literalSql({ column, value: coerced.value, schemaName, enums });
|
|
10923
|
-
}
|
|
10924
|
-
function coerceResumeValue(column, after) {
|
|
10925
|
-
const type = typeof column.type === "string" ? column.type : null;
|
|
10926
|
-
if (type === "integer") {
|
|
10927
|
-
if (!INTEGER_RE.test(after)) return { ok: false, error: `${column.name}: after must be an integer` };
|
|
10928
|
-
const parsed = Number(after);
|
|
10929
|
-
if (!Number.isSafeInteger(parsed) || parsed < INT4_MIN || parsed > INT4_MAX) {
|
|
10930
|
-
return { ok: false, error: `${column.name}: after must be an integer` };
|
|
10931
|
-
}
|
|
10932
|
-
return { ok: true, value: parsed };
|
|
10933
|
-
}
|
|
10934
|
-
if (type === "boolean") {
|
|
10935
|
-
if (after !== "true" && after !== "false") return { ok: false, error: `${column.name}: after must be true or false` };
|
|
10936
|
-
return { ok: true, value: after === "true" };
|
|
10937
|
-
}
|
|
10938
|
-
return { ok: true, value: after };
|
|
10939
|
-
}
|
|
10940
|
-
function literalSql({
|
|
10941
|
-
column,
|
|
10942
|
-
value,
|
|
10943
|
-
schemaName,
|
|
10944
|
-
enums
|
|
10945
|
-
}) {
|
|
10946
|
-
const label = column.name;
|
|
10947
|
-
if (typeof value === "string" && value.includes("\0")) {
|
|
10948
|
-
return { ok: false, error: `${label}: null default contains a NUL character` };
|
|
10949
|
-
}
|
|
10950
|
-
if (typeof column.type !== "string") {
|
|
10951
|
-
const enumDef = enums.get(column.type.enum);
|
|
10952
|
-
if (!enumDef) return { ok: false, error: `${label}: enum '${column.type.enum}' is not declared` };
|
|
10953
|
-
if (typeof value !== "string" || !enumDef.values.includes(value)) {
|
|
10954
|
-
return { ok: false, error: `${label}: null default must be one of ${enumDef.values.join(", ")}` };
|
|
10955
|
-
}
|
|
10956
|
-
const typeName2 = columnPostgresType(column, schemaName, enums);
|
|
10957
|
-
return { ok: true, sql: `${quoteLiteral(value)}::${typeName2}` };
|
|
10958
|
-
}
|
|
10959
|
-
return scalarLiteral2({ column, type: column.type, value, label });
|
|
10960
|
-
}
|
|
10961
|
-
var SCALAR_LITERALS = {
|
|
10962
|
-
text: (value, label) => typeof value === "string" ? { ok: true, sql: quoteLiteral(value) } : { ok: false, error: `${label}: null default must be a string` },
|
|
10963
|
-
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` },
|
|
10964
|
-
boolean: (value, label) => typeof value === "boolean" ? { ok: true, sql: value ? "TRUE" : "FALSE" } : { ok: false, error: `${label}: null default must be true or false` },
|
|
10965
|
-
integer: (value, label) => typeof value === "number" && Number.isSafeInteger(value) ? { ok: true, sql: String(value) } : { ok: false, error: `${label}: null default must be an integer` },
|
|
10966
|
-
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` },
|
|
10967
|
-
numeric: numericLiteral,
|
|
10968
|
-
double: numericLiteral,
|
|
10969
|
-
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` },
|
|
10970
|
-
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` },
|
|
10971
|
-
jsonb: jsonbLiteral
|
|
10972
|
-
};
|
|
10973
|
-
function numericLiteral(value, label) {
|
|
10974
|
-
if (typeof value === "number" && Number.isFinite(value)) return { ok: true, sql: String(value) };
|
|
10975
|
-
if (typeof value === "string" && NUMERIC_RE.test(value)) return { ok: true, sql: value };
|
|
10976
|
-
return { ok: false, error: `${label}: null default must be a finite number` };
|
|
10977
|
-
}
|
|
10978
|
-
function scalarLiteral2({
|
|
10979
|
-
column,
|
|
10980
|
-
type,
|
|
10981
|
-
value,
|
|
10982
|
-
label
|
|
10983
|
-
}) {
|
|
10984
|
-
const encode = SCALAR_LITERALS[type];
|
|
10985
|
-
if (!encode) return { ok: false, error: `${column.name}: unsupported type '${type}'` };
|
|
10986
|
-
return encode(value, label);
|
|
10987
|
-
}
|
|
10988
|
-
function jsonbLiteral(value, label) {
|
|
10989
|
-
if (typeof value !== "string") return { ok: false, error: `${label}: null default must be a JSON string` };
|
|
10990
|
-
try {
|
|
10991
|
-
JSON.parse(value);
|
|
10992
|
-
} catch {
|
|
10993
|
-
return { ok: false, error: `${label}: null default must be valid JSON` };
|
|
10994
|
-
}
|
|
10995
|
-
return { ok: true, sql: `${quoteLiteral(value)}::jsonb` };
|
|
10996
|
-
}
|
|
10997
|
-
function dollarQuote(body) {
|
|
10998
|
-
const digest = createHash("sha256").update(body).digest("hex");
|
|
10999
|
-
const candidates = ["seq_orm_import", `seq_orm_${digest.slice(0, 16)}`, `seq_orm_${digest}`];
|
|
11000
|
-
const tag = candidates.find((candidate) => !body.includes(`$${candidate}$`)) ?? `seq_orm_${digest}_body`;
|
|
11001
|
-
return `$${tag}$${body}$${tag}$`;
|
|
11002
|
-
}
|
|
11003
10956
|
|
|
11004
10957
|
// src/import/script.ts
|
|
11005
10958
|
function renderImportScript({
|
|
@@ -11513,7 +11466,7 @@ var USAGE = `usage:
|
|
|
11513
11466
|
seq-studio orm generate [dir] --migration-export [--check]
|
|
11514
11467
|
export reviewed ORM inputs for a coordinated pipeline migration; --check verifies without writing
|
|
11515
11468
|
seq-studio orm validate [dir] parse + validate definitions and verify committed migrations are in sync
|
|
11516
|
-
seq-studio orm plan [dir] -e <env>
|
|
11469
|
+
seq-studio orm plan [dir] -e <env> preview fresh-schema DDL and compare registry versions (no live migration diff, no writes)
|
|
11517
11470
|
seq-studio orm apply [dir] -e <env> author the migration, register, apply, and refresh the generated outputs (the everyday command)
|
|
11518
11471
|
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)
|
|
11519
11472
|
seq-studio orm apply --no-create -e <env> apply only if the namespace is already registered (CI guard; never provisions a new namespace)
|
|
@@ -11799,7 +11752,7 @@ async function generateCommand(rest) {
|
|
|
11799
11752
|
canonical_definition: loaded2.canonical,
|
|
11800
11753
|
documents,
|
|
11801
11754
|
sdl,
|
|
11802
|
-
client_manifest: {
|
|
11755
|
+
client_manifest: { operations: manifest2.operations },
|
|
11803
11756
|
schema_snapshot: workspace.tipSnapshot,
|
|
11804
11757
|
...migration ? { migration } : {}
|
|
11805
11758
|
} });
|
|
@@ -12246,8 +12199,7 @@ async function applyV2Command(rest, dir) {
|
|
|
12246
12199
|
canonical_definition: loaded.canonical,
|
|
12247
12200
|
documents,
|
|
12248
12201
|
client_manifest: {
|
|
12249
|
-
|
|
12250
|
-
operations: Object.fromEntries(Object.entries(manifest.operations).map(([name2, op]) => [name2, op.opHash]))
|
|
12202
|
+
operations: manifest.operations
|
|
12251
12203
|
},
|
|
12252
12204
|
sdl,
|
|
12253
12205
|
...workspace.tipSnapshot !== void 0 ? { schema_snapshot: workspace.tipSnapshot } : {},
|
|
@@ -12257,7 +12209,7 @@ async function applyV2Command(rest, dir) {
|
|
|
12257
12209
|
...noCreate ? { no_create: true } : {}
|
|
12258
12210
|
});
|
|
12259
12211
|
console.log(
|
|
12260
|
-
(registered.created ? `registered ${namespace}@${registered.content_hash.slice(0, 12)}` : `already registered ${namespace}@${registered.content_hash.slice(0, 12)}`) + (
|
|
12212
|
+
(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}` : "")
|
|
12261
12213
|
);
|
|
12262
12214
|
if (dryRun) return dryRunRehearsal({ namespace, versionId: registered.version_id, contentHash: registered.content_hash });
|
|
12263
12215
|
const registry = await fetchRegistryState(namespace, registered.content_hash);
|