@cerbos/orm-prisma 4.0.0 → 5.0.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 +611 -460
- package/lib/collections.d.ts +30 -0
- package/lib/collections.d.ts.map +1 -0
- package/lib/collections.js +421 -0
- package/lib/collections.js.map +1 -0
- package/lib/comparison.d.ts +24 -0
- package/lib/comparison.d.ts.map +1 -0
- package/lib/comparison.js +731 -0
- package/lib/comparison.js.map +1 -0
- package/lib/errors.d.ts +13 -0
- package/lib/errors.d.ts.map +1 -0
- package/lib/errors.js +17 -0
- package/lib/errors.js.map +1 -0
- package/lib/evaluate.d.ts +5 -0
- package/lib/evaluate.d.ts.map +1 -0
- package/lib/evaluate.js +118 -0
- package/lib/evaluate.js.map +1 -0
- package/lib/fields.d.ts +34 -0
- package/lib/fields.d.ts.map +1 -0
- package/lib/fields.js +253 -0
- package/lib/fields.js.map +1 -0
- package/lib/functions.d.ts +5 -0
- package/lib/functions.d.ts.map +1 -0
- package/lib/functions.js +408 -0
- package/lib/functions.js.map +1 -0
- package/lib/hierarchy.d.ts +6 -0
- package/lib/hierarchy.d.ts.map +1 -0
- package/lib/hierarchy.js +266 -0
- package/lib/hierarchy.js.map +1 -0
- package/lib/index.d.ts +91 -8
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +34 -2301
- package/lib/index.js.map +1 -1
- package/lib/literals.d.ts +20 -0
- package/lib/literals.d.ts.map +1 -0
- package/lib/literals.js +290 -0
- package/lib/literals.js.map +1 -0
- package/lib/mapping.d.ts +95 -0
- package/lib/mapping.d.ts.map +1 -0
- package/lib/mapping.js +316 -0
- package/lib/mapping.js.map +1 -0
- package/lib/narrowing.d.ts +12 -0
- package/lib/narrowing.d.ts.map +1 -0
- package/lib/narrowing.js +32 -0
- package/lib/narrowing.js.map +1 -0
- package/lib/plan.d.ts +49 -0
- package/lib/plan.d.ts.map +1 -0
- package/lib/plan.js +86 -0
- package/lib/plan.js.map +1 -0
- package/lib/presence.d.ts +25 -0
- package/lib/presence.d.ts.map +1 -0
- package/lib/presence.js +82 -0
- package/lib/presence.js.map +1 -0
- package/lib/regex.d.ts +33 -0
- package/lib/regex.d.ts.map +1 -0
- package/lib/regex.js +480 -0
- package/lib/regex.js.map +1 -0
- package/lib/relations.d.ts +58 -0
- package/lib/relations.d.ts.map +1 -0
- package/lib/relations.js +175 -0
- package/lib/relations.js.map +1 -0
- package/lib/rewrite.d.ts +36 -0
- package/lib/rewrite.d.ts.map +1 -0
- package/lib/rewrite.js +366 -0
- package/lib/rewrite.js.map +1 -0
- package/lib/solve.d.ts +20 -0
- package/lib/solve.d.ts.map +1 -0
- package/lib/solve.js +77 -0
- package/lib/solve.js.map +1 -0
- package/lib/strings.d.ts +12 -0
- package/lib/strings.d.ts.map +1 -0
- package/lib/strings.js +110 -0
- package/lib/strings.js.map +1 -0
- package/lib/ternary.d.ts +12 -0
- package/lib/ternary.d.ts.map +1 -0
- package/lib/ternary.js +192 -0
- package/lib/ternary.js.map +1 -0
- package/lib/timestamp.d.ts +45 -0
- package/lib/timestamp.d.ts.map +1 -0
- package/lib/timestamp.js +225 -0
- package/lib/timestamp.js.map +1 -0
- package/lib/translate.d.ts +20 -0
- package/lib/translate.d.ts.map +1 -0
- package/lib/translate.js +287 -0
- package/lib/translate.js.map +1 -0
- package/lib/types.d.ts +29 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +980 -0
- package/lib/types.js.map +1 -0
- package/lib/value.d.ts +8 -0
- package/lib/value.d.ts.map +1 -0
- package/lib/value.js +7 -0
- package/lib/value.js.map +1 -0
- package/package.json +31 -18
- package/src/adversarial.test.ts +488 -488
- package/src/collections.ts +738 -0
- package/src/comparison.ts +1157 -0
- package/src/corpus.ts +597 -0
- package/src/errors.ts +12 -0
- package/src/evaluate.ts +170 -0
- package/src/fields.ts +373 -0
- package/src/functions.ts +548 -0
- package/src/generated/prisma-adversarial/browser.ts +20 -0
- package/src/generated/prisma-adversarial/client.ts +20 -0
- package/src/generated/prisma-adversarial/commonInputTypes.ts +116 -127
- package/src/generated/prisma-adversarial/internal/class.ts +44 -4
- package/src/generated/prisma-adversarial/internal/prismaNamespace.ts +350 -3
- package/src/generated/prisma-adversarial/internal/prismaNamespaceBrowser.ts +49 -2
- package/src/generated/prisma-adversarial/models/AdversarialBoolListElement.ts +1272 -0
- package/src/generated/prisma-adversarial/models/AdversarialInner.ts +1369 -0
- package/src/generated/prisma-adversarial/models/AdversarialNumberListElement.ts +1316 -0
- package/src/generated/prisma-adversarial/models/AdversarialParent.ts +1474 -0
- package/src/generated/prisma-adversarial/models/AdversarialResource.ts +547 -75
- package/src/generated/prisma-adversarial/models.ts +4 -0
- package/src/generated/prisma-adversarial-mysql/browser.ts +64 -0
- package/src/generated/{prisma → prisma-adversarial-mysql}/client.ts +23 -18
- package/src/generated/{prisma → prisma-adversarial-mysql}/commonInputTypes.ts +167 -92
- package/src/generated/prisma-adversarial-mysql/internal/class.ts +284 -0
- package/src/generated/prisma-adversarial-mysql/internal/prismaNamespace.ts +1518 -0
- package/src/generated/prisma-adversarial-mysql/internal/prismaNamespaceBrowser.ts +274 -0
- package/src/generated/prisma-adversarial-mysql/models/AdversarialBoolListElement.ts +1157 -0
- package/src/generated/prisma-adversarial-mysql/models/AdversarialCategory.ts +1286 -0
- package/src/generated/prisma-adversarial-mysql/models/AdversarialInner.ts +1247 -0
- package/src/generated/prisma-adversarial-mysql/models/AdversarialLabel.ts +1157 -0
- package/src/generated/prisma-adversarial-mysql/models/AdversarialNumberListElement.ts +1201 -0
- package/src/generated/prisma-adversarial-mysql/models/AdversarialParent.ts +1352 -0
- package/src/generated/prisma-adversarial-mysql/models/AdversarialResource.ts +2021 -0
- package/src/generated/prisma-adversarial-mysql/models/AdversarialSubCategory.ts +1286 -0
- package/src/generated/prisma-adversarial-mysql/models/AdversarialTag.ts +1190 -0
- package/src/generated/prisma-adversarial-mysql/models.ts +20 -0
- package/src/generated/prisma-adversarial-mysql-v6/index.d.ts +13822 -0
- package/src/generated/prisma-adversarial-pg/browser.ts +64 -0
- package/src/generated/prisma-adversarial-pg/client.ts +86 -0
- package/src/generated/prisma-adversarial-pg/commonInputTypes.ts +345 -0
- package/src/generated/prisma-adversarial-pg/enums.ts +15 -0
- package/src/generated/prisma-adversarial-pg/internal/class.ts +284 -0
- package/src/generated/prisma-adversarial-pg/internal/prismaNamespace.ts +1542 -0
- package/src/generated/{prisma → prisma-adversarial-pg}/internal/prismaNamespaceBrowser.ts +72 -43
- package/src/generated/prisma-adversarial-pg/models/AdversarialBoolListElement.ts +1275 -0
- package/src/generated/prisma-adversarial-pg/models/AdversarialCategory.ts +1404 -0
- package/src/generated/prisma-adversarial-pg/models/AdversarialInner.ts +1371 -0
- package/src/generated/prisma-adversarial-pg/models/AdversarialLabel.ts +1275 -0
- package/src/generated/prisma-adversarial-pg/models/AdversarialNumberListElement.ts +1319 -0
- package/src/generated/prisma-adversarial-pg/models/AdversarialParent.ts +1476 -0
- package/src/generated/prisma-adversarial-pg/models/AdversarialResource.ts +2139 -0
- package/src/generated/prisma-adversarial-pg/models/AdversarialSubCategory.ts +1404 -0
- package/src/generated/prisma-adversarial-pg/models/AdversarialTag.ts +1310 -0
- package/src/generated/prisma-adversarial-pg/models.ts +20 -0
- package/src/generated/prisma-adversarial-pg-v6/client.d.ts +1 -0
- package/src/generated/prisma-adversarial-pg-v6/default.d.ts +1 -0
- package/src/generated/prisma-adversarial-pg-v6/edge.d.ts +1 -0
- package/src/generated/prisma-adversarial-pg-v6/index.d.ts +14918 -0
- package/src/generated/prisma-adversarial-pg-v6/runtime/index-browser.d.ts +370 -0
- package/src/generated/prisma-adversarial-pg-v6/runtime/library.d.ts +3982 -0
- package/src/generated/prisma-adversarial-pg-v6/wasm.d.ts +1 -0
- package/src/generated/prisma-adversarial-v6/index.d.ts +6515 -304
- package/src/hierarchy.ts +405 -0
- package/src/index.ts +134 -3325
- package/src/literals.ts +363 -0
- package/src/mapping.ts +474 -0
- package/src/narrowing.ts +33 -0
- package/src/plan.ts +125 -0
- package/src/presence.ts +114 -0
- package/src/regex.ts +596 -0
- package/src/relations.ts +226 -0
- package/src/rewrite.ts +524 -0
- package/src/solve.ts +96 -0
- package/src/strings.ts +152 -0
- package/src/ternary.ts +359 -0
- package/src/test-setup.adversarial-url.ts +21 -0
- package/src/test-setup.adversarial.mysql.v6.ts +13 -0
- package/src/test-setup.adversarial.mysql.v7.ts +12 -0
- package/src/test-setup.adversarial.pg.v6.ts +13 -0
- package/src/test-setup.adversarial.pg.v7.ts +9 -0
- package/src/test-setup.adversarial.v7.ts +1 -0
- package/src/timestamp.ts +308 -0
- package/src/translate.ts +419 -0
- package/src/translator.test.ts +766 -0
- package/src/types.ts +1310 -0
- package/src/value.ts +16 -0
- package/src/generated/prisma/browser.ts +0 -59
- package/src/generated/prisma/internal/class.ts +0 -274
- package/src/generated/prisma/internal/prismaNamespace.ts +0 -1403
- package/src/generated/prisma/models/Category.ts +0 -1412
- package/src/generated/prisma/models/Label.ts +0 -1276
- package/src/generated/prisma/models/NestedResource.ts +0 -1562
- package/src/generated/prisma/models/NextLevelNestedResource.ts +0 -1337
- package/src/generated/prisma/models/Resource.ts +0 -2196
- package/src/generated/prisma/models/SubCategory.ts +0 -1412
- package/src/generated/prisma/models/Tag.ts +0 -1276
- package/src/generated/prisma/models/User.ts +0 -1503
- package/src/generated/prisma/models.ts +0 -19
- package/src/generated/prisma-v6/index.d.ts +0 -13726
- package/src/index.test.ts +0 -8885
- package/src/test-setup.v6.ts +0 -5
- package/src/test-setup.v7.ts +0 -7
- /package/src/generated/{prisma → prisma-adversarial-mysql}/enums.ts +0 -0
- /package/src/generated/{prisma-v6 → prisma-adversarial-mysql-v6}/client.d.ts +0 -0
- /package/src/generated/{prisma-v6 → prisma-adversarial-mysql-v6}/default.d.ts +0 -0
- /package/src/generated/{prisma-v6 → prisma-adversarial-mysql-v6}/edge.d.ts +0 -0
- /package/src/generated/{prisma-v6 → prisma-adversarial-mysql-v6}/runtime/index-browser.d.ts +0 -0
- /package/src/generated/{prisma-v6 → prisma-adversarial-mysql-v6}/runtime/library.d.ts +0 -0
- /package/src/generated/{prisma-v6 → prisma-adversarial-mysql-v6}/wasm.d.ts +0 -0
package/lib/solve.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Solving `f(column) CMP v` for a monotone IEEE-754 function f exactly, over the doubles.
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.solveMonotone = solveMonotone;
|
|
5
|
+
exports.negateInterval = negateInterval;
|
|
6
|
+
const view = new DataView(new ArrayBuffer(8));
|
|
7
|
+
const SIGN = 1n << 63n;
|
|
8
|
+
/** An integer key that orders finite doubles as the doubles themselves (+0 and -0 share one). */
|
|
9
|
+
function toKey(x) {
|
|
10
|
+
view.setFloat64(0, x);
|
|
11
|
+
const bits = view.getBigUint64(0);
|
|
12
|
+
return bits & SIGN ? -(bits & ~SIGN) : bits;
|
|
13
|
+
}
|
|
14
|
+
function fromKey(key) {
|
|
15
|
+
view.setBigUint64(0, key < 0n ? -key | SIGN : key);
|
|
16
|
+
return view.getFloat64(0);
|
|
17
|
+
}
|
|
18
|
+
const MIN_KEY = toKey(-Number.MAX_VALUE);
|
|
19
|
+
const MAX_KEY = toKey(Number.MAX_VALUE);
|
|
20
|
+
/** The least key in [MIN_KEY, MAX_KEY] whose double satisfies `holds`, or undefined. */
|
|
21
|
+
function leastKey(holds) {
|
|
22
|
+
if (!holds(fromKey(MAX_KEY)))
|
|
23
|
+
return undefined;
|
|
24
|
+
let low = MIN_KEY;
|
|
25
|
+
let high = MAX_KEY;
|
|
26
|
+
while (low < high) {
|
|
27
|
+
const mid = low + (high - low) / 2n;
|
|
28
|
+
if (holds(fromKey(mid)))
|
|
29
|
+
high = mid;
|
|
30
|
+
else
|
|
31
|
+
low = mid + 1n;
|
|
32
|
+
}
|
|
33
|
+
return low;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The doubles `x` with `f(x) CMP v`, for `f` non-decreasing over the finite doubles — IEEE-754
|
|
37
|
+
* addition and multiplication by a positive constant are, whatever rounding does to them, which
|
|
38
|
+
* is what makes this exact where subtracting the constant from `v` is not.
|
|
39
|
+
*/
|
|
40
|
+
function solveMonotone(f, operator, v) {
|
|
41
|
+
// {x : f(x) >= v} and {x : f(x) > v} are both upward-closed.
|
|
42
|
+
const atLeast = leastKey((x) => f(x) >= v);
|
|
43
|
+
const above = leastKey((x) => f(x) > v);
|
|
44
|
+
const interval = (lo, hi) => {
|
|
45
|
+
if (lo !== undefined && hi !== undefined && lo > hi)
|
|
46
|
+
return { empty: true };
|
|
47
|
+
return {
|
|
48
|
+
empty: false,
|
|
49
|
+
lo: lo === undefined || lo === MIN_KEY ? undefined : fromKey(lo),
|
|
50
|
+
hi: hi === undefined || hi === MAX_KEY ? undefined : fromKey(hi),
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
const below = (key) => (key === undefined ? MAX_KEY : key - 1n);
|
|
54
|
+
switch (operator) {
|
|
55
|
+
case "ge":
|
|
56
|
+
return atLeast === undefined ? { empty: true } : interval(atLeast, undefined);
|
|
57
|
+
case "gt":
|
|
58
|
+
return above === undefined ? { empty: true } : interval(above, undefined);
|
|
59
|
+
case "le":
|
|
60
|
+
return above === MIN_KEY ? { empty: true } : interval(undefined, below(above));
|
|
61
|
+
case "lt":
|
|
62
|
+
return atLeast === MIN_KEY ? { empty: true } : interval(undefined, below(atLeast));
|
|
63
|
+
case "eq":
|
|
64
|
+
return atLeast === undefined ? { empty: true } : interval(atLeast, below(above));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** The interval of `-x` for `x` in `interval`. */
|
|
68
|
+
function negateInterval(interval) {
|
|
69
|
+
if (interval.empty)
|
|
70
|
+
return interval;
|
|
71
|
+
return {
|
|
72
|
+
empty: false,
|
|
73
|
+
lo: interval.hi === undefined ? undefined : -interval.hi,
|
|
74
|
+
hi: interval.lo === undefined ? undefined : -interval.lo,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=solve.js.map
|
package/lib/solve.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solve.js","sourceRoot":"","sources":["../src/solve.ts"],"names":[],"mappings":"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"}
|
package/lib/strings.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PlanExpressionOperand } from "@cerbos/core";
|
|
2
|
+
import type { PrismaFilter } from "./index";
|
|
3
|
+
import type { TranslationContext } from "./mapping";
|
|
4
|
+
/**
|
|
5
|
+
* Helper function to handle string operators (contains, startsWith, endsWith).
|
|
6
|
+
*
|
|
7
|
+
* These operators are receiver-sensitive and the planner preserves policy source order:
|
|
8
|
+
* operand 0 is the receiver (haystack), operand 1 the needle. Swapping them silently
|
|
9
|
+
* inverts the match direction, so unlike symmetric comparisons they are never normalized.
|
|
10
|
+
*/
|
|
11
|
+
export declare function handleStringOperator(operator: string, operands: PlanExpressionOperand[], context: TranslationContext): PrismaFilter;
|
|
12
|
+
//# sourceMappingURL=strings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../src/strings.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAG1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAM5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAmCpD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,qBAAqB,EAAE,EACjC,OAAO,EAAE,kBAAkB,GAC1B,YAAY,CA8Fd"}
|
package/lib/strings.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// The receiver-sensitive string operators: `contains`, `startsWith`, `endsWith`.
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.handleStringOperator = handleStringOperator;
|
|
5
|
+
const fields_1 = require("./fields");
|
|
6
|
+
const mapping_1 = require("./mapping");
|
|
7
|
+
const plan_1 = require("./plan");
|
|
8
|
+
const translate_1 = require("./translate");
|
|
9
|
+
const errors_1 = require("./errors");
|
|
10
|
+
const narrowing_1 = require("./narrowing");
|
|
11
|
+
// Upper bound on the IN-list produced when enumerating a constant receiver's substrings.
|
|
12
|
+
const MAX_ENUMERATED_NEEDLES = 1000;
|
|
13
|
+
/**
|
|
14
|
+
* Every needle `haystack.<operator>(needle)` is true for: its prefixes for startsWith, its
|
|
15
|
+
* suffixes for endsWith, its substrings for contains — and the empty string for all three.
|
|
16
|
+
*/
|
|
17
|
+
function candidateNeedles(operator, haystack) {
|
|
18
|
+
const candidates = new Set([""]);
|
|
19
|
+
if (operator === "startsWith") {
|
|
20
|
+
for (let i = 1; i <= haystack.length; i++) {
|
|
21
|
+
candidates.add(haystack.slice(0, i));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
else if (operator === "endsWith") {
|
|
25
|
+
for (let i = 0; i < haystack.length; i++) {
|
|
26
|
+
candidates.add(haystack.slice(i));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
for (let start = 0; start < haystack.length; start++) {
|
|
31
|
+
for (let end = start + 1; end <= haystack.length; end++) {
|
|
32
|
+
candidates.add(haystack.slice(start, end));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return candidates;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Helper function to handle string operators (contains, startsWith, endsWith).
|
|
40
|
+
*
|
|
41
|
+
* These operators are receiver-sensitive and the planner preserves policy source order:
|
|
42
|
+
* operand 0 is the receiver (haystack), operand 1 the needle. Swapping them silently
|
|
43
|
+
* inverts the match direction, so unlike symmetric comparisons they are never normalized.
|
|
44
|
+
*/
|
|
45
|
+
function handleStringOperator(operator, operands, context) {
|
|
46
|
+
if (operands.length !== 2) {
|
|
47
|
+
throw new errors_1.UnsupportedQueryPlanError(`${operator} requires exactly two operands`);
|
|
48
|
+
}
|
|
49
|
+
const receiver = (0, translate_1.resolveOperand)((0, plan_1.assertDefined)(operands[0], `${operator} requires a receiver operand`), context);
|
|
50
|
+
const needle = (0, translate_1.resolveOperand)((0, plan_1.assertDefined)(operands[1], `${operator} requires a needle operand`), context);
|
|
51
|
+
if ((0, mapping_1.isResolvedFieldReference)(receiver))
|
|
52
|
+
(0, fields_1.assertStringField)(receiver, operator);
|
|
53
|
+
if ((0, mapping_1.isResolvedFieldReference)(needle))
|
|
54
|
+
(0, fields_1.assertStringField)(needle, operator);
|
|
55
|
+
// A null element of a projected list is a value, and a string function over it is an error.
|
|
56
|
+
(0, mapping_1.recordErroringNullElement)(context, operands[0], receiver);
|
|
57
|
+
(0, mapping_1.recordErroringNullElement)(context, operands[1], needle);
|
|
58
|
+
// Column receiver, constant needle: Prisma's LIKE-based filter.
|
|
59
|
+
if ((0, mapping_1.isResolvedFieldReference)(receiver) && (0, mapping_1.isResolvedValue)(needle)) {
|
|
60
|
+
const { value } = needle;
|
|
61
|
+
if (!(0, narrowing_1.isString)(value)) {
|
|
62
|
+
throw new errors_1.UnsupportedQueryPlanError(`${operator} operator requires string value`);
|
|
63
|
+
}
|
|
64
|
+
if (value.includes("\u0000")) {
|
|
65
|
+
throw new errors_1.UnsupportedQueryPlanError(`${operator} with a needle holding a NUL character: PostgreSQL text cannot hold one, and SQLite's LIKE stops reading the pattern at it, so %NUL% matched every row`);
|
|
66
|
+
}
|
|
67
|
+
// A prefix is matched by the range of strings it bounds, so startsWith needs no LIKE escaping
|
|
68
|
+
// (see buildPrefixFilter). Prisma emits LIKE without an ESCAPE clause and does not escape
|
|
69
|
+
// wildcard characters, so a contains or endsWith needle containing % or _ would match as a
|
|
70
|
+
// pattern instead of literally (contains("a_b") wrongly matches "axb"), and a suffix or
|
|
71
|
+
// substring bounds no range. Fail loudly rather than filter wrong.
|
|
72
|
+
//
|
|
73
|
+
// A backslash is the same hazard reached from the other direction, and only an executed
|
|
74
|
+
// PostgreSQL leg surfaces it (cerbos/query-plan-adapters#320): SQLite's LIKE has no escape
|
|
75
|
+
// character at all, so `\` is literal there, while PostgreSQL and MySQL treat it as the
|
|
76
|
+
// DEFAULT escape character even with no ESCAPE clause. `endsWith("\\")` is then a pattern
|
|
77
|
+
// ending in an escape character — a hard error on PostgreSQL — and a `\x` anywhere inside
|
|
78
|
+
// silently drops the backslash, so `contains("a\\b")` matches "ab", a row the PDP denies.
|
|
79
|
+
if (operator === "startsWith") {
|
|
80
|
+
return (0, fields_1.buildPrefixFilter)(receiver, value);
|
|
81
|
+
}
|
|
82
|
+
if (/[%_\\]/.test(value)) {
|
|
83
|
+
throw new errors_1.UnsupportedQueryPlanError(`Cannot translate ${operator} with a needle containing LIKE metacharacters (%, _ or \\): ` +
|
|
84
|
+
"Prisma does not escape wildcards in string filters, and \\ is the default LIKE " +
|
|
85
|
+
"escape character on PostgreSQL and MySQL");
|
|
86
|
+
}
|
|
87
|
+
return (0, fields_1.buildFieldFilter)(receiver, operator, value);
|
|
88
|
+
}
|
|
89
|
+
// Constant receiver, column needle (e.g. `"a-b-c".contains(R.attr.x)`): enumerate every
|
|
90
|
+
// candidate needle the constant admits into an exact IN filter. No LIKE, so no escaping
|
|
91
|
+
// hazards; a NULL needle column stays excluded (CEL missing-attribute deny).
|
|
92
|
+
if ((0, mapping_1.isResolvedValue)(receiver) && (0, mapping_1.isResolvedFieldReference)(needle)) {
|
|
93
|
+
if (!(0, narrowing_1.isString)(receiver.value)) {
|
|
94
|
+
throw new errors_1.UnsupportedQueryPlanError(`${operator} operator requires a string receiver`);
|
|
95
|
+
}
|
|
96
|
+
const candidates = candidateNeedles(operator, receiver.value);
|
|
97
|
+
if (candidates.size > MAX_ENUMERATED_NEEDLES) {
|
|
98
|
+
throw new errors_1.UnsupportedQueryPlanError(`Cannot translate ${operator} with a constant receiver of this length: ` +
|
|
99
|
+
`enumerating its ${candidates.size} candidate needles exceeds the ${MAX_ENUMERATED_NEEDLES}-entry limit`);
|
|
100
|
+
}
|
|
101
|
+
return (0, fields_1.buildFieldFilter)(needle, "in", [...candidates]);
|
|
102
|
+
}
|
|
103
|
+
if ((0, mapping_1.isResolvedFieldReference)(receiver) && (0, mapping_1.isResolvedFieldReference)(needle)) {
|
|
104
|
+
// A column-valued needle would need its LIKE metacharacters escaped per row, which
|
|
105
|
+
// Prisma's filters cannot do (and Prisma leaks wildcards from field references).
|
|
106
|
+
throw new errors_1.UnsupportedQueryPlanError(`Cannot translate ${operator} between two columns: Prisma cannot escape LIKE wildcards held in a column`);
|
|
107
|
+
}
|
|
108
|
+
throw new errors_1.UnsupportedQueryPlanError(`${operator} between two constants must be folded by the Cerbos planner`);
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=strings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strings.js","sourceRoot":"","sources":["../src/strings.ts"],"names":[],"mappings":"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"}
|
package/lib/ternary.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PlanExpressionOperand } from "@cerbos/core";
|
|
2
|
+
import type { PrismaFilter } from "./index";
|
|
3
|
+
import type { TranslationContext } from "./mapping";
|
|
4
|
+
export declare function handleBooleanTernaryOperator(operands: PlanExpressionOperand[], context: TranslationContext): PrismaFilter;
|
|
5
|
+
/**
|
|
6
|
+
* A comparison or membership test with a ternary operand (`(c ? a : b) == x`,
|
|
7
|
+
* `x in (c ? a : b)`), translated by distributing the
|
|
8
|
+
* comparison into both branches; or null when `operator` is not a comparison or no operand is a
|
|
9
|
+
* ternary. `negated` builds the filter for the comparison's negation instead.
|
|
10
|
+
*/
|
|
11
|
+
export declare function tryHandleTernaryComparison(operator: string, operands: PlanExpressionOperand[], context: TranslationContext, negated?: boolean): PrismaFilter | null;
|
|
12
|
+
//# sourceMappingURL=ternary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ternary.d.ts","sourceRoot":"","sources":["../src/ternary.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAAS,MAAM,cAAc,CAAC;AAKjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAuJpD,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,qBAAqB,EAAE,EACjC,OAAO,EAAE,kBAAkB,GAC1B,YAAY,CAmBd;AA6GD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,qBAAqB,EAAE,EACjC,OAAO,EAAE,kBAAkB,EAC3B,OAAO,UAAQ,GACd,YAAY,GAAG,IAAI,CAwDrB"}
|
package/lib/ternary.js
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// `cond ? a : b`, in boolean position and as an operand of a comparison. Both lower to the same
|
|
3
|
+
// guarded disjunction, which keeps CEL's error semantics when the condition is UNKNOWN.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.handleBooleanTernaryOperator = handleBooleanTernaryOperator;
|
|
6
|
+
exports.tryHandleTernaryComparison = tryHandleTernaryComparison;
|
|
7
|
+
const comparison_1 = require("./comparison");
|
|
8
|
+
const evaluate_1 = require("./evaluate");
|
|
9
|
+
const fields_1 = require("./fields");
|
|
10
|
+
const plan_1 = require("./plan");
|
|
11
|
+
const translate_1 = require("./translate");
|
|
12
|
+
const timestamp_1 = require("./timestamp");
|
|
13
|
+
const errors_1 = require("./errors");
|
|
14
|
+
const narrowing_1 = require("./narrowing");
|
|
15
|
+
// The comparison that holds exactly when `operator` does not, over two definite operands.
|
|
16
|
+
const COMPLEMENT_OPERATOR = {
|
|
17
|
+
eq: "ne",
|
|
18
|
+
ne: "eq",
|
|
19
|
+
lt: "ge",
|
|
20
|
+
le: "gt",
|
|
21
|
+
gt: "le",
|
|
22
|
+
ge: "lt",
|
|
23
|
+
};
|
|
24
|
+
function getTernaryOperands(operands) {
|
|
25
|
+
if (operands.length !== 3) {
|
|
26
|
+
throw new errors_1.UnsupportedQueryPlanError(`if (ternary) requires exactly 3 operands (condition, then, else), got ${operands.length}`);
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
condition: (0, plan_1.assertDefined)(operands[0], "if (ternary) requires a condition operand"),
|
|
30
|
+
thenBranch: (0, plan_1.assertDefined)(operands[1], "if (ternary) requires a then operand"),
|
|
31
|
+
elseBranch: (0, plan_1.assertDefined)(operands[2], "if (ternary) requires an else operand"),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function getConstantBooleanCondition(condition) {
|
|
35
|
+
if (!(0, plan_1.isValueOperand)(condition)) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
if (!(0, narrowing_1.isBoolean)(condition.value)) {
|
|
39
|
+
throw new errors_1.UnsupportedQueryPlanError("if (ternary) condition must be a boolean expression");
|
|
40
|
+
}
|
|
41
|
+
return condition.value;
|
|
42
|
+
}
|
|
43
|
+
function buildBooleanBranchFilter(branch, context) {
|
|
44
|
+
if (!(0, plan_1.isValueOperand)(branch)) {
|
|
45
|
+
return {
|
|
46
|
+
kind: "filter",
|
|
47
|
+
filter: (0, translate_1.buildPrismaFilterFromCerbosExpression)(branch, context),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (!(0, narrowing_1.isBoolean)(branch.value)) {
|
|
51
|
+
throw new errors_1.UnsupportedQueryPlanError("if (ternary) branch in boolean position must be a boolean");
|
|
52
|
+
}
|
|
53
|
+
return { kind: "constant", value: branch.value };
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* `(cond AND then) OR (NOT cond AND else) OR (cond AND NOT cond)`, dropping any arm a constant
|
|
57
|
+
* branch makes redundant.
|
|
58
|
+
*
|
|
59
|
+
* "The condition is definitively FALSE" is buildNegatedFilter's contract — three-valued, so a
|
|
60
|
+
* condition that is UNKNOWN (a NULL column, an erroring lambda body, an absent to-one parent)
|
|
61
|
+
* selects NEITHER branch. It delegates rather than spelling a second negation. A private copy is
|
|
62
|
+
* how the ternary missed the hop requirement #315/#316 added: a bare `NOT` over a chain filter is
|
|
63
|
+
* TRUE when the to-one parent is absent, so the else-branch was selected for rows CEL denies
|
|
64
|
+
* outright — the missing path is an evaluation error, not a false condition
|
|
65
|
+
* (cerbos/query-plan-adapters#334). Delegating also gives the ternary the De Morgan push-down,
|
|
66
|
+
* which a chained `and`/`or` condition needs for CEL's error absorption to survive.
|
|
67
|
+
*/
|
|
68
|
+
function buildGuardedTernaryFilter(condition, thenFilter, elseFilter, context) {
|
|
69
|
+
const conditionTrue = (0, translate_1.buildPrismaFilterFromCerbosExpression)(condition, context);
|
|
70
|
+
const conditionFalse = (0, translate_1.buildNegatedFilter)(condition, context);
|
|
71
|
+
const guardedBranches = [];
|
|
72
|
+
if (thenFilter.kind === "filter") {
|
|
73
|
+
guardedBranches.push({ AND: [conditionTrue, thenFilter.filter] });
|
|
74
|
+
}
|
|
75
|
+
else if (thenFilter.value) {
|
|
76
|
+
guardedBranches.push(conditionTrue);
|
|
77
|
+
}
|
|
78
|
+
if (elseFilter.kind === "filter") {
|
|
79
|
+
guardedBranches.push({ AND: [conditionFalse, elseFilter.filter] });
|
|
80
|
+
}
|
|
81
|
+
else if (elseFilter.value) {
|
|
82
|
+
guardedBranches.push(conditionFalse);
|
|
83
|
+
}
|
|
84
|
+
// For a known condition this contradiction is false. If the condition is
|
|
85
|
+
// NULL/error-derived, both sides are SQL UNKNOWN, which keeps the whole
|
|
86
|
+
// ternary UNKNOWN under an outer NOT instead of authorizing the row.
|
|
87
|
+
guardedBranches.push({ AND: [conditionTrue, conditionFalse] });
|
|
88
|
+
return { OR: guardedBranches };
|
|
89
|
+
}
|
|
90
|
+
function finalizeTernaryBranchPredicate(predicate) {
|
|
91
|
+
if (predicate.kind === "filter") {
|
|
92
|
+
return predicate.filter;
|
|
93
|
+
}
|
|
94
|
+
return predicate.value ? {} : (0, fields_1.rejectConstantFalse)();
|
|
95
|
+
}
|
|
96
|
+
function handleBooleanTernaryOperator(operands, context) {
|
|
97
|
+
const { condition, thenBranch, elseBranch } = getTernaryOperands(operands);
|
|
98
|
+
const constantCondition = getConstantBooleanCondition(condition);
|
|
99
|
+
if (constantCondition !== undefined) {
|
|
100
|
+
return finalizeTernaryBranchPredicate(buildBooleanBranchFilter(constantCondition ? thenBranch : elseBranch, context));
|
|
101
|
+
}
|
|
102
|
+
return buildGuardedTernaryFilter(condition, buildBooleanBranchFilter(thenBranch, context), buildBooleanBranchFilter(elseBranch, context), context);
|
|
103
|
+
}
|
|
104
|
+
/** The comparison with its ternary operand replaced by `branch`, as a branch predicate. */
|
|
105
|
+
// A timestamp() literal compares as its canonical instant, never against a bare string.
|
|
106
|
+
function constantOf(operand) {
|
|
107
|
+
if (operand === undefined)
|
|
108
|
+
return undefined;
|
|
109
|
+
if ((0, plan_1.isValueOperand)(operand))
|
|
110
|
+
return { value: operand.value, timestamp: false };
|
|
111
|
+
if ((0, plan_1.isOperatorOperand)(operand) &&
|
|
112
|
+
operand.operator === "timestamp" &&
|
|
113
|
+
operand.operands.length === 1) {
|
|
114
|
+
const literal = operand.operands[0];
|
|
115
|
+
if (literal !== undefined && (0, plan_1.isValueOperand)(literal) && (0, narrowing_1.isString)(literal.value)) {
|
|
116
|
+
return { value: (0, timestamp_1.normalizeRfc3339Milliseconds)(literal.value), timestamp: true };
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
function buildTernaryComparisonBranch(operator, operands, ternaryIndex, branch, context, negated) {
|
|
122
|
+
const substitutedOperands = operands.map((operand, index) => index === ternaryIndex ? branch : operand);
|
|
123
|
+
(0, plan_1.assertDefined)(substitutedOperands[0], `${operator} requires a left operand`);
|
|
124
|
+
(0, plan_1.assertDefined)(substitutedOperands[1], `${operator} requires a right operand`);
|
|
125
|
+
// Membership is not symmetric: its member stays first even when it is the constant.
|
|
126
|
+
const normalized = operator === "in"
|
|
127
|
+
? { operator, operands: substitutedOperands }
|
|
128
|
+
: (0, plan_1.normalizeBinaryOperands)(operator, substitutedOperands);
|
|
129
|
+
const [normalizedFirst, normalizedSecond] = normalized.operands;
|
|
130
|
+
const first = constantOf(normalizedFirst);
|
|
131
|
+
const second = constantOf(normalizedSecond);
|
|
132
|
+
if (normalized.operands.length === 2 &&
|
|
133
|
+
first !== undefined &&
|
|
134
|
+
second !== undefined &&
|
|
135
|
+
first.timestamp === second.timestamp) {
|
|
136
|
+
return {
|
|
137
|
+
kind: "constant",
|
|
138
|
+
value: (0, evaluate_1.evaluateConstantComparison)(normalized.operator, first.value, second.value) !== negated,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
if (!negated) {
|
|
142
|
+
return {
|
|
143
|
+
kind: "filter",
|
|
144
|
+
filter: (0, translate_1.buildPrismaFilterFromCerbosExpression)(normalized, context),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
const nested = tryHandleTernaryComparison(normalized.operator, normalized.operands, context, true);
|
|
148
|
+
if (nested !== null)
|
|
149
|
+
return { kind: "filter", filter: nested };
|
|
150
|
+
if (normalized.operator === "in") {
|
|
151
|
+
return {
|
|
152
|
+
kind: "filter",
|
|
153
|
+
filter: (0, translate_1.buildNegatedFilter)({ operator: "in", operands: normalized.operands }, context),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
// Keep missing-value and relation guards inside the selected branch. Constants
|
|
157
|
+
// are negated above, since !(NaN <= n) is true but NaN > n is false in CEL 0.30.
|
|
158
|
+
return {
|
|
159
|
+
kind: "filter",
|
|
160
|
+
filter: (0, comparison_1.handleRelationalOperator)((0, plan_1.assertDefined)((0, narrowing_1.lookup)(COMPLEMENT_OPERATOR, normalized.operator), "Unsupported negated comparison"), normalized.operands, context),
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* A comparison or membership test with a ternary operand (`(c ? a : b) == x`,
|
|
165
|
+
* `x in (c ? a : b)`), translated by distributing the
|
|
166
|
+
* comparison into both branches; or null when `operator` is not a comparison or no operand is a
|
|
167
|
+
* ternary. `negated` builds the filter for the comparison's negation instead.
|
|
168
|
+
*/
|
|
169
|
+
function tryHandleTernaryComparison(operator, operands, context, negated = false) {
|
|
170
|
+
if ((0, narrowing_1.lookup)(plan_1.CERBOS_TO_PRISMA_OPERATOR, operator) === undefined && operator !== "in") {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
const ternaryIndex = operands.findIndex((operand) => (0, plan_1.isOperatorOperand)(operand) && operand.operator === "if");
|
|
174
|
+
if (ternaryIndex === -1) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
if (operands.length !== 2) {
|
|
178
|
+
throw new errors_1.UnsupportedQueryPlanError(`${operator} with a ternary requires exactly 2 operands, got ${operands.length}`);
|
|
179
|
+
}
|
|
180
|
+
const ternary = (0, plan_1.assertDefined)(operands[ternaryIndex], "Ternary comparison operand is missing");
|
|
181
|
+
if (!(0, plan_1.isOperatorOperand)(ternary)) {
|
|
182
|
+
throw new errors_1.UnsupportedQueryPlanError("Ternary comparison operand must be an expression");
|
|
183
|
+
}
|
|
184
|
+
const { condition, thenBranch, elseBranch } = getTernaryOperands(ternary.operands);
|
|
185
|
+
const branchFor = (branch) => buildTernaryComparisonBranch(operator, operands, ternaryIndex, branch, context, negated);
|
|
186
|
+
const constantCondition = getConstantBooleanCondition(condition);
|
|
187
|
+
if (constantCondition !== undefined) {
|
|
188
|
+
return finalizeTernaryBranchPredicate(branchFor(constantCondition ? thenBranch : elseBranch));
|
|
189
|
+
}
|
|
190
|
+
return buildGuardedTernaryFilter(condition, branchFor(thenBranch), branchFor(elseBranch), context);
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=ternary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ternary.js","sourceRoot":"","sources":["../src/ternary.ts"],"names":[],"mappings":";AAAA,gGAAgG;AAChG,wFAAwF;;AA+JxF,oEAsBC;AAmHD,gEA6DC;AAjWD,6CAAwD;AACxD,yCAAwD;AACxD,qCAA+C;AAG/C,iCAMgB;AAChB,2CAGqB;AACrB,2CAA2D;AAC3D,qCAAqD;AACrD,2CAA0D;AAO1D,0FAA0F;AAC1F,MAAM,mBAAmB,GAAG;IAC1B,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;CACwB,CAAC;AAQnC,SAAS,kBAAkB,CAAC,QAAiC;IAC3D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,kCAAyB,CACjC,yEAAyE,QAAQ,CAAC,MAAM,EAAE,CAC3F,CAAC;IACJ,CAAC;IAED,OAAO;QACL,SAAS,EAAE,IAAA,oBAAa,EACtB,QAAQ,CAAC,CAAC,CAAC,EACX,2CAA2C,CAC5C;QACD,UAAU,EAAE,IAAA,oBAAa,EACvB,QAAQ,CAAC,CAAC,CAAC,EACX,sCAAsC,CACvC;QACD,UAAU,EAAE,IAAA,oBAAa,EACvB,QAAQ,CAAC,CAAC,CAAC,EACX,uCAAuC,CACxC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,2BAA2B,CAClC,SAAgC;IAEhC,IAAI,CAAC,IAAA,qBAAc,EAAC,SAAS,CAAC,EAAE,CAAC;QAC/B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,CAAC,IAAA,qBAAS,EAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,kCAAyB,CAAC,qDAAqD,CAAC,CAAC;IAC7F,CAAC;IAED,OAAO,SAAS,CAAC,KAAK,CAAC;AACzB,CAAC;AAED,SAAS,wBAAwB,CAC/B,MAA6B,EAC7B,OAA2B;IAE3B,IAAI,CAAC,IAAA,qBAAc,EAAC,MAAM,CAAC,EAAE,CAAC;QAC5B,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,IAAA,iDAAqC,EAAC,MAAM,EAAE,OAAO,CAAC;SAC/D,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,IAAA,qBAAS,EAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,kCAAyB,CACjC,2DAA2D,CAC5D,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;AACnD,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAS,yBAAyB,CAChC,SAAgC,EAChC,UAAkC,EAClC,UAAkC,EAClC,OAA2B;IAE3B,MAAM,aAAa,GAAG,IAAA,iDAAqC,EACzD,SAAS,EACT,OAAO,CACR,CAAC;IAEF,MAAM,cAAc,GAAG,IAAA,8BAAkB,EAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC9D,MAAM,eAAe,GAAmB,EAAE,CAAC;IAE3C,IAAI,UAAU,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACjC,eAAe,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,aAAa,EAAE,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACpE,CAAC;SAAM,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;QAC5B,eAAe,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,UAAU,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACjC,eAAe,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,cAAc,EAAE,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACrE,CAAC;SAAM,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;QAC5B,eAAe,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACvC,CAAC;IAED,yEAAyE;IACzE,wEAAwE;IACxE,qEAAqE;IACrE,eAAe,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,aAAa,EAAE,cAAc,CAAC,EAAE,CAAC,CAAC;IAE/D,OAAO,EAAE,EAAE,EAAE,eAAe,EAAE,CAAC;AACjC,CAAC;AAED,SAAS,8BAA8B,CACrC,SAAiC;IAEjC,IAAI,SAAS,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,SAAS,CAAC,MAAM,CAAC;IAC1B,CAAC;IAED,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAA,4BAAmB,GAAE,CAAC;AACtD,CAAC;AAED,SAAgB,4BAA4B,CAC1C,QAAiC,EACjC,OAA2B;IAE3B,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC3E,MAAM,iBAAiB,GAAG,2BAA2B,CAAC,SAAS,CAAC,CAAC;IAEjE,IAAI,iBAAiB,KAAK,SAAS,EAAE,CAAC;QACpC,OAAO,8BAA8B,CACnC,wBAAwB,CACtB,iBAAiB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAC3C,OAAO,CACR,CACF,CAAC;IACJ,CAAC;IAED,OAAO,yBAAyB,CAC9B,SAAS,EACT,wBAAwB,CAAC,UAAU,EAAE,OAAO,CAAC,EAC7C,wBAAwB,CAAC,UAAU,EAAE,OAAO,CAAC,EAC7C,OAAO,CACR,CAAC;AACJ,CAAC;AAED,2FAA2F;AAC3F,wFAAwF;AACxF,SAAS,UAAU,CACjB,OAA0C;IAE1C,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAE5C,IAAI,IAAA,qBAAc,EAAC,OAAO,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IAE/E,IACE,IAAA,wBAAiB,EAAC,OAAO,CAAC;QAC1B,OAAO,CAAC,QAAQ,KAAK,WAAW;QAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAC7B,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAEpC,IAAI,OAAO,KAAK,SAAS,IAAI,IAAA,qBAAc,EAAC,OAAO,CAAC,IAAI,IAAA,oBAAQ,EAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAChF,OAAO,EAAE,KAAK,EAAE,IAAA,wCAA4B,EAAC,OAAO,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QACjF,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,4BAA4B,CACnC,QAAgB,EAChB,QAAiC,EACjC,YAAoB,EACpB,MAA6B,EAC7B,OAA2B,EAC3B,OAAgB;IAEhB,MAAM,mBAAmB,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAC1D,KAAK,KAAK,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAC1C,CAAC;IAEF,IAAA,oBAAa,EAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,GAAG,QAAQ,0BAA0B,CAAC,CAAC;IAC7E,IAAA,oBAAa,EAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,GAAG,QAAQ,2BAA2B,CAAC,CAAC;IAE9E,oFAAoF;IACpF,MAAM,UAAU,GACd,QAAQ,KAAK,IAAI;QACf,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,mBAAmB,EAAE;QAC7C,CAAC,CAAC,IAAA,8BAAuB,EAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;IAE7D,MAAM,CAAC,eAAe,EAAE,gBAAgB,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC;IAChE,MAAM,KAAK,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAE5C,IACE,UAAU,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QAChC,KAAK,KAAK,SAAS;QACnB,MAAM,KAAK,SAAS;QACpB,KAAK,CAAC,SAAS,KAAK,MAAM,CAAC,SAAS,EACpC,CAAC;QACD,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,KAAK,EACH,IAAA,qCAA0B,EACxB,UAAU,CAAC,QAAQ,EACnB,KAAK,CAAC,KAAK,EACX,MAAM,CAAC,KAAK,CACb,KAAK,OAAO;SAChB,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,IAAA,iDAAqC,EAAC,UAAU,EAAE,OAAO,CAAC;SACnE,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,0BAA0B,CACvC,UAAU,CAAC,QAAQ,EACnB,UAAU,CAAC,QAAQ,EACnB,OAAO,EACP,IAAI,CACL,CAAC;IAEF,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAE/D,IAAI,UAAU,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QACjC,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,IAAA,8BAAkB,EACxB,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,EACjD,OAAO,CACR;SACF,CAAC;IACJ,CAAC;IAED,+EAA+E;IAC/E,iFAAiF;IACjF,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,IAAA,qCAAwB,EAC9B,IAAA,oBAAa,EACX,IAAA,kBAAM,EAAC,mBAAmB,EAAE,UAAU,CAAC,QAAQ,CAAC,EAChD,gCAAgC,CACjC,EACD,UAAU,CAAC,QAAQ,EACnB,OAAO,CACR;KACF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAgB,0BAA0B,CACxC,QAAgB,EAChB,QAAiC,EACjC,OAA2B,EAC3B,OAAO,GAAG,KAAK;IAEf,IAAI,IAAA,kBAAM,EAAC,gCAAyB,EAAE,QAAQ,CAAC,KAAK,SAAS,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACnF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,YAAY,GAAG,QAAQ,CAAC,SAAS,CACrC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAA,wBAAiB,EAAC,OAAO,CAAC,IAAI,OAAO,CAAC,QAAQ,KAAK,IAAI,CACrE,CAAC;IAEF,IAAI,YAAY,KAAK,CAAC,CAAC,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,kCAAyB,CACjC,GAAG,QAAQ,oDAAoD,QAAQ,CAAC,MAAM,EAAE,CACjF,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,IAAA,oBAAa,EAC3B,QAAQ,CAAC,YAAY,CAAC,EACtB,uCAAuC,CACxC,CAAC;IAEF,IAAI,CAAC,IAAA,wBAAiB,EAAC,OAAO,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,kCAAyB,CAAC,kDAAkD,CAAC,CAAC;IAC1F,CAAC;IAED,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,kBAAkB,CAC9D,OAAO,CAAC,QAAQ,CACjB,CAAC;IAEF,MAAM,SAAS,GAAG,CAAC,MAA6B,EAAE,EAAE,CAClD,4BAA4B,CAC1B,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,MAAM,EACN,OAAO,EACP,OAAO,CACR,CAAC;IAEJ,MAAM,iBAAiB,GAAG,2BAA2B,CAAC,SAAS,CAAC,CAAC;IAEjE,IAAI,iBAAiB,KAAK,SAAS,EAAE,CAAC;QACpC,OAAO,8BAA8B,CACnC,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CACvD,CAAC;IACJ,CAAC;IAED,OAAO,yBAAyB,CAC9B,SAAS,EACT,SAAS,CAAC,UAAU,CAAC,EACrB,SAAS,CAAC,UAAU,CAAC,EACrB,OAAO,CACR,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { PlanExpressionOperand } from "@cerbos/core";
|
|
2
|
+
import type { OperatorOperand } from "./plan";
|
|
3
|
+
/**
|
|
4
|
+
* Parses an RFC 3339 literal into the ISO string Prisma binds. Anything a lenient `Date` parse
|
|
5
|
+
* would coerce into some other instant — a missing time part, a day that does not exist, digits
|
|
6
|
+
* past the millisecond, an instant outside CEL's range — is refused instead.
|
|
7
|
+
*/
|
|
8
|
+
export declare function normalizeRfc3339Milliseconds(value: string): string;
|
|
9
|
+
type ParsedInstant = {
|
|
10
|
+
iso: string;
|
|
11
|
+
subMillisecond: boolean;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Parses an RFC 3339 literal like normalizeRfc3339Milliseconds, except that an instant between
|
|
15
|
+
* two milliseconds is accepted: `iso` is then the NEXT millisecond, and `subMillisecond` says so.
|
|
16
|
+
* A comparison against it has to be rewritten for that rounding (see roundSubMillisecond).
|
|
17
|
+
*/
|
|
18
|
+
export declare function parseRfc3339Instant(value: string): ParsedInstant;
|
|
19
|
+
/**
|
|
20
|
+
* A Prisma `DateTime` carries milliseconds, so the attribute an application builds from one is a
|
|
21
|
+
* whole millisecond `a`, truncated from whatever the column stores. Against an instant `T` strictly
|
|
22
|
+
* between two milliseconds, with `C` the millisecond after it: `a < T` and `a <= T` both mean
|
|
23
|
+
* `column < C`, `a > T` and `a >= T` both mean `column >= C`, and `a == T` never holds. Returns the
|
|
24
|
+
* operator to compare against `C`, or null for the equality family.
|
|
25
|
+
*/
|
|
26
|
+
export declare function roundSubMillisecond(operator: string): string | null;
|
|
27
|
+
/**
|
|
28
|
+
* A comparison over timestamp arithmetic, rewritten as a comparison of the bare `timestamp(x)`
|
|
29
|
+
* against a literal instant, or undefined for any other shape:
|
|
30
|
+
*
|
|
31
|
+
* - `timeSince(timestamp(x)) CMP duration(d)`: timeSince is `now - x`, read from the clock when
|
|
32
|
+
* the query runs, so it holds exactly when `x` lies on the mirrored side of `now - d`. Cerbos
|
|
33
|
+
* computes it with Go's saturating `time.Sub`, which raises no error.
|
|
34
|
+
* - `timestamp(x) ± duration(d) CMP timestamp(t)`: the shift is monotone, so it holds exactly when
|
|
35
|
+
* `x CMP t ∓ d`. CEL raises an error when the shifted instant leaves 0001-01-01..9999-12-31,
|
|
36
|
+
* which the comparison alone cannot carry: `positive` says whether the leaf sits under an even
|
|
37
|
+
* number of negations, and the rows that overflow are then excluded from (positive) or included
|
|
38
|
+
* in (negative) the leaf, so the enclosing negations never select them.
|
|
39
|
+
*
|
|
40
|
+
* Both sides may come in either order. A duration or instant that is not a whole millisecond, or a
|
|
41
|
+
* bound outside CEL's range, is left alone for the translator to refuse.
|
|
42
|
+
*/
|
|
43
|
+
export declare function rewriteTemporalComparison(expr: OperatorOperand, positive: boolean, now?: number): PlanExpressionOperand | undefined;
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=timestamp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timestamp.d.ts","sourceRoot":"","sources":["../src/timestamp.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAS1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAe9C;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUlE;AAED,KAAK,aAAa,GAAG;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAsDhE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAWnE;AAOD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,eAAe,EACrB,QAAQ,EAAE,OAAO,EACjB,GAAG,GAAE,MAAmB,GACvB,qBAAqB,GAAG,SAAS,CA4DnC"}
|