@sequenceholdings/orm 2.3.0 → 2.5.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/dist/authoring.cjs +53 -7
- package/dist/authoring.cjs.map +1 -1
- package/dist/authoring.d.cts +11 -7
- package/dist/authoring.d.ts +11 -7
- package/dist/authoring.js +53 -7
- package/dist/authoring.js.map +1 -1
- package/dist/canonical.cjs +48 -2
- package/dist/canonical.cjs.map +1 -1
- package/dist/canonical.d.cts +72 -72
- package/dist/canonical.d.ts +72 -72
- package/dist/canonical.js +48 -2
- package/dist/canonical.js.map +1 -1
- package/dist/cli.cjs +337 -86
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +337 -86
- package/dist/cli.js.map +1 -1
- package/dist/client.cjs +1 -1
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/client.js.map +1 -1
- package/dist/compiler.cjs +493 -52
- package/dist/compiler.cjs.map +1 -1
- package/dist/compiler.d.cts +22 -7
- package/dist/compiler.d.ts +22 -7
- package/dist/compiler.js +493 -53
- package/dist/compiler.js.map +1 -1
- package/dist/{constants-C6EG6Wq7.d.cts → constants-Dou1RkTo.d.cts} +7 -2
- package/dist/{constants-C6EG6Wq7.d.ts → constants-Dou1RkTo.d.ts} +7 -2
- package/dist/dynamic-input.d.cts +1 -1
- package/dist/dynamic-input.d.ts +1 -1
- package/dist/index.cjs +329 -130
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +66 -58
- package/dist/index.d.ts +66 -58
- package/dist/index.js +329 -131
- package/dist/index.js.map +1 -1
- package/dist/ir.cjs +50 -3
- package/dist/ir.cjs.map +1 -1
- package/dist/ir.d.cts +71 -71
- package/dist/ir.d.ts +71 -71
- package/dist/ir.js +50 -3
- package/dist/ir.js.map +1 -1
- package/dist/predicate-v2.cjs +145 -22
- package/dist/predicate-v2.cjs.map +1 -1
- package/dist/predicate-v2.d.cts +41 -4
- package/dist/predicate-v2.d.ts +41 -4
- package/dist/predicate-v2.js +145 -22
- package/dist/predicate-v2.js.map +1 -1
- package/dist/sdl.cjs +53 -3
- package/dist/sdl.cjs.map +1 -1
- package/dist/sdl.d.cts +3 -1
- package/dist/sdl.d.ts +3 -1
- package/dist/sdl.js +53 -3
- package/dist/sdl.js.map +1 -1
- package/package.json +1 -1
- package/dist/{definition-DjfC7Lll.d.cts → definition-B99BsOAO.d.cts} +4 -4
- package/dist/{definition-DjfC7Lll.d.ts → definition-B99BsOAO.d.ts} +4 -4
package/dist/predicate-v2.cjs
CHANGED
|
@@ -31,9 +31,11 @@ var PolicyCompileError = class extends Error {
|
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
// src/constants.ts
|
|
34
|
+
var NAMESPACE_PATTERN = /^(?!(?:events|native_sources)$)[a-z][a-z0-9_]{0,40}$/;
|
|
34
35
|
var COLUMN_IDENTIFIER_PATTERN = /^_?[a-z][a-z0-9_]*$/;
|
|
35
36
|
var MAX_IDENTIFIER_LENGTH = 63;
|
|
36
37
|
var CAPABILITY_KEY_PATTERN = /^(?:org\/|app\/[a-z][a-z0-9-]{0,63}\/)?[a-z0-9-]{1,64}$/;
|
|
38
|
+
var MAX_PERSISTED_READ_ROWS = 50001;
|
|
37
39
|
var QUALIFIED_TABLE_PATTERN = /^[a-z][a-z0-9_]{0,62}\.[a-z][a-z0-9_]{0,62}$/;
|
|
38
40
|
var CELL_PARTS = ["at", "by", "rev", "source", "conflicts"];
|
|
39
41
|
var CELL_PART_SUFFIX = {
|
|
@@ -383,6 +385,7 @@ function validateResolvedView({ view, tables, views = [] }) {
|
|
|
383
385
|
function validateSource({ scope, source, table }) {
|
|
384
386
|
const { fail } = scope;
|
|
385
387
|
if (source.kind === "etl" && table.source === void 0) fail(`etl source '${source.name}' must reference a synced table`);
|
|
388
|
+
if (source.kind === "etl" && table.primaryKey?.length === 0) fail(`etl source '${source.name}' cannot use an unkeyed synced table for resolved row identity`);
|
|
386
389
|
if (source.kind !== "etl" && (table.internal !== true || table.cellMetadata !== true)) {
|
|
387
390
|
fail(`${source.kind} source '${source.name}' must reference an internal table with cell metadata`);
|
|
388
391
|
}
|
|
@@ -674,7 +677,7 @@ var canonicalTableSchema = zod.z.object({
|
|
|
674
677
|
/** Synced/reflected read-only tables (`source: schema.table`) — v1 semantics. */
|
|
675
678
|
source: zod.z.string().regex(QUALIFIED_TABLE_PATTERN).optional(),
|
|
676
679
|
columns: zod.z.array(canonicalColumnSchema).default([]),
|
|
677
|
-
primaryKey: zod.z.array(columnIdentifier).
|
|
680
|
+
primaryKey: zod.z.array(columnIdentifier).max(8).optional(),
|
|
678
681
|
links: zod.z.array(canonicalLinkSchema).default([]),
|
|
679
682
|
indexes: zod.z.array(canonicalIndexSchema).default([]),
|
|
680
683
|
/** Omitted by old definitions, preserving their existing content hashes. */
|
|
@@ -710,6 +713,29 @@ var canonicalTableSchema = zod.z.object({
|
|
|
710
713
|
* data plane. Omitted otherwise.
|
|
711
714
|
*/
|
|
712
715
|
materializes: identifier2.optional()
|
|
716
|
+
}).superRefine((table, ctx) => {
|
|
717
|
+
if (table.primaryKey?.length !== 0) return;
|
|
718
|
+
const fail = (message, path = ["primaryKey"]) => ctx.addIssue({ code: "custom", path, message: `unkeyed table '${table.table}' ${message}` });
|
|
719
|
+
if (table.source === void 0 || table.columns.length === 0) {
|
|
720
|
+
fail("requires a typed synced source");
|
|
721
|
+
}
|
|
722
|
+
if ([table.policies.write, table.policies.insert, table.policies.update].some((policy) => policy !== void 0)) {
|
|
723
|
+
fail("is read-only and cannot declare write policies", ["policies"]);
|
|
724
|
+
}
|
|
725
|
+
const ownedCollections = [table.indexes, table.actions, table.checks, table.foreignKeys, table.cowMutations];
|
|
726
|
+
const ownedMetadata = [table.cellMetadata, table.internal, table.materializes, table.renamedFrom];
|
|
727
|
+
if (ownedCollections.some((items) => items !== void 0 && items.length > 0) || ownedMetadata.some((value) => value !== void 0)) {
|
|
728
|
+
fail("cannot declare owned storage, constraints or identity operations");
|
|
729
|
+
}
|
|
730
|
+
for (const [index, column] of table.columns.entries()) {
|
|
731
|
+
const ownedColumnMetadata = [column.default, column.defaultFn, column.onUpdateFn, column.renamedFrom, column.cast, column.cell];
|
|
732
|
+
if (column.unique || ownedColumnMetadata.some((value) => value !== void 0)) {
|
|
733
|
+
fail("cannot declare column uniqueness, mutation defaults or migration metadata", ["columns", index]);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
for (const [index, link] of table.links.entries()) {
|
|
737
|
+
if (link.enforce || link.kind === "toMany") fail("cannot provide an identity for this link", ["links", index]);
|
|
738
|
+
}
|
|
713
739
|
});
|
|
714
740
|
var MAX_VIEW_QUERY = 1e5;
|
|
715
741
|
var MAX_RESOLVED_VIEW_QUERY = 5e6;
|
|
@@ -766,6 +792,26 @@ var canonicalViewSchema = zod.z.object({
|
|
|
766
792
|
}
|
|
767
793
|
}
|
|
768
794
|
});
|
|
795
|
+
function validateUnkeyedLinkIdentities({ definition, ctx }) {
|
|
796
|
+
const tables = new Map(definition.tables.map((table) => [table.table, table]));
|
|
797
|
+
const relations = [
|
|
798
|
+
...definition.tables.map((table, index) => ({ kind: "tables", index, links: table.links })),
|
|
799
|
+
...(definition.views ?? []).map((view, index) => ({ kind: "views", index, links: view.links }))
|
|
800
|
+
];
|
|
801
|
+
for (const relation of relations) {
|
|
802
|
+
for (const [linkIndex, link] of relation.links.entries()) {
|
|
803
|
+
if (link.kind !== "toOne" || link.namespace !== void 0 && link.namespace !== definition.namespace) continue;
|
|
804
|
+
const target = link.target === void 0 ? void 0 : tables.get(link.target);
|
|
805
|
+
if (target?.source !== void 0 && target.primaryKey?.length === 0) {
|
|
806
|
+
ctx.addIssue({
|
|
807
|
+
code: "custom",
|
|
808
|
+
path: [relation.kind, relation.index, "links", linkIndex],
|
|
809
|
+
message: `link '${link.name}' cannot use unkeyed table '${target.table}' as a to-one identity`
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
}
|
|
769
815
|
var CELL_PART_TYPES = {
|
|
770
816
|
at: "timestamptz",
|
|
771
817
|
by: "text",
|
|
@@ -829,7 +875,7 @@ var exportGateSchema = zod.z.union([zod.z.literal(true), zod.z.object({ capabili
|
|
|
829
875
|
var relationExportSchema = zod.z.object({ read: exportGateSchema, write: exportGateSchema.optional() }).strict();
|
|
830
876
|
var localDefinitionSchema = zod.z.object({
|
|
831
877
|
definition_format: zod.z.literal(CANONICAL_FORMAT),
|
|
832
|
-
namespace: identifier2.max(41),
|
|
878
|
+
namespace: identifier2.max(41).regex(NAMESPACE_PATTERN, "invalid or reserved ORM namespace"),
|
|
833
879
|
description: zod.z.string().max(2e3).optional(),
|
|
834
880
|
enums: zod.z.array(canonicalEnumSchema).default([]),
|
|
835
881
|
tables: zod.z.array(canonicalTableSchema).min(0).max(500),
|
|
@@ -863,6 +909,7 @@ var localDefinitionSchema = zod.z.object({
|
|
|
863
909
|
}
|
|
864
910
|
}
|
|
865
911
|
const fkTables = new Map(definition.tables.map((table) => [table.table, table]));
|
|
912
|
+
validateUnkeyedLinkIdentities({ definition, ctx });
|
|
866
913
|
const relations = /* @__PURE__ */ new Set([...fkTables.keys(), ...(definition.views ?? []).map((view) => view.view)]);
|
|
867
914
|
for (const name of Object.keys(definition.exports ?? {})) {
|
|
868
915
|
if (!relations.has(name)) ctx.addIssue({ code: "custom", path: ["exports", name], message: `export '${name}' is not a local object` });
|
|
@@ -1126,7 +1173,7 @@ var limitIrSchema = zod.z.object({
|
|
|
1126
1173
|
variable: zod.z.string().optional(),
|
|
1127
1174
|
value: zod.z.number().int().positive().optional(),
|
|
1128
1175
|
default: zod.z.number().int().positive(),
|
|
1129
|
-
max: zod.z.number().int().positive()
|
|
1176
|
+
max: zod.z.number().int().positive().max(MAX_PERSISTED_READ_ROWS)
|
|
1130
1177
|
});
|
|
1131
1178
|
var selectionIrSchema = zod.z.lazy(
|
|
1132
1179
|
() => zod.z.object({
|
|
@@ -1642,6 +1689,7 @@ var Parser2 = class {
|
|
|
1642
1689
|
return node;
|
|
1643
1690
|
}
|
|
1644
1691
|
if (this.peekKeyword("exists")) return this.parseExists();
|
|
1692
|
+
if (this.peekKeyword("visible") && this.tokens[this.index + 1]?.kind === "lparen") return this.parseVisible();
|
|
1645
1693
|
return this.parseComparison();
|
|
1646
1694
|
}
|
|
1647
1695
|
parseBooleanCall(fn) {
|
|
@@ -1661,6 +1709,13 @@ var Parser2 = class {
|
|
|
1661
1709
|
this.expect("rparen", "')' closing exists(...)");
|
|
1662
1710
|
return { kind: "exists", path, where };
|
|
1663
1711
|
}
|
|
1712
|
+
parseVisible() {
|
|
1713
|
+
this.advance();
|
|
1714
|
+
this.expect("lparen", "'(' after visible");
|
|
1715
|
+
const path = this.parsePath("a link path in visible(...)");
|
|
1716
|
+
this.expect("rparen", "')' closing visible(...)");
|
|
1717
|
+
return { kind: "visible", path };
|
|
1718
|
+
}
|
|
1664
1719
|
parseComparison() {
|
|
1665
1720
|
const left = this.parseOperand();
|
|
1666
1721
|
const operator = this.expect("operator", "a comparison operator");
|
|
@@ -1776,6 +1831,24 @@ function parsePolicy(source) {
|
|
|
1776
1831
|
|
|
1777
1832
|
// src/predicate-v2/compile.ts
|
|
1778
1833
|
var POLICY_MAX_LINK_DEPTH = 3;
|
|
1834
|
+
function scopeToNamespace(pred, namespace) {
|
|
1835
|
+
switch (pred.kind) {
|
|
1836
|
+
case "capability":
|
|
1837
|
+
case "role":
|
|
1838
|
+
return pred.namespace ? pred : { ...pred, namespace };
|
|
1839
|
+
case "and":
|
|
1840
|
+
case "or":
|
|
1841
|
+
return { ...pred, operands: pred.operands.map((operand) => scopeToNamespace(operand, namespace)) };
|
|
1842
|
+
case "not":
|
|
1843
|
+
return { ...pred, operand: scopeToNamespace(pred.operand, namespace) };
|
|
1844
|
+
case "exists":
|
|
1845
|
+
return { ...pred, where: scopeToNamespace(pred.where, namespace) };
|
|
1846
|
+
case "aggPredicate":
|
|
1847
|
+
return pred.where ? { ...pred, where: scopeToNamespace(pred.where, namespace) } : pred;
|
|
1848
|
+
default:
|
|
1849
|
+
return pred;
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1779
1852
|
var CMP_BY_OP = {
|
|
1780
1853
|
"=": "eq",
|
|
1781
1854
|
"!=": "neq",
|
|
@@ -1809,7 +1882,7 @@ function resolveLink(info, ref) {
|
|
|
1809
1882
|
function columnCandidates(info) {
|
|
1810
1883
|
return [...info.columns.map((c) => c.name), ...info.links.map((l) => l.name)];
|
|
1811
1884
|
}
|
|
1812
|
-
var PolicyCompiler = class {
|
|
1885
|
+
var PolicyCompiler = class _PolicyCompiler {
|
|
1813
1886
|
constructor(ctx) {
|
|
1814
1887
|
this.ctx = ctx;
|
|
1815
1888
|
}
|
|
@@ -1822,13 +1895,15 @@ var PolicyCompiler = class {
|
|
|
1822
1895
|
return { kind: node.kind, operands: node.operands.map((operand) => this.compile(operand, table, depth)) };
|
|
1823
1896
|
case "not":
|
|
1824
1897
|
assertNoNegatedExternalClaim(node.operand);
|
|
1825
|
-
return { kind: "not", operand: this.compile(node.operand, table, depth) };
|
|
1898
|
+
return { kind: "not", operand: new _PolicyCompiler({ ...this.ctx, negated: true }).compile(node.operand, table, depth) };
|
|
1826
1899
|
case "capability":
|
|
1827
1900
|
return { kind: "capability", key: node.key };
|
|
1828
1901
|
case "role":
|
|
1829
1902
|
return { kind: "role", key: node.key };
|
|
1830
1903
|
case "exists":
|
|
1831
1904
|
return this.compileExists(node.path, node.where, table, depth);
|
|
1905
|
+
case "visible":
|
|
1906
|
+
return this.compileVisible(node.path, table, depth);
|
|
1832
1907
|
case "compare":
|
|
1833
1908
|
return this.compileCompare(node, table, depth);
|
|
1834
1909
|
}
|
|
@@ -1842,6 +1917,36 @@ var PolicyCompiler = class {
|
|
|
1842
1917
|
}
|
|
1843
1918
|
return pred;
|
|
1844
1919
|
}
|
|
1920
|
+
/** `visible(path)` → `exists(path, <final target's read policy>)`. */
|
|
1921
|
+
compileVisible(path, table, depth) {
|
|
1922
|
+
const { links, finalTable } = this.resolveLinkPath(path, table, depth, { toOneOnly: false });
|
|
1923
|
+
const readPolicy = this.ctx.resolver.readPolicy;
|
|
1924
|
+
if (!readPolicy) {
|
|
1925
|
+
throw new PolicyCompileError(
|
|
1926
|
+
`visible(${path.join(".")}) needs the target's read policy, which this compile context does not provide`,
|
|
1927
|
+
"visible-unresolvable"
|
|
1928
|
+
);
|
|
1929
|
+
}
|
|
1930
|
+
if (this.ctx.visiting.includes(finalTable)) {
|
|
1931
|
+
throw new PolicyCompileError(
|
|
1932
|
+
`visible(${path.join(".")}) on '${table}' reaches '${finalTable}' whose read policy is already being expanded (${[...this.ctx.visiting, finalTable].join(" \u2192 ")})`,
|
|
1933
|
+
"visible-cycle"
|
|
1934
|
+
);
|
|
1935
|
+
}
|
|
1936
|
+
const expression = readPolicy(finalTable);
|
|
1937
|
+
let pred = expression === void 0 ? { kind: "const", value: true } : compilePolicyAt({
|
|
1938
|
+
expression,
|
|
1939
|
+
table: finalTable,
|
|
1940
|
+
ctx: { ...this.ctx, visiting: [...this.ctx.visiting, finalTable] },
|
|
1941
|
+
depth: depth + links.length
|
|
1942
|
+
});
|
|
1943
|
+
const owner = this.ctx.resolver.policyNamespace?.(finalTable);
|
|
1944
|
+
if (owner) pred = scopeToNamespace(pred, owner);
|
|
1945
|
+
for (let i = links.length - 1; i >= 0; i -= 1) {
|
|
1946
|
+
pred = { kind: "exists", link: links[i].name, where: pred };
|
|
1947
|
+
}
|
|
1948
|
+
return pred;
|
|
1949
|
+
}
|
|
1845
1950
|
resolveLinkPath(path, table, depth, { toOneOnly }) {
|
|
1846
1951
|
const links = [];
|
|
1847
1952
|
let current = table;
|
|
@@ -1902,6 +2007,7 @@ var PolicyCompiler = class {
|
|
|
1902
2007
|
);
|
|
1903
2008
|
}
|
|
1904
2009
|
if (valueSide.kind === "claim" && isExternalPolicyClaimKey(valueSide.key)) {
|
|
2010
|
+
if (this.ctx.negated) throw negatedExternalClaim(valueSide.key);
|
|
1905
2011
|
assertExternalClaimComparison({ op, key: valueSide.key, column: info.columns.find((c) => c.name === column) });
|
|
1906
2012
|
}
|
|
1907
2013
|
let cmp = this.buildCmp(op, column, valueSide);
|
|
@@ -1939,22 +2045,30 @@ function assertExternalClaimComparison({ op, key, column }) {
|
|
|
1939
2045
|
);
|
|
1940
2046
|
}
|
|
1941
2047
|
}
|
|
2048
|
+
function negatedExternalClaim(key) {
|
|
2049
|
+
return new PolicyCompileError(
|
|
2050
|
+
`claim('${key}') cannot appear under not(): a negated borrower comparison admits other borrowers' rows`,
|
|
2051
|
+
"unsupported-comparison"
|
|
2052
|
+
);
|
|
2053
|
+
}
|
|
1942
2054
|
function assertNoNegatedExternalClaim(operand) {
|
|
1943
2055
|
walkPolicy(operand, (node) => {
|
|
1944
2056
|
if (node.kind !== "compare") return;
|
|
1945
2057
|
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
|
-
}
|
|
2058
|
+
if (claim?.kind === "claim") throw negatedExternalClaim(claim.key);
|
|
1952
2059
|
});
|
|
1953
2060
|
}
|
|
1954
2061
|
function compilePredicateV2({ expression, table, resolver, maxLinkDepth }) {
|
|
2062
|
+
return compilePredicateAt({
|
|
2063
|
+
expression,
|
|
2064
|
+
table,
|
|
2065
|
+
depth: 0,
|
|
2066
|
+
ctx: { resolver, maxLinkDepth: maxLinkDepth ?? POLICY_MAX_LINK_DEPTH, visiting: [table] }
|
|
2067
|
+
});
|
|
2068
|
+
}
|
|
2069
|
+
function compilePredicateAt({ expression, table, ctx, depth }) {
|
|
1955
2070
|
const parsed = typeof expression === "string" ? parsePolicy(expression) : expression;
|
|
1956
|
-
|
|
1957
|
-
return compiler.compile(parsed.ast, table, 0);
|
|
2071
|
+
return new PolicyCompiler(ctx).compile(parsed.ast, table, depth);
|
|
1958
2072
|
}
|
|
1959
2073
|
function assertClaimsOnlyWhen(parsed) {
|
|
1960
2074
|
walkPolicy(parsed.ast, (node) => {
|
|
@@ -1971,25 +2085,34 @@ function assertClaimsOnlyWhen(parsed) {
|
|
|
1971
2085
|
"when-not-claims-only"
|
|
1972
2086
|
);
|
|
1973
2087
|
}
|
|
1974
|
-
if (node.kind === "exists") {
|
|
2088
|
+
if (node.kind === "exists" || node.kind === "visible") {
|
|
1975
2089
|
throw new PolicyCompileError(
|
|
1976
|
-
|
|
2090
|
+
`variant 'when' guards are claims-only \u2014 ${node.kind}() is not allowed`,
|
|
1977
2091
|
"when-not-claims-only"
|
|
1978
2092
|
);
|
|
1979
2093
|
}
|
|
1980
2094
|
});
|
|
1981
2095
|
}
|
|
1982
|
-
function
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
2096
|
+
function initialVisiting({ table, access }) {
|
|
2097
|
+
return (access ?? "read") === "read" ? [table] : [];
|
|
2098
|
+
}
|
|
2099
|
+
function compilePolicy({ expression, table, resolver, maxLinkDepth, access }) {
|
|
2100
|
+
return compilePolicyAt({
|
|
2101
|
+
expression,
|
|
2102
|
+
table,
|
|
2103
|
+
depth: 0,
|
|
2104
|
+
ctx: { resolver, maxLinkDepth: maxLinkDepth ?? POLICY_MAX_LINK_DEPTH, visiting: initialVisiting({ table, access }) }
|
|
2105
|
+
});
|
|
2106
|
+
}
|
|
2107
|
+
function compilePolicyAt({ expression, table, ctx, depth }) {
|
|
2108
|
+
if (typeof expression === "string") return compilePredicateAt({ expression, table, ctx, depth });
|
|
2109
|
+
const defaultPred = compilePredicateAt({ expression: expression.default, table, ctx, depth });
|
|
1987
2110
|
if (expression.variants.length === 0) return defaultPred;
|
|
1988
2111
|
const branches = expression.variants.map((variant) => {
|
|
1989
2112
|
const parsedWhen = parsePolicy(variant.when);
|
|
1990
2113
|
assertClaimsOnlyWhen(parsedWhen);
|
|
1991
|
-
const when =
|
|
1992
|
-
const grant = variant.allow === true ? { kind: "const", value: true } :
|
|
2114
|
+
const when = compilePredicateAt({ expression: parsedWhen, table, ctx, depth });
|
|
2115
|
+
const grant = variant.allow === true ? { kind: "const", value: true } : compilePredicateAt({ expression: variant.policy, table, ctx, depth });
|
|
1993
2116
|
return { kind: "and", operands: [when, grant] };
|
|
1994
2117
|
});
|
|
1995
2118
|
return { kind: "or", operands: [defaultPred, ...branches] };
|