@sequenceholdings/orm 2.1.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/authoring.cjs +284 -99
- package/dist/authoring.cjs.map +1 -1
- package/dist/authoring.d.cts +31 -8
- package/dist/authoring.d.ts +31 -8
- package/dist/authoring.js +282 -100
- package/dist/authoring.js.map +1 -1
- package/dist/canonical.cjs +51 -3
- package/dist/canonical.cjs.map +1 -1
- package/dist/canonical.d.cts +838 -12
- package/dist/canonical.d.ts +838 -12
- package/dist/canonical.js +47 -4
- package/dist/canonical.js.map +1 -1
- package/dist/cli.cjs +5876 -4198
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +5876 -4198
- package/dist/cli.js.map +1 -1
- package/dist/client.cjs +49 -32
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +49 -6
- package/dist/client.d.ts +49 -6
- package/dist/client.js +49 -32
- package/dist/client.js.map +1 -1
- package/dist/compiler.cjs +1275 -264
- package/dist/compiler.cjs.map +1 -1
- package/dist/compiler.d.cts +57 -3
- package/dist/compiler.d.ts +57 -3
- package/dist/compiler.js +1268 -265
- package/dist/compiler.js.map +1 -1
- package/dist/{constants-YoFGjIBM.d.cts → constants-C6EG6Wq7.d.cts} +1 -1
- package/dist/{constants-YoFGjIBM.d.ts → constants-C6EG6Wq7.d.ts} +1 -1
- package/dist/definition-DjfC7Lll.d.cts +91 -0
- package/dist/definition-DjfC7Lll.d.ts +91 -0
- package/dist/dynamic-input.cjs +2 -1
- package/dist/dynamic-input.cjs.map +1 -1
- package/dist/dynamic-input.d.cts +9 -2
- package/dist/dynamic-input.d.ts +9 -2
- package/dist/dynamic-input.js +2 -1
- package/dist/dynamic-input.js.map +1 -1
- package/dist/index.cjs +1103 -322
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +479 -19
- package/dist/index.d.ts +479 -19
- package/dist/index.js +1090 -323
- package/dist/index.js.map +1 -1
- package/dist/ir.cjs +93 -11
- package/dist/ir.cjs.map +1 -1
- package/dist/ir.d.cts +226 -15
- package/dist/ir.d.ts +226 -15
- package/dist/ir.js +88 -12
- package/dist/ir.js.map +1 -1
- package/dist/predicate-v2.cjs +116 -10
- package/dist/predicate-v2.cjs.map +1 -1
- package/dist/predicate-v2.d.cts +11 -3
- package/dist/predicate-v2.d.ts +11 -3
- package/dist/predicate-v2.js +116 -10
- package/dist/predicate-v2.js.map +1 -1
- package/dist/sdl.cjs +158 -22
- package/dist/sdl.cjs.map +1 -1
- package/dist/sdl.d.cts +8 -1
- package/dist/sdl.d.ts +8 -1
- package/dist/sdl.js +158 -22
- package/dist/sdl.js.map +1 -1
- package/package.json +5 -4
- package/src/codegen-gql/server-fns.cjs +2 -2
- package/templates/orm-namespace/AGENTS.md +10 -0
- package/templates/orm-namespace/CLAUDE.md +1 -84
- package/templates/orm-namespace/package.json +1 -1
package/dist/predicate-v2.cjs
CHANGED
|
@@ -34,6 +34,7 @@ var PolicyCompileError = class extends Error {
|
|
|
34
34
|
var COLUMN_IDENTIFIER_PATTERN = /^_?[a-z][a-z0-9_]*$/;
|
|
35
35
|
var MAX_IDENTIFIER_LENGTH = 63;
|
|
36
36
|
var CAPABILITY_KEY_PATTERN = /^(?:org\/|app\/[a-z][a-z0-9-]{0,63}\/)?[a-z0-9-]{1,64}$/;
|
|
37
|
+
var QUALIFIED_TABLE_PATTERN = /^[a-z][a-z0-9_]{0,62}\.[a-z][a-z0-9_]{0,62}$/;
|
|
37
38
|
var CELL_PARTS = ["at", "by", "rev", "source", "conflicts"];
|
|
38
39
|
var CELL_PART_SUFFIX = {
|
|
39
40
|
at: "__at",
|
|
@@ -563,6 +564,8 @@ var canonicalLinkSchema = zod.z.object({
|
|
|
563
564
|
kind: zod.z.enum(["toOne", "toMany", "toPlatformUser"]),
|
|
564
565
|
/** Target table name (namespace-local). Absent for toPlatformUser. */
|
|
565
566
|
target: identifier2.optional(),
|
|
567
|
+
/** Owning namespace of an imported target; omitted for local links. */
|
|
568
|
+
namespace: identifier2.max(41).optional(),
|
|
566
569
|
/** FK column on the owning side (toOne/toPlatformUser: on this table; toMany: on the target). */
|
|
567
570
|
on: columnIdentifier,
|
|
568
571
|
/** Referenced column on the target (default: target's PK / platform user `sub`). */
|
|
@@ -664,11 +667,12 @@ var canonicalForeignKeySchema = zod.z.object({
|
|
|
664
667
|
}).strict();
|
|
665
668
|
var canonicalTableSchema = zod.z.object({
|
|
666
669
|
table: identifier2,
|
|
670
|
+
displayName: zod.z.string().trim().min(1).max(120).optional(),
|
|
667
671
|
description: zod.z.string().max(2e3).optional(),
|
|
668
672
|
/** Table-level rename hint (new in v2). */
|
|
669
673
|
renamedFrom: identifier2.optional(),
|
|
670
|
-
/** Synced/reflected read-only tables (`source:
|
|
671
|
-
source: zod.z.string().regex(
|
|
674
|
+
/** Synced/reflected read-only tables (`source: schema.table`) — v1 semantics. */
|
|
675
|
+
source: zod.z.string().regex(QUALIFIED_TABLE_PATTERN).optional(),
|
|
672
676
|
columns: zod.z.array(canonicalColumnSchema).default([]),
|
|
673
677
|
primaryKey: zod.z.array(columnIdentifier).min(1).max(8).optional(),
|
|
674
678
|
links: zod.z.array(canonicalLinkSchema).default([]),
|
|
@@ -821,7 +825,9 @@ function validateCellMetadata(table, index, ctx) {
|
|
|
821
825
|
}
|
|
822
826
|
}
|
|
823
827
|
}
|
|
824
|
-
zod.z.object({
|
|
828
|
+
var exportGateSchema = zod.z.union([zod.z.literal(true), zod.z.object({ capability: zod.z.string().min(1) }).strict(), zod.z.object({ role: zod.z.string().min(1) }).strict()]);
|
|
829
|
+
var relationExportSchema = zod.z.object({ read: exportGateSchema, write: exportGateSchema.optional() }).strict();
|
|
830
|
+
var localDefinitionSchema = zod.z.object({
|
|
825
831
|
definition_format: zod.z.literal(CANONICAL_FORMAT),
|
|
826
832
|
namespace: identifier2.max(41),
|
|
827
833
|
description: zod.z.string().max(2e3).optional(),
|
|
@@ -829,6 +835,8 @@ zod.z.object({
|
|
|
829
835
|
tables: zod.z.array(canonicalTableSchema).min(0).max(500),
|
|
830
836
|
/** Optional to preserve byte-identical hashes for pre-view canonical v2 documents. */
|
|
831
837
|
views: zod.z.array(canonicalViewSchema).max(500).optional(),
|
|
838
|
+
/** Target-owned cross-namespace access contract, using existing namespace grants. */
|
|
839
|
+
exports: zod.z.record(identifier2, relationExportSchema).optional(),
|
|
832
840
|
/** Verbatim custom-roles grammar (@sequenceholdings/custom-roles-manifest). */
|
|
833
841
|
capabilities: zod.z.object({
|
|
834
842
|
roles: zod.z.unknown().optional(),
|
|
@@ -855,7 +863,16 @@ zod.z.object({
|
|
|
855
863
|
}
|
|
856
864
|
}
|
|
857
865
|
const fkTables = new Map(definition.tables.map((table) => [table.table, table]));
|
|
866
|
+
const relations = /* @__PURE__ */ new Set([...fkTables.keys(), ...(definition.views ?? []).map((view) => view.view)]);
|
|
867
|
+
for (const name of Object.keys(definition.exports ?? {})) {
|
|
868
|
+
if (!relations.has(name)) ctx.addIssue({ code: "custom", path: ["exports", name], message: `export '${name}' is not a local object` });
|
|
869
|
+
}
|
|
858
870
|
for (const [tableIndex, table] of definition.tables.entries()) {
|
|
871
|
+
for (const [linkIndex, link] of table.links.entries()) {
|
|
872
|
+
if (link.enforce && link.namespace !== void 0 && link.namespace !== definition.namespace) {
|
|
873
|
+
ctx.addIssue({ code: "custom", path: ["tables", tableIndex, "links", linkIndex], message: "physical foreign keys require a local target; use an ORM link without enforce" });
|
|
874
|
+
}
|
|
875
|
+
}
|
|
859
876
|
const names = /* @__PURE__ */ new Set([
|
|
860
877
|
...table.primaryKey?.length ? [`${table.table}_pkey`] : [],
|
|
861
878
|
...table.columns.filter((column) => column.unique && !(table.primaryKey?.length === 1 && table.primaryKey[0] === column.columnName)).map((column) => `${table.table}_${column.columnName}_unique`),
|
|
@@ -1025,23 +1042,36 @@ zod.z.object({
|
|
|
1025
1042
|
};
|
|
1026
1043
|
for (const view of views) visit(view.view, []);
|
|
1027
1044
|
});
|
|
1045
|
+
localDefinitionSchema.safeExtend({
|
|
1046
|
+
/** Flattened, pinned snapshots. Imported relations never participate in this namespace's DDL. */
|
|
1047
|
+
imports: zod.z.array(localDefinitionSchema).max(32).optional()
|
|
1048
|
+
});
|
|
1028
1049
|
|
|
1029
1050
|
// src/ir/index.ts
|
|
1030
|
-
var IR_VERSION = 2;
|
|
1031
1051
|
var LEGACY_IR_VERSION = 1;
|
|
1032
|
-
var
|
|
1052
|
+
var GUARDED_IR_VERSION = 2;
|
|
1053
|
+
var COMPOSED_IR_VERSION = 3;
|
|
1054
|
+
var SQL_IR_VERSION = 4;
|
|
1055
|
+
var RUNTIME_SQL_IR_VERSION = 5;
|
|
1056
|
+
var irVersionSchema = zod.z.union([zod.z.literal(LEGACY_IR_VERSION), zod.z.literal(GUARDED_IR_VERSION), zod.z.literal(COMPOSED_IR_VERSION), zod.z.literal(SQL_IR_VERSION), zod.z.literal(RUNTIME_SQL_IR_VERSION)]);
|
|
1033
1057
|
zod.z.object({ irVersion: irVersionSchema });
|
|
1034
1058
|
var CLAIMS_CONTRACT = {
|
|
1035
1059
|
sub: "string",
|
|
1036
1060
|
org: "string?",
|
|
1061
|
+
ext_subject: "string?",
|
|
1062
|
+
ext_email: "string?",
|
|
1037
1063
|
roles: "string[]",
|
|
1038
1064
|
capabilities: "string[]"
|
|
1039
1065
|
};
|
|
1066
|
+
var EXTERNAL_POLICY_CLAIM_KEYS = ["ext_subject", "ext_email"];
|
|
1067
|
+
function isExternalPolicyClaimKey(key) {
|
|
1068
|
+
return EXTERNAL_POLICY_CLAIM_KEYS.includes(key);
|
|
1069
|
+
}
|
|
1040
1070
|
var scalarLiteral = zod.z.union([zod.z.string(), zod.z.number(), zod.z.boolean(), zod.z.null()]);
|
|
1041
1071
|
var valueIrSchema = zod.z.discriminatedUnion("kind", [
|
|
1042
1072
|
zod.z.object({ kind: zod.z.literal("literal"), value: zod.z.union([scalarLiteral, zod.z.array(scalarLiteral)]) }),
|
|
1043
1073
|
zod.z.object({ kind: zod.z.literal("variable"), name: zod.z.string() }),
|
|
1044
|
-
zod.z.object({ kind: zod.z.literal("claim"), key: zod.z.enum(["sub", "org"]) })
|
|
1074
|
+
zod.z.object({ kind: zod.z.literal("claim"), key: zod.z.enum(["sub", "org", ...EXTERNAL_POLICY_CLAIM_KEYS]) })
|
|
1045
1075
|
]);
|
|
1046
1076
|
var CMP_OPS = [
|
|
1047
1077
|
"eq",
|
|
@@ -1073,8 +1103,8 @@ var predIrSchema = zod.z.lazy(
|
|
|
1073
1103
|
value: zod.z.number(),
|
|
1074
1104
|
where: predIrSchema.optional()
|
|
1075
1105
|
}),
|
|
1076
|
-
zod.z.object({ kind: zod.z.literal("capability"), key: zod.z.string() }),
|
|
1077
|
-
zod.z.object({ kind: zod.z.literal("role"), key: zod.z.string() }),
|
|
1106
|
+
zod.z.object({ kind: zod.z.literal("capability"), key: zod.z.string(), namespace: zod.z.string().optional() }),
|
|
1107
|
+
zod.z.object({ kind: zod.z.literal("role"), key: zod.z.string(), namespace: zod.z.string().optional() }),
|
|
1078
1108
|
zod.z.object({ kind: zod.z.literal("dynamicFilter"), slot: zod.z.string() }),
|
|
1079
1109
|
zod.z.object({ kind: zod.z.literal("const"), value: zod.z.boolean() })
|
|
1080
1110
|
])
|
|
@@ -1301,7 +1331,31 @@ var variableIrSchema = zod.z.object({
|
|
|
1301
1331
|
/** Absent = no default declared; see {@link variableDefaultIrSchema}. */
|
|
1302
1332
|
defaultValue: variableDefaultIrSchema.optional()
|
|
1303
1333
|
});
|
|
1334
|
+
var sqlColumnSchema = zod.z.object({ name: zod.z.string(), type: zod.z.enum(["text", "boolean", "integer", "bigint", "numeric", "double", "uuid", "date", "timestamptz"]), nullable: zod.z.boolean() });
|
|
1304
1335
|
var compiledOperationSchema = zod.z.object({
|
|
1336
|
+
language: zod.z.literal("sql").optional(),
|
|
1337
|
+
/** Server-compiled object catalog and permission ceiling, never caller SQL. */
|
|
1338
|
+
sqlQuery: zod.z.object({
|
|
1339
|
+
catalog: zod.z.object({
|
|
1340
|
+
identity: zod.z.string(),
|
|
1341
|
+
objects: zod.z.array(zod.z.object({
|
|
1342
|
+
ref: zod.z.string(),
|
|
1343
|
+
table: zod.z.string(),
|
|
1344
|
+
columns: zod.z.array(sqlColumnSchema.extend({ type: zod.z.string() })).min(1),
|
|
1345
|
+
scan: zod.z.string().min(1),
|
|
1346
|
+
read: zod.z.array(zod.z.string()).min(1)
|
|
1347
|
+
}).strict()).min(1).max(256)
|
|
1348
|
+
}).strict(),
|
|
1349
|
+
read: zod.z.array(zod.z.string()).min(1).max(256),
|
|
1350
|
+
maxRows: zod.z.number().int().min(1).max(1e4)
|
|
1351
|
+
}).strict().optional(),
|
|
1352
|
+
sql: zod.z.object({
|
|
1353
|
+
text: zod.z.string().min(1).max(1048576),
|
|
1354
|
+
columns: zod.z.array(sqlColumnSchema).min(1).max(256),
|
|
1355
|
+
parameters: zod.z.array(zod.z.string()).max(128),
|
|
1356
|
+
read: zod.z.array(zod.z.string()).min(1).max(256),
|
|
1357
|
+
maxRows: zod.z.number().int().min(1).max(1e4)
|
|
1358
|
+
}).strict().optional(),
|
|
1305
1359
|
irVersion: irVersionSchema,
|
|
1306
1360
|
name: zod.z.string(),
|
|
1307
1361
|
opHash: zod.z.string().regex(/^sha256:[0-9a-f]{64}$/),
|
|
@@ -1313,8 +1367,16 @@ var compiledOperationSchema = zod.z.object({
|
|
|
1313
1367
|
variables: zod.z.array(variableIrSchema),
|
|
1314
1368
|
/** Every table the op touches — data-token scoping + audit. */
|
|
1315
1369
|
tableSet: zod.z.array(zod.z.string()).min(1),
|
|
1316
|
-
roots: zod.z.array(rootIrSchema)
|
|
1370
|
+
roots: zod.z.array(rootIrSchema)
|
|
1317
1371
|
}).superRefine((operation, ctx) => {
|
|
1372
|
+
if (operation.language === "sql") {
|
|
1373
|
+
const validPlan = operation.sqlQuery ? !operation.sql && operation.irVersion === RUNTIME_SQL_IR_VERSION : !!operation.sql && operation.irVersion === SQL_IR_VERSION;
|
|
1374
|
+
if (!validPlan || operation.kind !== "query" || operation.roots.length !== 0 || !operation.requires?.capability) {
|
|
1375
|
+
ctx.addIssue({ code: "custom", message: "SQL operations require a query-only v4 plan or v5 runtime contract, capability, and no GraphQL roots" });
|
|
1376
|
+
}
|
|
1377
|
+
} else if (operation.sql || operation.sqlQuery || operation.roots.length === 0) {
|
|
1378
|
+
ctx.addIssue({ code: "custom", message: "GraphQL operations require roots and cannot carry SQL" });
|
|
1379
|
+
}
|
|
1318
1380
|
for (const [index, root] of operation.roots.entries()) {
|
|
1319
1381
|
if (root.kind !== "mutation" || root.assertAffectedRows === void 0) continue;
|
|
1320
1382
|
if (operation.irVersion < 2 || operation.kind !== "mutation" || root.includeIf !== void 0) {
|
|
@@ -1361,11 +1423,16 @@ var resolvedMetaIrSchema = zod.z.object({
|
|
|
1361
1423
|
});
|
|
1362
1424
|
var tableMetaIrSchema = zod.z.object({
|
|
1363
1425
|
table: zod.z.string(),
|
|
1426
|
+
namespace: zod.z.string().optional(),
|
|
1427
|
+
dependencies: zod.z.array(zod.z.string()).optional(),
|
|
1428
|
+
foreignReferences: zod.z.array(zod.z.object({ column: zod.z.string(), target: zod.z.string(), targetColumn: zod.z.string() })).optional(),
|
|
1429
|
+
exportRead: zod.z.union([zod.z.literal(true), zod.z.object({ capability: zod.z.string() }), zod.z.object({ role: zod.z.string() })]).optional(),
|
|
1430
|
+
exportWrite: zod.z.union([zod.z.literal(true), zod.z.object({ capability: zod.z.string() }), zod.z.object({ role: zod.z.string() })]).optional(),
|
|
1364
1431
|
schema: zod.z.string(),
|
|
1365
1432
|
typename: zod.z.string(),
|
|
1366
1433
|
/**
|
|
1367
1434
|
* True when statements over this relation evaluate a claims-gated synced
|
|
1368
|
-
* view: synced twins (`source:
|
|
1435
|
+
* view: synced twins (`source: schema.table`) materialize as views whose baked
|
|
1369
1436
|
* policy reads `current_setting('request.jwt.claims')`, and namespace views
|
|
1370
1437
|
* inherit the gate transitively through their declared dependencies. The
|
|
1371
1438
|
* executor must stamp that GUC (transaction-scoped) before any statement
|
|
@@ -1424,10 +1491,18 @@ zod.z.object({
|
|
|
1424
1491
|
irVersion: irVersionSchema,
|
|
1425
1492
|
namespace: zod.z.string(),
|
|
1426
1493
|
schemaHash: zod.z.string(),
|
|
1494
|
+
ownSchemaHash: zod.z.string().optional(),
|
|
1495
|
+
dependencies: zod.z.record(zod.z.string(), zod.z.string()).optional(),
|
|
1496
|
+
readPolicies: zod.z.record(zod.z.string(), predIrSchema).optional(),
|
|
1427
1497
|
opsHash: zod.z.string(),
|
|
1498
|
+
/** Apply-observed synced objects without a serving backing; not part of the authored schema hash. */
|
|
1499
|
+
unbackedTables: zod.z.array(zod.z.string()).optional(),
|
|
1428
1500
|
tables: zod.z.record(zod.z.string(), tableMetaIrSchema),
|
|
1429
1501
|
operations: zod.z.record(zod.z.string(), compiledOperationSchema)
|
|
1430
1502
|
}).superRefine((artifact, ctx) => {
|
|
1503
|
+
if (Object.keys(artifact.dependencies ?? {}).length > 0 && artifact.irVersion < COMPOSED_IR_VERSION) {
|
|
1504
|
+
ctx.addIssue({ code: "custom", path: ["irVersion"], message: "cross-namespace dependencies require IR v3" });
|
|
1505
|
+
}
|
|
1431
1506
|
for (const [name, operation] of Object.entries(artifact.operations)) {
|
|
1432
1507
|
if (operation.irVersion > artifact.irVersion) {
|
|
1433
1508
|
ctx.addIssue({ code: "custom", path: ["operations", name, "irVersion"], message: "operation requires a newer IR version than its artifact" });
|
|
@@ -1746,6 +1821,7 @@ var PolicyCompiler = class {
|
|
|
1746
1821
|
case "or":
|
|
1747
1822
|
return { kind: node.kind, operands: node.operands.map((operand) => this.compile(operand, table, depth)) };
|
|
1748
1823
|
case "not":
|
|
1824
|
+
assertNoNegatedExternalClaim(node.operand);
|
|
1749
1825
|
return { kind: "not", operand: this.compile(node.operand, table, depth) };
|
|
1750
1826
|
case "capability":
|
|
1751
1827
|
return { kind: "capability", key: node.key };
|
|
@@ -1825,6 +1901,9 @@ var PolicyCompiler = class {
|
|
|
1825
1901
|
columnCandidates(info)
|
|
1826
1902
|
);
|
|
1827
1903
|
}
|
|
1904
|
+
if (valueSide.kind === "claim" && isExternalPolicyClaimKey(valueSide.key)) {
|
|
1905
|
+
assertExternalClaimComparison({ op, key: valueSide.key, column: info.columns.find((c) => c.name === column) });
|
|
1906
|
+
}
|
|
1828
1907
|
let cmp = this.buildCmp(op, column, valueSide);
|
|
1829
1908
|
for (let i = links.length - 1; i >= 0; i -= 1) {
|
|
1830
1909
|
cmp = { kind: "exists", link: links[i].name, where: cmp };
|
|
@@ -1845,6 +1924,33 @@ var PolicyCompiler = class {
|
|
|
1845
1924
|
return { kind: "cmp", op: CMP_BY_OP[op], column, value };
|
|
1846
1925
|
}
|
|
1847
1926
|
};
|
|
1927
|
+
function assertExternalClaimComparison({ op, key, column }) {
|
|
1928
|
+
if (op !== "=") {
|
|
1929
|
+
throw new PolicyCompileError(
|
|
1930
|
+
`claim('${key}') supports = comparisons only, got '${op}'`,
|
|
1931
|
+
"unsupported-comparison"
|
|
1932
|
+
);
|
|
1933
|
+
}
|
|
1934
|
+
if (column?.type !== "text") {
|
|
1935
|
+
const actual = column?.type === void 0 ? "of unknown type" : typeof column.type === "string" ? column.type : "an enum";
|
|
1936
|
+
throw new PolicyCompileError(
|
|
1937
|
+
`claim('${key}') is text and compares to a text column only \u2014 '${column?.name ?? "?"}' is ${actual}`,
|
|
1938
|
+
"claim-type-mismatch"
|
|
1939
|
+
);
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
function assertNoNegatedExternalClaim(operand) {
|
|
1943
|
+
walkPolicy(operand, (node) => {
|
|
1944
|
+
if (node.kind !== "compare") return;
|
|
1945
|
+
const claim = [node.left, node.right].find((side) => side.kind === "claim" && isExternalPolicyClaimKey(side.key));
|
|
1946
|
+
if (claim?.kind === "claim") {
|
|
1947
|
+
throw new PolicyCompileError(
|
|
1948
|
+
`claim('${claim.key}') cannot appear under not(): a negated borrower comparison admits other borrowers' rows`,
|
|
1949
|
+
"unsupported-comparison"
|
|
1950
|
+
);
|
|
1951
|
+
}
|
|
1952
|
+
});
|
|
1953
|
+
}
|
|
1848
1954
|
function compilePredicateV2({ expression, table, resolver, maxLinkDepth }) {
|
|
1849
1955
|
const parsed = typeof expression === "string" ? parsePolicy(expression) : expression;
|
|
1850
1956
|
const compiler = new PolicyCompiler({ resolver, maxLinkDepth: maxLinkDepth ?? POLICY_MAX_LINK_DEPTH });
|