@sequenceholdings/orm 2.6.2 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -1
- package/dist/cli.cjs +81 -29
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +81 -29
- package/dist/cli.js.map +1 -1
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +4 -1
- package/dist/client.d.ts +4 -1
- package/dist/client.js.map +1 -1
- package/dist/compiler.cjs +68 -29
- package/dist/compiler.cjs.map +1 -1
- package/dist/compiler.js +68 -29
- package/dist/compiler.js.map +1 -1
- package/dist/index.cjs +73 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -4
- package/dist/index.d.ts +6 -4
- package/dist/index.js +72 -5
- package/dist/index.js.map +1 -1
- package/dist/ir.cjs +19 -3
- package/dist/ir.cjs.map +1 -1
- package/dist/ir.d.cts +13 -6
- package/dist/ir.d.ts +13 -6
- package/dist/ir.js +18 -4
- package/dist/ir.js.map +1 -1
- package/dist/predicate-v2.cjs +24 -2
- package/dist/predicate-v2.cjs.map +1 -1
- package/dist/predicate-v2.d.cts +4 -0
- package/dist/predicate-v2.d.ts +4 -0
- package/dist/predicate-v2.js +24 -2
- package/dist/predicate-v2.js.map +1 -1
- package/dist/sdl.cjs +16 -2
- package/dist/sdl.cjs.map +1 -1
- package/dist/sdl.js +16 -2
- package/dist/sdl.js.map +1 -1
- package/package.json +1 -1
- package/src/codegen-gql/preset.cjs +45 -8
- package/templates/orm-namespace/codegen.ts +5 -0
package/dist/cli.js
CHANGED
|
@@ -1459,14 +1459,21 @@ function normalizeCanonical(definition) {
|
|
|
1459
1459
|
var BUILTIN_SQL_READ_HASH = "sha256:a50c477c952a5e0fe68ed158a4530e4aab573c09bcbb1a8ac454dc88a39a6258";
|
|
1460
1460
|
|
|
1461
1461
|
// src/ir/index.ts
|
|
1462
|
-
var IR_VERSION =
|
|
1462
|
+
var IR_VERSION = 6;
|
|
1463
1463
|
var LEGACY_IR_VERSION = 1;
|
|
1464
1464
|
var GUARDED_IR_VERSION = 2;
|
|
1465
1465
|
var COMPOSED_IR_VERSION = 3;
|
|
1466
1466
|
var SQL_IR_VERSION = 4;
|
|
1467
1467
|
var RUNTIME_SQL_IR_VERSION = 5;
|
|
1468
|
-
var
|
|
1468
|
+
var SERVICE_PRINCIPAL_IR_VERSION = 6;
|
|
1469
|
+
var irVersionSchema = z.union([z.literal(LEGACY_IR_VERSION), z.literal(GUARDED_IR_VERSION), z.literal(COMPOSED_IR_VERSION), z.literal(SQL_IR_VERSION), z.literal(RUNTIME_SQL_IR_VERSION), z.literal(SERVICE_PRINCIPAL_IR_VERSION)]);
|
|
1469
1470
|
var operationVersionSchema = z.object({ irVersion: irVersionSchema });
|
|
1471
|
+
function usesServicePrincipal(value) {
|
|
1472
|
+
if (value === null || typeof value !== "object") return false;
|
|
1473
|
+
if (Array.isArray(value)) return value.some(usesServicePrincipal);
|
|
1474
|
+
const row = value;
|
|
1475
|
+
return row.kind === "servicePrincipal" || Object.values(row).some(usesServicePrincipal);
|
|
1476
|
+
}
|
|
1470
1477
|
function requiredArtifactIrVersion(operations) {
|
|
1471
1478
|
let required = LEGACY_IR_VERSION;
|
|
1472
1479
|
for (const operation of operations) {
|
|
@@ -1526,6 +1533,7 @@ var predIrSchema = z.lazy(
|
|
|
1526
1533
|
z.object({ kind: z.literal("capability"), key: z.string(), namespace: z.string().optional() }),
|
|
1527
1534
|
z.object({ kind: z.literal("role"), key: z.string(), namespace: z.string().optional() }),
|
|
1528
1535
|
z.object({ kind: z.literal("dynamicFilter"), slot: z.string() }),
|
|
1536
|
+
z.object({ kind: z.literal("servicePrincipal") }).strict(),
|
|
1529
1537
|
z.object({ kind: z.literal("const"), value: z.boolean() })
|
|
1530
1538
|
])
|
|
1531
1539
|
);
|
|
@@ -1751,7 +1759,7 @@ var variableIrSchema = z.object({
|
|
|
1751
1759
|
/** Absent = no default declared; see {@link variableDefaultIrSchema}. */
|
|
1752
1760
|
defaultValue: variableDefaultIrSchema.optional()
|
|
1753
1761
|
});
|
|
1754
|
-
var sqlColumnSchema = z.object({ name: z.string(), type: z.enum(["text", "boolean", "integer", "bigint", "numeric", "double", "uuid", "date", "timestamptz"]), nullable: z.boolean() });
|
|
1762
|
+
var sqlColumnSchema = z.object({ name: z.string(), type: z.enum(["text", "boolean", "integer", "bigint", "numeric", "double", "uuid", "date", "timestamptz", "jsonb"]), nullable: z.boolean() });
|
|
1755
1763
|
var compiledOperationSchema = z.object({
|
|
1756
1764
|
language: z.literal("sql").optional(),
|
|
1757
1765
|
/** Server-compiled object catalog and permission ceiling, never caller SQL. */
|
|
@@ -1789,6 +1797,9 @@ var compiledOperationSchema = z.object({
|
|
|
1789
1797
|
tableSet: z.array(z.string()).min(1),
|
|
1790
1798
|
roots: z.array(rootIrSchema)
|
|
1791
1799
|
}).superRefine((operation, ctx) => {
|
|
1800
|
+
if (operation.irVersion < SERVICE_PRINCIPAL_IR_VERSION && usesServicePrincipal(operation.roots)) {
|
|
1801
|
+
ctx.addIssue({ code: "custom", message: "servicePrincipal() requires IR v6" });
|
|
1802
|
+
}
|
|
1792
1803
|
if (operation.language === "sql") {
|
|
1793
1804
|
const validPlan = operation.sqlQuery ? !operation.sql && operation.irVersion === RUNTIME_SQL_IR_VERSION : !!operation.sql && operation.irVersion === SQL_IR_VERSION;
|
|
1794
1805
|
const builtin = operation.name === "BuiltinSqlRead" && operation.opHash === BUILTIN_SQL_READ_HASH && operation.requires === null;
|
|
@@ -1921,6 +1932,9 @@ var compiledArtifactSchema = z.object({
|
|
|
1921
1932
|
tables: z.record(z.string(), tableMetaIrSchema),
|
|
1922
1933
|
operations: z.record(z.string(), compiledOperationSchema)
|
|
1923
1934
|
}).superRefine((artifact, ctx) => {
|
|
1935
|
+
if (artifact.irVersion < SERVICE_PRINCIPAL_IR_VERSION && usesServicePrincipal(artifact)) {
|
|
1936
|
+
ctx.addIssue({ code: "custom", message: "servicePrincipal() requires IR v6" });
|
|
1937
|
+
}
|
|
1924
1938
|
if (Object.keys(artifact.dependencies ?? {}).length > 0 && artifact.irVersion < COMPOSED_IR_VERSION) {
|
|
1925
1939
|
ctx.addIssue({ code: "custom", path: ["irVersion"], message: "cross-namespace dependencies require IR v3" });
|
|
1926
1940
|
}
|
|
@@ -2229,6 +2243,12 @@ var Parser2 = class {
|
|
|
2229
2243
|
}
|
|
2230
2244
|
return node;
|
|
2231
2245
|
}
|
|
2246
|
+
if (this.peekKeyword("servicePrincipal") && this.tokens[this.index + 1]?.kind === "lparen") {
|
|
2247
|
+
this.advance();
|
|
2248
|
+
this.expect("lparen", "'(' after servicePrincipal");
|
|
2249
|
+
this.expect("rparen", "')' closing servicePrincipal()");
|
|
2250
|
+
return { kind: "servicePrincipal" };
|
|
2251
|
+
}
|
|
2232
2252
|
if (this.peekKeyword("exists")) return this.parseExists();
|
|
2233
2253
|
if (this.peekKeyword("visible") && this.tokens[this.index + 1]?.kind === "lparen") return this.parseVisible();
|
|
2234
2254
|
return this.parseComparison();
|
|
@@ -2441,6 +2461,8 @@ var PolicyCompiler = class _PolicyCompiler {
|
|
|
2441
2461
|
return { kind: "capability", key: node.key };
|
|
2442
2462
|
case "role":
|
|
2443
2463
|
return { kind: "role", key: node.key };
|
|
2464
|
+
case "servicePrincipal":
|
|
2465
|
+
return { kind: "servicePrincipal" };
|
|
2444
2466
|
case "exists":
|
|
2445
2467
|
return this.compileExists(node.path, node.where, table, depth);
|
|
2446
2468
|
case "visible":
|
|
@@ -3105,7 +3127,10 @@ function platformUserMeta() {
|
|
|
3105
3127
|
{ name: "role", columnName: "role", type: "text", nullable: true },
|
|
3106
3128
|
{ name: "managerId", columnName: "manager_id", type: "text", nullable: true },
|
|
3107
3129
|
// NOT NULL DEFAULT true on chat.users, so non-null through the view.
|
|
3108
|
-
{ name: "accountEnabled", columnName: "account_enabled", type: "boolean", nullable: false }
|
|
3130
|
+
{ name: "accountEnabled", columnName: "account_enabled", type: "boolean", nullable: false },
|
|
3131
|
+
{ name: "canonicalSub", columnName: "canonical_sub", type: "text", nullable: false },
|
|
3132
|
+
{ name: "normalizedEmail", columnName: "normalized_email", type: "text", nullable: true },
|
|
3133
|
+
{ name: "emailDomain", columnName: "email_domain", type: "text", nullable: true }
|
|
3109
3134
|
];
|
|
3110
3135
|
return {
|
|
3111
3136
|
table: "users_directory",
|
|
@@ -5092,7 +5117,7 @@ function compileNamespace({ canonical, sdl, documents }) {
|
|
|
5092
5117
|
}
|
|
5093
5118
|
}
|
|
5094
5119
|
operations[restricted.name] = {
|
|
5095
|
-
irVersion: canonical.imports?.length ? COMPOSED_IR_VERSION : roots.some((root) => root.kind === "mutation" && root.assertAffectedRows !== void 0) ? GUARDED_IR_VERSION : LEGACY_IR_VERSION,
|
|
5120
|
+
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,
|
|
5096
5121
|
name: restricted.name,
|
|
5097
5122
|
opHash: computeOpHash({ definition: flattened, schemaHash }),
|
|
5098
5123
|
kind: restricted.kind,
|
|
@@ -5119,7 +5144,7 @@ function compileNamespace({ canonical, sdl, documents }) {
|
|
|
5119
5144
|
}
|
|
5120
5145
|
if (diagnostics.some((d) => d.severity === "error")) return { ok: false, diagnostics };
|
|
5121
5146
|
const artifact = {
|
|
5122
|
-
irVersion: canonical.imports?.length ? COMPOSED_IR_VERSION : requiredArtifactIrVersion(Object.values(operations)),
|
|
5147
|
+
irVersion: usesServicePrincipal([...ctx.readPolicies.values(), ...ctx.writePolicies.values(), ...ctx.insertPolicies.values(), ...ctx.updatePolicies.values(), ...Object.values(operations)]) ? SERVICE_PRINCIPAL_IR_VERSION : canonical.imports?.length ? COMPOSED_IR_VERSION : requiredArtifactIrVersion(Object.values(operations)),
|
|
5123
5148
|
namespace: ctx.namespace,
|
|
5124
5149
|
schemaHash,
|
|
5125
5150
|
ownSchemaHash: computeSchemaHash(localContract(canonical)),
|
|
@@ -5173,6 +5198,8 @@ function compilePredIrToSql(pred, options = {}) {
|
|
|
5173
5198
|
return `(NOT ${compilePredIrToSql(pred.operand, options)})`;
|
|
5174
5199
|
case "cmp":
|
|
5175
5200
|
return compileCmp(pred.op, pred.column, pred.value, options);
|
|
5201
|
+
case "servicePrincipal":
|
|
5202
|
+
return `coalesce(${claimExpression("servicePrincipal")} = 'true', false)`;
|
|
5176
5203
|
case "capability":
|
|
5177
5204
|
return `(${options.statementClaimChecks ? "SELECT " : ""}${capabilityExpression(pred.key, pred.namespace ?? options.namespace)})`;
|
|
5178
5205
|
case "role":
|
|
@@ -5275,6 +5302,39 @@ function compileArrayValue(value, columnType, _options) {
|
|
|
5275
5302
|
return columnType ? `${array}::${sqlTypeName(columnType)}[]` : array;
|
|
5276
5303
|
}
|
|
5277
5304
|
|
|
5305
|
+
// src/compiler/static-policy-sql.ts
|
|
5306
|
+
function compileStaticPolicySql({ table, predicate, tables, namespace, alias, rootRelation, statementClaimChecks, onRead }) {
|
|
5307
|
+
let sequence = 0;
|
|
5308
|
+
const aliases = new Set([alias, rootRelation].filter((value) => value !== void 0));
|
|
5309
|
+
const column = (meta, qualifier, name2) => {
|
|
5310
|
+
const found = meta.columns.find((c) => c.name === name2 || c.columnName === name2);
|
|
5311
|
+
if (!found) throw new OrmDefinitionError("Static policy relationship column is unavailable");
|
|
5312
|
+
return `${quoteIdentifier(qualifier)}.${quoteIdentifier(found.columnName)}`;
|
|
5313
|
+
};
|
|
5314
|
+
const render = (meta, pred, qualifier, outerRelation) => compilePredIrToSql(pred, {
|
|
5315
|
+
alias: qualifier,
|
|
5316
|
+
namespace: meta.namespace ?? namespace,
|
|
5317
|
+
statementClaimChecks,
|
|
5318
|
+
columnNames: Object.fromEntries(meta.columns.map((c) => [c.name, c.columnName])),
|
|
5319
|
+
columnTypes: Object.fromEntries(meta.columns.map((c) => [c.name, c.type])),
|
|
5320
|
+
exists: (node) => {
|
|
5321
|
+
const link = meta.links.find((candidate) => candidate.name === node.link);
|
|
5322
|
+
const target = link?.target ? tables[link.target] : void 0;
|
|
5323
|
+
const parent = qualifier ?? outerRelation;
|
|
5324
|
+
if (!link || !target || !parent) throw new OrmDefinitionError("Static policy relationship metadata is unavailable");
|
|
5325
|
+
onRead?.(target);
|
|
5326
|
+
let child;
|
|
5327
|
+
do {
|
|
5328
|
+
child = `policy_${++sequence}`;
|
|
5329
|
+
} while (aliases.has(child));
|
|
5330
|
+
aliases.add(child);
|
|
5331
|
+
const join5 = link.kind === "toMany" ? `${column(target, child, link.on)} = ${column(meta, parent, link.references)}` : `${column(meta, parent, link.on)} = ${column(target, child, link.references)}`;
|
|
5332
|
+
return `EXISTS (SELECT 1 FROM ${quoteIdentifier(target.schema)}.${quoteIdentifier(target.table)} AS ${quoteIdentifier(child)} WHERE ${join5} AND (${render(target, node.where, child)}))`;
|
|
5333
|
+
}
|
|
5334
|
+
});
|
|
5335
|
+
return render(table, predicate, alias, rootRelation);
|
|
5336
|
+
}
|
|
5337
|
+
|
|
5278
5338
|
// src/sql/catalog.ts
|
|
5279
5339
|
function sqlHash(value) {
|
|
5280
5340
|
return `sha256:${createHash("sha256").update(value).digest("hex")}`;
|
|
@@ -5295,27 +5355,6 @@ function createSqlCatalog({ canonical, publishedObjects, executionTarget }) {
|
|
|
5295
5355
|
const meta = Object.values(ctx.tables).find((table) => refOf(table) === ref);
|
|
5296
5356
|
if (!meta || internal.has(ref) || meta.namespace !== canonical.namespace && !meta.exportRead) throw new Error(`SQL object not published: ${ref}`);
|
|
5297
5357
|
const reads = /* @__PURE__ */ new Set([ref]);
|
|
5298
|
-
let sequence = 0;
|
|
5299
|
-
const predicate = (table, pred, alias) => compilePredIrToSql(pred, {
|
|
5300
|
-
alias,
|
|
5301
|
-
namespace: table.namespace ?? canonical.namespace,
|
|
5302
|
-
columnNames: Object.fromEntries(table.columns.map((c) => [c.name, c.columnName])),
|
|
5303
|
-
columnTypes: Object.fromEntries(table.columns.map((c) => [c.name, c.type])),
|
|
5304
|
-
exists: (node) => {
|
|
5305
|
-
const link = table.links.find((candidate) => candidate.name === node.link);
|
|
5306
|
-
const target = link?.target ? ctx.tables[link.target] : void 0;
|
|
5307
|
-
if (!link || !target) throw new Error("SQL policy link is unavailable");
|
|
5308
|
-
reads.add(refOf(target));
|
|
5309
|
-
const child = `p${++sequence}`;
|
|
5310
|
-
const col = (t2, a, name2) => {
|
|
5311
|
-
const c = t2.columns.find((c2) => c2.name === name2 || c2.columnName === name2);
|
|
5312
|
-
if (!c) throw new Error("SQL policy column is unavailable");
|
|
5313
|
-
return `${quoteIdentifier(a)}.${quoteIdentifier(c.columnName)}`;
|
|
5314
|
-
};
|
|
5315
|
-
const join5 = link.kind === "toMany" ? `${col(target, child, link.on)} = ${col(table, alias, link.references)}` : `${col(table, alias, link.on)} = ${col(target, child, link.references)}`;
|
|
5316
|
-
return `EXISTS (SELECT 1 FROM ${quoteIdentifier(target.schema)}.${quoteIdentifier(target.table)} AS ${quoteIdentifier(child)} WHERE ${join5} AND (${predicate(target, node.where, child)}))`;
|
|
5317
|
-
}
|
|
5318
|
-
});
|
|
5319
5358
|
const columns = meta.columns.filter((c) => meta.filterable.includes(c.name)).map((c) => ({
|
|
5320
5359
|
name: c.name,
|
|
5321
5360
|
type: typeof c.type === "string" ? c.type : "text",
|
|
@@ -5326,7 +5365,7 @@ function createSqlCatalog({ canonical, publishedObjects, executionTarget }) {
|
|
|
5326
5365
|
return `${quoteIdentifier("p0")}.${quoteIdentifier(physical.columnName)}${typeof physical.type === "object" ? "::text" : ""} AS ${quoteIdentifier(c.name)}`;
|
|
5327
5366
|
}).join(", ");
|
|
5328
5367
|
const policy = ctx.readPolicies.get(meta.table) ?? { kind: "const", value: true };
|
|
5329
|
-
const scan = `SELECT ${projection} FROM ${quoteIdentifier(meta.schema)}.${quoteIdentifier(meta.table)} AS ${quoteIdentifier("p0")} WHERE ${
|
|
5368
|
+
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)) })}`;
|
|
5330
5369
|
return { ref, table: meta.table, columns, scan, read: [...reads].sort() };
|
|
5331
5370
|
});
|
|
5332
5371
|
return { identity, objects };
|
|
@@ -5950,7 +5989,7 @@ async function managedViewDiagnostics(canonical) {
|
|
|
5950
5989
|
}
|
|
5951
5990
|
|
|
5952
5991
|
// src/sql/codegen.ts
|
|
5953
|
-
var typeOf = (type) => ["integer", "double"].includes(type) ? "number" : type === "boolean" ? "boolean" : "string";
|
|
5992
|
+
var typeOf = (type) => ["integer", "double"].includes(type) ? "number" : type === "boolean" ? "boolean" : type === "jsonb" ? "unknown" : "string";
|
|
5954
5993
|
function generateSqlOperations({ artifact }) {
|
|
5955
5994
|
const dynamic = Object.values(artifact.operations).some((op) => op.sqlQuery);
|
|
5956
5995
|
const lines = [
|
|
@@ -5987,6 +6026,15 @@ ${variables}
|
|
|
5987
6026
|
return `${lines.join("\n").trimEnd()}
|
|
5988
6027
|
`;
|
|
5989
6028
|
}
|
|
6029
|
+
|
|
6030
|
+
// src/runtime-capabilities.ts
|
|
6031
|
+
function assertServicePrincipalRuntime(value) {
|
|
6032
|
+
const row = value !== null && typeof value === "object" ? value : {};
|
|
6033
|
+
const predicates = row.policyPredicates;
|
|
6034
|
+
if (typeof row.maxIrVersion !== "number" || row.maxIrVersion < 6 || !Array.isArray(predicates) || !predicates.includes("servicePrincipal")) {
|
|
6035
|
+
throw new Error("The target ORM runtime does not support servicePrincipal() / IR v6; deploy the reviewed runtime before applying this namespace");
|
|
6036
|
+
}
|
|
6037
|
+
}
|
|
5990
6038
|
var ENUM_BRAND = "seq-enum";
|
|
5991
6039
|
function isEnumRef(value) {
|
|
5992
6040
|
return typeof value === "object" && value !== null && value.kind === ENUM_BRAND;
|
|
@@ -11962,6 +12010,10 @@ async function applyV2Command(rest, dir) {
|
|
|
11962
12010
|
}
|
|
11963
12011
|
const { loaded, sdl, documents, manifest } = compiled.project;
|
|
11964
12012
|
const namespace = loaded.canonical.namespace;
|
|
12013
|
+
if (compiled.project.artifact.irVersion >= SERVICE_PRINCIPAL_IR_VERSION || usesServicePrincipal(compiled.project.artifact)) {
|
|
12014
|
+
const support = await apiRequestStrict("GET", "/api/orm/runtime-capabilities");
|
|
12015
|
+
assertServicePrincipalRuntime(support);
|
|
12016
|
+
}
|
|
11965
12017
|
const workspace = await readMigrationWorkspace(dir, namespace);
|
|
11966
12018
|
const migration = await loadCommittedTipMigrationV2({ dir, loaded, workspace });
|
|
11967
12019
|
const registered = await apiRequestStrict("POST", "/api/orm/namespaces", {
|