@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/index.cjs
CHANGED
|
@@ -4967,6 +4967,149 @@ function compileStaticPolicySql({ table, predicate, tables, namespace, alias, ro
|
|
|
4967
4967
|
});
|
|
4968
4968
|
return render(table, predicate, alias, rootRelation);
|
|
4969
4969
|
}
|
|
4970
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
4971
|
+
var DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
4972
|
+
var TIMESTAMPTZ_RE = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:?\d{2})$/;
|
|
4973
|
+
var INTEGER_RE = /^-?\d+$/;
|
|
4974
|
+
var NUMERIC_RE = /^-?\d+(\.\d+)?$/;
|
|
4975
|
+
function sourceSchemaAllowed(schema) {
|
|
4976
|
+
return schema !== "information_schema" && !schema.startsWith("pg_");
|
|
4977
|
+
}
|
|
4978
|
+
function isRelationIdentifier(value) {
|
|
4979
|
+
return value.length <= 63 && IDENTIFIER_PATTERN.test(value);
|
|
4980
|
+
}
|
|
4981
|
+
function isSourceColumn(value) {
|
|
4982
|
+
return value.length <= 63 && COLUMN_IDENTIFIER_PATTERN.test(value);
|
|
4983
|
+
}
|
|
4984
|
+
function splitQualifiedRelation(from) {
|
|
4985
|
+
const dot = from.indexOf(".");
|
|
4986
|
+
if (dot <= 0 || dot !== from.lastIndexOf(".")) return null;
|
|
4987
|
+
const schema = from.slice(0, dot);
|
|
4988
|
+
const table = from.slice(dot + 1);
|
|
4989
|
+
if (!isRelationIdentifier(schema) || !isRelationIdentifier(table)) return null;
|
|
4990
|
+
return { schema, table };
|
|
4991
|
+
}
|
|
4992
|
+
function postgresTypeName(type) {
|
|
4993
|
+
if (type === "double") return "double precision";
|
|
4994
|
+
if (type === "timestamptz") return "timestamp with time zone";
|
|
4995
|
+
return type;
|
|
4996
|
+
}
|
|
4997
|
+
function columnPostgresType(column, schemaName, enums) {
|
|
4998
|
+
if (typeof column.type === "string") return postgresTypeName(column.type);
|
|
4999
|
+
if (!enums.has(column.type.enum)) return null;
|
|
5000
|
+
return `${quoteIdentifier(schemaName)}.${quoteIdentifier(column.type.enum)}`;
|
|
5001
|
+
}
|
|
5002
|
+
function quoteQualified(schema, table) {
|
|
5003
|
+
return `${quoteIdentifier(schema)}.${quoteIdentifier(table)}`;
|
|
5004
|
+
}
|
|
5005
|
+
var INT4_MIN = -2147483648;
|
|
5006
|
+
var INT4_MAX = 2147483647;
|
|
5007
|
+
function resumeLiteralSql({
|
|
5008
|
+
column,
|
|
5009
|
+
after,
|
|
5010
|
+
schemaName,
|
|
5011
|
+
enums
|
|
5012
|
+
}) {
|
|
5013
|
+
const coerced = coerceResumeValue(column, after);
|
|
5014
|
+
if (!coerced.ok) return coerced;
|
|
5015
|
+
return literalSql({ column, value: coerced.value, schemaName, enums });
|
|
5016
|
+
}
|
|
5017
|
+
function coerceResumeValue(column, after) {
|
|
5018
|
+
const type = typeof column.type === "string" ? column.type : null;
|
|
5019
|
+
if (type === "integer") {
|
|
5020
|
+
if (!INTEGER_RE.test(after)) return { ok: false, error: `${column.name}: after must be an integer` };
|
|
5021
|
+
const parsed = Number(after);
|
|
5022
|
+
if (!Number.isSafeInteger(parsed) || parsed < INT4_MIN || parsed > INT4_MAX) {
|
|
5023
|
+
return { ok: false, error: `${column.name}: after must be an integer` };
|
|
5024
|
+
}
|
|
5025
|
+
return { ok: true, value: parsed };
|
|
5026
|
+
}
|
|
5027
|
+
if (type === "boolean") {
|
|
5028
|
+
if (after !== "true" && after !== "false") return { ok: false, error: `${column.name}: after must be true or false` };
|
|
5029
|
+
return { ok: true, value: after === "true" };
|
|
5030
|
+
}
|
|
5031
|
+
return { ok: true, value: after };
|
|
5032
|
+
}
|
|
5033
|
+
function literalSql({
|
|
5034
|
+
column,
|
|
5035
|
+
value,
|
|
5036
|
+
schemaName,
|
|
5037
|
+
enums
|
|
5038
|
+
}) {
|
|
5039
|
+
const label = column.name;
|
|
5040
|
+
if (typeof value === "string" && value.includes("\0")) {
|
|
5041
|
+
return { ok: false, error: `${label}: null default contains a NUL character` };
|
|
5042
|
+
}
|
|
5043
|
+
if (typeof column.type !== "string") {
|
|
5044
|
+
const enumDef = enums.get(column.type.enum);
|
|
5045
|
+
if (!enumDef) return { ok: false, error: `${label}: enum '${column.type.enum}' is not declared` };
|
|
5046
|
+
if (typeof value !== "string" || !enumDef.values.includes(value)) {
|
|
5047
|
+
return { ok: false, error: `${label}: null default must be one of ${enumDef.values.join(", ")}` };
|
|
5048
|
+
}
|
|
5049
|
+
const typeName = columnPostgresType(column, schemaName, enums);
|
|
5050
|
+
return { ok: true, sql: `${quoteLiteral(value)}::${typeName}` };
|
|
5051
|
+
}
|
|
5052
|
+
return scalarLiteral({ column, type: column.type, value, label });
|
|
5053
|
+
}
|
|
5054
|
+
var SCALAR_LITERALS = {
|
|
5055
|
+
text: (value, label) => typeof value === "string" ? { ok: true, sql: quoteLiteral(value) } : { ok: false, error: `${label}: null default must be a string` },
|
|
5056
|
+
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` },
|
|
5057
|
+
boolean: (value, label) => typeof value === "boolean" ? { ok: true, sql: value ? "TRUE" : "FALSE" } : { ok: false, error: `${label}: null default must be true or false` },
|
|
5058
|
+
integer: (value, label) => typeof value === "number" && Number.isSafeInteger(value) ? { ok: true, sql: String(value) } : { ok: false, error: `${label}: null default must be an integer` },
|
|
5059
|
+
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` },
|
|
5060
|
+
numeric: numericLiteral,
|
|
5061
|
+
double: numericLiteral,
|
|
5062
|
+
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` },
|
|
5063
|
+
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` },
|
|
5064
|
+
jsonb: jsonbLiteral
|
|
5065
|
+
};
|
|
5066
|
+
function numericLiteral(value, label) {
|
|
5067
|
+
if (typeof value === "number" && Number.isFinite(value)) return { ok: true, sql: String(value) };
|
|
5068
|
+
if (typeof value === "string" && NUMERIC_RE.test(value)) return { ok: true, sql: value };
|
|
5069
|
+
return { ok: false, error: `${label}: null default must be a finite number` };
|
|
5070
|
+
}
|
|
5071
|
+
function scalarLiteral({
|
|
5072
|
+
column,
|
|
5073
|
+
type,
|
|
5074
|
+
value,
|
|
5075
|
+
label
|
|
5076
|
+
}) {
|
|
5077
|
+
const encode = SCALAR_LITERALS[type];
|
|
5078
|
+
if (!encode) return { ok: false, error: `${column.name}: unsupported type '${type}'` };
|
|
5079
|
+
return encode(value, label);
|
|
5080
|
+
}
|
|
5081
|
+
function jsonbLiteral(value, label) {
|
|
5082
|
+
if (typeof value !== "string") return { ok: false, error: `${label}: null default must be a JSON string` };
|
|
5083
|
+
try {
|
|
5084
|
+
JSON.parse(value);
|
|
5085
|
+
} catch {
|
|
5086
|
+
return { ok: false, error: `${label}: null default must be valid JSON` };
|
|
5087
|
+
}
|
|
5088
|
+
return { ok: true, sql: `${quoteLiteral(value)}::jsonb` };
|
|
5089
|
+
}
|
|
5090
|
+
function dollarQuote(body) {
|
|
5091
|
+
const digest = crypto.createHash("sha256").update(body).digest("hex");
|
|
5092
|
+
const candidates = ["seq_orm_import", `seq_orm_${digest.slice(0, 16)}`, `seq_orm_${digest}`];
|
|
5093
|
+
const tag = candidates.find((candidate) => !body.includes(`$${candidate}$`)) ?? `seq_orm_${digest}_body`;
|
|
5094
|
+
return `$${tag}$${body}$${tag}$`;
|
|
5095
|
+
}
|
|
5096
|
+
|
|
5097
|
+
// src/engine/synced-backing-absent.ts
|
|
5098
|
+
var SYNCED_BACKING_ABSENT_FUNCTION = "orm_synced_backing_absent";
|
|
5099
|
+
var SYNCED_BACKING_ABSENT_SQLSTATE = "55000";
|
|
5100
|
+
var REASON = "is disabled in this environment: its synced pipeline is not deployed here";
|
|
5101
|
+
var SYNCED_BACKING_ABSENT_RAISE = `RAISE EXCEPTION 'ORM object % ${REASON}', object
|
|
5102
|
+
USING ERRCODE = '${SYNCED_BACKING_ABSENT_SQLSTATE}';`;
|
|
5103
|
+
var RAISED = new RegExp(`^ORM object ([a-z][a-z0-9_]*\\.[a-z][a-z0-9_]*) ${REASON}`);
|
|
5104
|
+
function disabledSyncedObjectFromError(error) {
|
|
5105
|
+
if (error === null || typeof error !== "object") return null;
|
|
5106
|
+
const { code, message } = error;
|
|
5107
|
+
if (code !== SYNCED_BACKING_ABSENT_SQLSTATE || typeof message !== "string") return null;
|
|
5108
|
+
return RAISED.exec(message)?.[1] ?? null;
|
|
5109
|
+
}
|
|
5110
|
+
function disabledSyncedObjectMessage(object) {
|
|
5111
|
+
return `${object} ${REASON}`;
|
|
5112
|
+
}
|
|
4970
5113
|
|
|
4971
5114
|
// src/engine/security.ts
|
|
4972
5115
|
var CONSUMER_TABLE_PRIVILEGES = ["SELECT", "INSERT", "UPDATE", "DELETE"];
|
|
@@ -5143,6 +5286,42 @@ function splitPhysicalRelation(physicalRelation) {
|
|
|
5143
5286
|
`synced view physical relation must be "table" or "schema.table" (got "${physicalRelation}")`
|
|
5144
5287
|
);
|
|
5145
5288
|
}
|
|
5289
|
+
function syncedViewUnbackedStatements({
|
|
5290
|
+
definition,
|
|
5291
|
+
tables,
|
|
5292
|
+
columnTypesByTable
|
|
5293
|
+
}) {
|
|
5294
|
+
if (tables.length === 0) return [];
|
|
5295
|
+
const schema = quoteIdentifier(ormSchemaName(definition.namespace));
|
|
5296
|
+
const role = quoteIdentifier(consumerRoleName(definition.namespace));
|
|
5297
|
+
const guard = `${schema}.${quoteIdentifier(SYNCED_BACKING_ABSENT_FUNCTION)}`;
|
|
5298
|
+
const wanted = new Set(tables);
|
|
5299
|
+
const statements = [
|
|
5300
|
+
`CREATE OR REPLACE FUNCTION ${guard}(object text, typed anyelement) RETURNS anyelement LANGUAGE plpgsql VOLATILE AS ${quoteLiteral(`BEGIN
|
|
5301
|
+
${SYNCED_BACKING_ABSENT_RAISE}
|
|
5302
|
+
END`)}`
|
|
5303
|
+
];
|
|
5304
|
+
for (const table of syncedTables(definition)) {
|
|
5305
|
+
if (!wanted.has(table.table)) continue;
|
|
5306
|
+
const columns = Object.entries(table.columns ?? {});
|
|
5307
|
+
if (columns.length === 0) {
|
|
5308
|
+
throw new OrmDefinitionError(`synced table "${table.table}" needs declared columns to be disabled while its backing is absent`);
|
|
5309
|
+
}
|
|
5310
|
+
const object = quoteLiteral(`${definition.namespace}.${table.table}`);
|
|
5311
|
+
const canonicalTypes = columnTypesByTable?.get(table.table);
|
|
5312
|
+
const projection = columns.map(([name2, column]) => {
|
|
5313
|
+
const declared = canonicalTypes?.[name2];
|
|
5314
|
+
const sqlType = typeof declared === "object" ? `${schema}.${quoteIdentifier(declared.enum)}` : postgresTypeName(column.type);
|
|
5315
|
+
return `${guard}(${object}, NULL::${sqlType}) AS ${quoteIdentifier(name2)}`;
|
|
5316
|
+
}).join(", ");
|
|
5317
|
+
const viewName = `${schema}.${quoteIdentifier(table.table)}`;
|
|
5318
|
+
statements.push(
|
|
5319
|
+
`CREATE OR REPLACE VIEW ${viewName} AS SELECT ${projection} WHERE ${guard}(${object}, true)`,
|
|
5320
|
+
`GRANT SELECT ON ${viewName} TO ${role}`
|
|
5321
|
+
);
|
|
5322
|
+
}
|
|
5323
|
+
return statements;
|
|
5324
|
+
}
|
|
5146
5325
|
function syncedViewDropStatements({
|
|
5147
5326
|
schemaName,
|
|
5148
5327
|
tables
|
|
@@ -6225,11 +6404,13 @@ function applyMigrationHintsV2(previous, definition) {
|
|
|
6225
6404
|
if (column.renamedFrom) {
|
|
6226
6405
|
const previousColumn = snapshotTable.columns[column.renamedFrom];
|
|
6227
6406
|
if (previousColumn && snapshotTable.columns[name2]) {
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6407
|
+
const reused = table.columns.some((candidate) => candidate.columnName === column.renamedFrom);
|
|
6408
|
+
if (!reused) {
|
|
6409
|
+
throw new OrmDefinitionError(
|
|
6410
|
+
`'${table.table}.${name2}' declares renamedFrom '${column.renamedFrom}', but both columns exist in the previous schema \u2014 a rename cannot overwrite a live column`
|
|
6411
|
+
);
|
|
6412
|
+
}
|
|
6413
|
+
} else if (previousColumn) {
|
|
6233
6414
|
statements.push(
|
|
6234
6415
|
`ALTER TABLE ${qualified2(table.table)} RENAME COLUMN ${quoteIdentifier(column.renamedFrom)} TO ${quoteIdentifier(name2)}`
|
|
6235
6416
|
);
|
|
@@ -6322,7 +6503,7 @@ async function planWithViewRecreation({
|
|
|
6322
6503
|
const schema = ormSchemaName(canonical.namespace);
|
|
6323
6504
|
const previous = previousSnapshot ? normalizeSnapshot(previousSnapshot) : emptySnapshot(canonical.namespace);
|
|
6324
6505
|
assertValidViewDependencies(canonical);
|
|
6325
|
-
const hints = applyMigrationHintsV2(previous, canonical);
|
|
6506
|
+
const hints = previousSnapshot === void 0 ? { statements: [], adjusted: previous } : applyMigrationHintsV2(previous, canonical);
|
|
6326
6507
|
const snapshot = generateSnapshotV2(canonical, previousId(previous));
|
|
6327
6508
|
const generatedBaseDdl = await diffStatements(withoutViews(hints.adjusted), withoutViews(snapshot));
|
|
6328
6509
|
const baseDdl = orderForeignKeyAdditions(canonical, generatedBaseDdl);
|
|
@@ -7074,52 +7255,6 @@ async function planMigration({
|
|
|
7074
7255
|
}
|
|
7075
7256
|
var compileNamespace = (definition) => planMigration({ definition });
|
|
7076
7257
|
var previousId2 = (snapshot) => snapshot.id;
|
|
7077
|
-
var ORM_MIGRATION_EXPORT_FILE = "orm.migration.json";
|
|
7078
|
-
var ORM_MIGRATION_EXPORT_MAX_BYTES = ORM_REGISTRATION_MAX_BYTES;
|
|
7079
|
-
var hash = zod.z.string().regex(/^sha256:[0-9a-f]{64}$/);
|
|
7080
|
-
var ormMigrationPayloadSchema = zod.z.object({
|
|
7081
|
-
canonical_definition: canonicalDefinitionSchema,
|
|
7082
|
-
documents: zod.z.array(zod.z.object({ path: zod.z.string().min(1).max(2048), contents: zod.z.string().max(1e6) }).strict()).max(5e3),
|
|
7083
|
-
client_manifest: zod.z.object({ ops_hash: hash, operations: zod.z.record(zod.z.string(), hash) }).strict(),
|
|
7084
|
-
sdl: zod.z.string().refine((value) => Buffer.byteLength(value, "utf8") <= MAX_GENERATED_SDL_BYTES, {
|
|
7085
|
-
message: `sdl exceeds ${MAX_GENERATED_SDL_BYTES} bytes`
|
|
7086
|
-
}),
|
|
7087
|
-
schema_snapshot: zod.z.json(),
|
|
7088
|
-
// The existing ORM committed-migration validator and replay engine remain
|
|
7089
|
-
// authoritative. This envelope hashes the provenance, never authorizes SQL.
|
|
7090
|
-
migration: zod.z.json().optional()
|
|
7091
|
-
}).strict();
|
|
7092
|
-
var ormMigrationExportSchema = zod.z.object({
|
|
7093
|
-
schema_version: zod.z.literal(1),
|
|
7094
|
-
schema_hash: hash,
|
|
7095
|
-
payload: ormMigrationPayloadSchema,
|
|
7096
|
-
checksum: zod.z.string().regex(/^[0-9a-f]{64}$/)
|
|
7097
|
-
}).strict();
|
|
7098
|
-
function checksum(value) {
|
|
7099
|
-
return crypto.createHash("sha256").update(stableJson(value)).digest("hex");
|
|
7100
|
-
}
|
|
7101
|
-
function createOrmMigrationExport({ schemaHash, payload }) {
|
|
7102
|
-
const contents = { schema_version: 1, schema_hash: hash.parse(schemaHash), payload: ormMigrationPayloadSchema.parse(payload) };
|
|
7103
|
-
return { ...contents, checksum: checksum(contents) };
|
|
7104
|
-
}
|
|
7105
|
-
function parseOrmMigrationExport(text4) {
|
|
7106
|
-
if (Buffer.byteLength(text4, "utf8") > ORM_MIGRATION_EXPORT_MAX_BYTES) throw new Error("ORM migration export exceeds the size limit");
|
|
7107
|
-
const exported = ormMigrationExportSchema.parse(JSON.parse(text4));
|
|
7108
|
-
const { checksum: expected, ...contents } = exported;
|
|
7109
|
-
if (checksum(contents) !== expected) throw new Error("ORM migration export checksum mismatch; regenerate and commit it");
|
|
7110
|
-
return exported;
|
|
7111
|
-
}
|
|
7112
|
-
function renderOrmMigrationExport(exported) {
|
|
7113
|
-
const text4 = `${JSON.stringify(exported, null, 2)}
|
|
7114
|
-
`;
|
|
7115
|
-
if (Buffer.byteLength(text4, "utf8") > ORM_MIGRATION_EXPORT_MAX_BYTES) throw new Error("ORM migration export exceeds the size limit");
|
|
7116
|
-
return text4;
|
|
7117
|
-
}
|
|
7118
|
-
|
|
7119
|
-
// src/client/sql.ts
|
|
7120
|
-
var BUILTIN_SQL_READ_HASH = "sha256:a50c477c952a5e0fe68ed158a4530e4aab573c09bcbb1a8ac454dc88a39a6258";
|
|
7121
|
-
|
|
7122
|
-
// src/ir/index.ts
|
|
7123
7258
|
var IR_VERSION = 6;
|
|
7124
7259
|
var LEGACY_IR_VERSION = 1;
|
|
7125
7260
|
var GUARDED_IR_VERSION = 2;
|
|
@@ -7155,9 +7290,9 @@ var EXTERNAL_POLICY_CLAIM_KEYS = ["ext_subject", "ext_email"];
|
|
|
7155
7290
|
function isExternalPolicyClaimKey(key) {
|
|
7156
7291
|
return EXTERNAL_POLICY_CLAIM_KEYS.includes(key);
|
|
7157
7292
|
}
|
|
7158
|
-
var
|
|
7293
|
+
var scalarLiteral2 = zod.z.union([zod.z.string(), zod.z.number(), zod.z.boolean(), zod.z.null()]);
|
|
7159
7294
|
var valueIrSchema = zod.z.discriminatedUnion("kind", [
|
|
7160
|
-
zod.z.object({ kind: zod.z.literal("literal"), value: zod.z.union([
|
|
7295
|
+
zod.z.object({ kind: zod.z.literal("literal"), value: zod.z.union([scalarLiteral2, zod.z.array(scalarLiteral2)]) }),
|
|
7161
7296
|
zod.z.object({ kind: zod.z.literal("variable"), name: zod.z.string() }),
|
|
7162
7297
|
zod.z.object({ kind: zod.z.literal("claim"), key: zod.z.enum(["sub", "org", ...EXTERNAL_POLICY_CLAIM_KEYS]) })
|
|
7163
7298
|
]);
|
|
@@ -7404,7 +7539,7 @@ var INPUT_REF_KINDS = [
|
|
|
7404
7539
|
"onConflict"
|
|
7405
7540
|
];
|
|
7406
7541
|
var variableDefaultIrSchema = zod.z.object({
|
|
7407
|
-
value: zod.z.union([
|
|
7542
|
+
value: zod.z.union([scalarLiteral2, zod.z.array(scalarLiteral2)])
|
|
7408
7543
|
});
|
|
7409
7544
|
var variableIrSchema = zod.z.object({
|
|
7410
7545
|
name: zod.z.string(),
|
|
@@ -7447,8 +7582,7 @@ var compiledOperationSchema = zod.z.object({
|
|
|
7447
7582
|
maxRows: zod.z.number().int().min(1).max(1e4)
|
|
7448
7583
|
}).strict().optional(),
|
|
7449
7584
|
irVersion: irVersionSchema,
|
|
7450
|
-
name: zod.z.string(),
|
|
7451
|
-
opHash: zod.z.string().regex(/^sha256:[0-9a-f]{64}$/),
|
|
7585
|
+
name: zod.z.string().regex(/^[_A-Za-z][_0-9A-Za-z]{0,254}$/),
|
|
7452
7586
|
kind: zod.z.enum(["query", "mutation"]),
|
|
7453
7587
|
requires: zod.z.object({
|
|
7454
7588
|
capability: zod.z.string().optional(),
|
|
@@ -7464,7 +7598,7 @@ var compiledOperationSchema = zod.z.object({
|
|
|
7464
7598
|
}
|
|
7465
7599
|
if (operation.language === "sql") {
|
|
7466
7600
|
const validPlan = operation.sqlQuery ? !operation.sql && operation.irVersion === RUNTIME_SQL_IR_VERSION : !!operation.sql && operation.irVersion === SQL_IR_VERSION;
|
|
7467
|
-
const builtin = operation.name === "BuiltinSqlRead" && operation.
|
|
7601
|
+
const builtin = operation.name === "BuiltinSqlRead" && operation.requires === null;
|
|
7468
7602
|
if (!validPlan || operation.kind !== "query" || operation.roots.length !== 0 || !builtin && !operation.requires?.capability) {
|
|
7469
7603
|
ctx.addIssue({ code: "custom", message: "SQL operations require a query-only v4 plan or v5 runtime contract, capability, and no GraphQL roots" });
|
|
7470
7604
|
}
|
|
@@ -7479,7 +7613,7 @@ var compiledOperationSchema = zod.z.object({
|
|
|
7479
7613
|
}
|
|
7480
7614
|
});
|
|
7481
7615
|
var resolvedSourceIrSchema = zod.z.object({
|
|
7482
|
-
name: zod.z.string(),
|
|
7616
|
+
name: zod.z.string().regex(/^[_A-Za-z][_0-9A-Za-z]{0,254}$/),
|
|
7483
7617
|
kind: zod.z.enum(["manual", "etl", "prefetch"]),
|
|
7484
7618
|
/** Logical table key of the backing relation. */
|
|
7485
7619
|
table: zod.z.string(),
|
|
@@ -7593,7 +7727,6 @@ var compiledArtifactSchema = zod.z.object({
|
|
|
7593
7727
|
ownSchemaHash: zod.z.string().optional(),
|
|
7594
7728
|
dependencies: zod.z.record(zod.z.string(), zod.z.string()).optional(),
|
|
7595
7729
|
readPolicies: zod.z.record(zod.z.string(), predIrSchema).optional(),
|
|
7596
|
-
opsHash: zod.z.string(),
|
|
7597
7730
|
/** Apply-observed synced objects without a serving backing; not part of the authored schema hash. */
|
|
7598
7731
|
unbackedTables: zod.z.array(zod.z.string()).optional(),
|
|
7599
7732
|
tables: zod.z.record(zod.z.string(), tableMetaIrSchema),
|
|
@@ -7623,11 +7756,52 @@ function normalizeIr(raw) {
|
|
|
7623
7756
|
if (!irVersionSchema.safeParse(version).success) throw new IrVersionError(version);
|
|
7624
7757
|
return compiledArtifactSchema.parse(raw);
|
|
7625
7758
|
}
|
|
7626
|
-
function
|
|
7759
|
+
function indexByName(artifact) {
|
|
7627
7760
|
const map = /* @__PURE__ */ new Map();
|
|
7628
|
-
for (const op of Object.values(artifact.operations)) map.set(op.
|
|
7761
|
+
for (const op of Object.values(artifact.operations)) map.set(op.name, op);
|
|
7629
7762
|
return map;
|
|
7630
7763
|
}
|
|
7764
|
+
var ORM_MIGRATION_EXPORT_FILE = "orm.migration.json";
|
|
7765
|
+
var ORM_MIGRATION_EXPORT_MAX_BYTES = ORM_REGISTRATION_MAX_BYTES;
|
|
7766
|
+
var hash = zod.z.string().regex(/^sha256:[0-9a-f]{64}$/);
|
|
7767
|
+
var ormMigrationPayloadSchema = zod.z.object({
|
|
7768
|
+
canonical_definition: canonicalDefinitionSchema,
|
|
7769
|
+
documents: zod.z.array(zod.z.object({ path: zod.z.string().min(1).max(2048), contents: zod.z.string().max(1e6) }).strict()).max(5e3),
|
|
7770
|
+
client_manifest: zod.z.object({ operations: zod.z.record(zod.z.string(), compiledOperationSchema) }).strict(),
|
|
7771
|
+
sdl: zod.z.string().refine((value) => Buffer.byteLength(value, "utf8") <= MAX_GENERATED_SDL_BYTES, {
|
|
7772
|
+
message: `sdl exceeds ${MAX_GENERATED_SDL_BYTES} bytes`
|
|
7773
|
+
}),
|
|
7774
|
+
schema_snapshot: zod.z.json(),
|
|
7775
|
+
// The existing ORM committed-migration validator and replay engine remain
|
|
7776
|
+
// authoritative. This envelope hashes the provenance, never authorizes SQL.
|
|
7777
|
+
migration: zod.z.json().optional()
|
|
7778
|
+
}).strict();
|
|
7779
|
+
var ormMigrationExportSchema = zod.z.object({
|
|
7780
|
+
schema_version: zod.z.literal(1),
|
|
7781
|
+
schema_hash: hash,
|
|
7782
|
+
payload: ormMigrationPayloadSchema,
|
|
7783
|
+
checksum: zod.z.string().regex(/^[0-9a-f]{64}$/)
|
|
7784
|
+
}).strict();
|
|
7785
|
+
function checksum(value) {
|
|
7786
|
+
return crypto.createHash("sha256").update(stableJson(value)).digest("hex");
|
|
7787
|
+
}
|
|
7788
|
+
function createOrmMigrationExport({ schemaHash, payload }) {
|
|
7789
|
+
const contents = { schema_version: 1, schema_hash: hash.parse(schemaHash), payload: ormMigrationPayloadSchema.parse(payload) };
|
|
7790
|
+
return { ...contents, checksum: checksum(contents) };
|
|
7791
|
+
}
|
|
7792
|
+
function parseOrmMigrationExport(text4) {
|
|
7793
|
+
if (Buffer.byteLength(text4, "utf8") > ORM_MIGRATION_EXPORT_MAX_BYTES) throw new Error("ORM migration export exceeds the size limit");
|
|
7794
|
+
const exported = ormMigrationExportSchema.parse(JSON.parse(text4));
|
|
7795
|
+
const { checksum: expected, ...contents } = exported;
|
|
7796
|
+
if (checksum(contents) !== expected) throw new Error("ORM migration export checksum mismatch; regenerate and commit it");
|
|
7797
|
+
return exported;
|
|
7798
|
+
}
|
|
7799
|
+
function renderOrmMigrationExport(exported) {
|
|
7800
|
+
const text4 = `${JSON.stringify(exported, null, 2)}
|
|
7801
|
+
`;
|
|
7802
|
+
if (Buffer.byteLength(text4, "utf8") > ORM_MIGRATION_EXPORT_MAX_BYTES) throw new Error("ORM migration export exceeds the size limit");
|
|
7803
|
+
return text4;
|
|
7804
|
+
}
|
|
7631
7805
|
|
|
7632
7806
|
// src/schema/namespace.ts
|
|
7633
7807
|
var EMPTY_CAPABILITIES = { roles: { definitions: {}, capabilities: {} }, uses: [] };
|
|
@@ -8358,132 +8532,6 @@ var importSpecSchema = zod.z.object({
|
|
|
8358
8532
|
onConflict: zod.z.enum(IMPORT_CONFLICT_MODES).default("skip"),
|
|
8359
8533
|
batchSize: zod.z.number().int().min(1).max(2e4).default(5e3)
|
|
8360
8534
|
}).strict();
|
|
8361
|
-
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
8362
|
-
var DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
8363
|
-
var TIMESTAMPTZ_RE = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:?\d{2})$/;
|
|
8364
|
-
var INTEGER_RE = /^-?\d+$/;
|
|
8365
|
-
var NUMERIC_RE = /^-?\d+(\.\d+)?$/;
|
|
8366
|
-
function sourceSchemaAllowed(schema) {
|
|
8367
|
-
return schema !== "information_schema" && !schema.startsWith("pg_");
|
|
8368
|
-
}
|
|
8369
|
-
function isRelationIdentifier(value) {
|
|
8370
|
-
return value.length <= 63 && IDENTIFIER_PATTERN.test(value);
|
|
8371
|
-
}
|
|
8372
|
-
function isSourceColumn(value) {
|
|
8373
|
-
return value.length <= 63 && COLUMN_IDENTIFIER_PATTERN.test(value);
|
|
8374
|
-
}
|
|
8375
|
-
function splitQualifiedRelation(from) {
|
|
8376
|
-
const dot = from.indexOf(".");
|
|
8377
|
-
if (dot <= 0 || dot !== from.lastIndexOf(".")) return null;
|
|
8378
|
-
const schema = from.slice(0, dot);
|
|
8379
|
-
const table = from.slice(dot + 1);
|
|
8380
|
-
if (!isRelationIdentifier(schema) || !isRelationIdentifier(table)) return null;
|
|
8381
|
-
return { schema, table };
|
|
8382
|
-
}
|
|
8383
|
-
function postgresTypeName(type) {
|
|
8384
|
-
if (type === "double") return "double precision";
|
|
8385
|
-
if (type === "timestamptz") return "timestamp with time zone";
|
|
8386
|
-
return type;
|
|
8387
|
-
}
|
|
8388
|
-
function columnPostgresType(column, schemaName, enums) {
|
|
8389
|
-
if (typeof column.type === "string") return postgresTypeName(column.type);
|
|
8390
|
-
if (!enums.has(column.type.enum)) return null;
|
|
8391
|
-
return `${quoteIdentifier(schemaName)}.${quoteIdentifier(column.type.enum)}`;
|
|
8392
|
-
}
|
|
8393
|
-
function quoteQualified(schema, table) {
|
|
8394
|
-
return `${quoteIdentifier(schema)}.${quoteIdentifier(table)}`;
|
|
8395
|
-
}
|
|
8396
|
-
var INT4_MIN = -2147483648;
|
|
8397
|
-
var INT4_MAX = 2147483647;
|
|
8398
|
-
function resumeLiteralSql({
|
|
8399
|
-
column,
|
|
8400
|
-
after,
|
|
8401
|
-
schemaName,
|
|
8402
|
-
enums
|
|
8403
|
-
}) {
|
|
8404
|
-
const coerced = coerceResumeValue(column, after);
|
|
8405
|
-
if (!coerced.ok) return coerced;
|
|
8406
|
-
return literalSql({ column, value: coerced.value, schemaName, enums });
|
|
8407
|
-
}
|
|
8408
|
-
function coerceResumeValue(column, after) {
|
|
8409
|
-
const type = typeof column.type === "string" ? column.type : null;
|
|
8410
|
-
if (type === "integer") {
|
|
8411
|
-
if (!INTEGER_RE.test(after)) return { ok: false, error: `${column.name}: after must be an integer` };
|
|
8412
|
-
const parsed = Number(after);
|
|
8413
|
-
if (!Number.isSafeInteger(parsed) || parsed < INT4_MIN || parsed > INT4_MAX) {
|
|
8414
|
-
return { ok: false, error: `${column.name}: after must be an integer` };
|
|
8415
|
-
}
|
|
8416
|
-
return { ok: true, value: parsed };
|
|
8417
|
-
}
|
|
8418
|
-
if (type === "boolean") {
|
|
8419
|
-
if (after !== "true" && after !== "false") return { ok: false, error: `${column.name}: after must be true or false` };
|
|
8420
|
-
return { ok: true, value: after === "true" };
|
|
8421
|
-
}
|
|
8422
|
-
return { ok: true, value: after };
|
|
8423
|
-
}
|
|
8424
|
-
function literalSql({
|
|
8425
|
-
column,
|
|
8426
|
-
value,
|
|
8427
|
-
schemaName,
|
|
8428
|
-
enums
|
|
8429
|
-
}) {
|
|
8430
|
-
const label = column.name;
|
|
8431
|
-
if (typeof value === "string" && value.includes("\0")) {
|
|
8432
|
-
return { ok: false, error: `${label}: null default contains a NUL character` };
|
|
8433
|
-
}
|
|
8434
|
-
if (typeof column.type !== "string") {
|
|
8435
|
-
const enumDef = enums.get(column.type.enum);
|
|
8436
|
-
if (!enumDef) return { ok: false, error: `${label}: enum '${column.type.enum}' is not declared` };
|
|
8437
|
-
if (typeof value !== "string" || !enumDef.values.includes(value)) {
|
|
8438
|
-
return { ok: false, error: `${label}: null default must be one of ${enumDef.values.join(", ")}` };
|
|
8439
|
-
}
|
|
8440
|
-
const typeName = columnPostgresType(column, schemaName, enums);
|
|
8441
|
-
return { ok: true, sql: `${quoteLiteral(value)}::${typeName}` };
|
|
8442
|
-
}
|
|
8443
|
-
return scalarLiteral2({ column, type: column.type, value, label });
|
|
8444
|
-
}
|
|
8445
|
-
var SCALAR_LITERALS = {
|
|
8446
|
-
text: (value, label) => typeof value === "string" ? { ok: true, sql: quoteLiteral(value) } : { ok: false, error: `${label}: null default must be a string` },
|
|
8447
|
-
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` },
|
|
8448
|
-
boolean: (value, label) => typeof value === "boolean" ? { ok: true, sql: value ? "TRUE" : "FALSE" } : { ok: false, error: `${label}: null default must be true or false` },
|
|
8449
|
-
integer: (value, label) => typeof value === "number" && Number.isSafeInteger(value) ? { ok: true, sql: String(value) } : { ok: false, error: `${label}: null default must be an integer` },
|
|
8450
|
-
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` },
|
|
8451
|
-
numeric: numericLiteral,
|
|
8452
|
-
double: numericLiteral,
|
|
8453
|
-
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` },
|
|
8454
|
-
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` },
|
|
8455
|
-
jsonb: jsonbLiteral
|
|
8456
|
-
};
|
|
8457
|
-
function numericLiteral(value, label) {
|
|
8458
|
-
if (typeof value === "number" && Number.isFinite(value)) return { ok: true, sql: String(value) };
|
|
8459
|
-
if (typeof value === "string" && NUMERIC_RE.test(value)) return { ok: true, sql: value };
|
|
8460
|
-
return { ok: false, error: `${label}: null default must be a finite number` };
|
|
8461
|
-
}
|
|
8462
|
-
function scalarLiteral2({
|
|
8463
|
-
column,
|
|
8464
|
-
type,
|
|
8465
|
-
value,
|
|
8466
|
-
label
|
|
8467
|
-
}) {
|
|
8468
|
-
const encode = SCALAR_LITERALS[type];
|
|
8469
|
-
if (!encode) return { ok: false, error: `${column.name}: unsupported type '${type}'` };
|
|
8470
|
-
return encode(value, label);
|
|
8471
|
-
}
|
|
8472
|
-
function jsonbLiteral(value, label) {
|
|
8473
|
-
if (typeof value !== "string") return { ok: false, error: `${label}: null default must be a JSON string` };
|
|
8474
|
-
try {
|
|
8475
|
-
JSON.parse(value);
|
|
8476
|
-
} catch {
|
|
8477
|
-
return { ok: false, error: `${label}: null default must be valid JSON` };
|
|
8478
|
-
}
|
|
8479
|
-
return { ok: true, sql: `${quoteLiteral(value)}::jsonb` };
|
|
8480
|
-
}
|
|
8481
|
-
function dollarQuote(body) {
|
|
8482
|
-
const digest = crypto.createHash("sha256").update(body).digest("hex");
|
|
8483
|
-
const candidates = ["seq_orm_import", `seq_orm_${digest.slice(0, 16)}`, `seq_orm_${digest}`];
|
|
8484
|
-
const tag = candidates.find((candidate) => !body.includes(`$${candidate}$`)) ?? `seq_orm_${digest}_body`;
|
|
8485
|
-
return `$${tag}$${body}$${tag}$`;
|
|
8486
|
-
}
|
|
8487
8535
|
|
|
8488
8536
|
// src/import/script.ts
|
|
8489
8537
|
function renderImportScript({
|
|
@@ -8947,6 +8995,8 @@ exports.SCHEMA_DIR = SCHEMA_DIR;
|
|
|
8947
8995
|
exports.SERVICE_PRINCIPAL_IR_VERSION = SERVICE_PRINCIPAL_IR_VERSION;
|
|
8948
8996
|
exports.SQL_IR_VERSION = SQL_IR_VERSION;
|
|
8949
8997
|
exports.STATEMENT_KINDS = STATEMENT_KINDS;
|
|
8998
|
+
exports.SYNCED_BACKING_ABSENT_FUNCTION = SYNCED_BACKING_ABSENT_FUNCTION;
|
|
8999
|
+
exports.SYNCED_BACKING_ABSENT_SQLSTATE = SYNCED_BACKING_ABSENT_SQLSTATE;
|
|
8950
9000
|
exports.SYNCED_CONTRACT_HASH_DOMAIN = SYNCED_CONTRACT_HASH_DOMAIN;
|
|
8951
9001
|
exports.SYNCED_SOURCE_PATTERN = SYNCED_SOURCE_PATTERN;
|
|
8952
9002
|
exports.SYNCED_VIEW_EXECUTION_OWNER_ROLE = SYNCED_VIEW_EXECUTION_OWNER_ROLE;
|
|
@@ -9016,6 +9066,8 @@ exports.defineView = defineView;
|
|
|
9016
9066
|
exports.deriveColumnName = deriveColumnName;
|
|
9017
9067
|
exports.diffCommand = diffCommand;
|
|
9018
9068
|
exports.diffStatements = diffStatements;
|
|
9069
|
+
exports.disabledSyncedObjectFromError = disabledSyncedObjectFromError;
|
|
9070
|
+
exports.disabledSyncedObjectMessage = disabledSyncedObjectMessage;
|
|
9019
9071
|
exports.emptyJournal = emptyJournal;
|
|
9020
9072
|
exports.emptySnapshot = emptySnapshot;
|
|
9021
9073
|
exports.endAuthoringContext = endAuthoringContext;
|
|
@@ -9028,7 +9080,7 @@ exports.generateSnapshotV2 = generateSnapshotV2;
|
|
|
9028
9080
|
exports.highest = highest;
|
|
9029
9081
|
exports.identifierSchema = identifierSchema;
|
|
9030
9082
|
exports.importSpecSchema = importSpecSchema;
|
|
9031
|
-
exports.
|
|
9083
|
+
exports.indexByName = indexByName;
|
|
9032
9084
|
exports.isColumnBuilder = isColumnBuilder;
|
|
9033
9085
|
exports.isEnumRef = isEnumRef;
|
|
9034
9086
|
exports.isExternalPolicyClaimKey = isExternalPolicyClaimKey;
|
|
@@ -9116,6 +9168,7 @@ exports.syncedIndexStatements = syncedIndexStatements;
|
|
|
9116
9168
|
exports.syncedTables = syncedTables;
|
|
9117
9169
|
exports.syncedViewDropStatements = syncedViewDropStatements;
|
|
9118
9170
|
exports.syncedViewStatements = syncedViewStatements;
|
|
9171
|
+
exports.syncedViewUnbackedStatements = syncedViewUnbackedStatements;
|
|
9119
9172
|
exports.t = t;
|
|
9120
9173
|
exports.tableFileSchema = tableFileSchema;
|
|
9121
9174
|
exports.tableMetaIrSchema = tableMetaIrSchema;
|