@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.
Files changed (203) hide show
  1. package/README.md +611 -460
  2. package/lib/collections.d.ts +30 -0
  3. package/lib/collections.d.ts.map +1 -0
  4. package/lib/collections.js +421 -0
  5. package/lib/collections.js.map +1 -0
  6. package/lib/comparison.d.ts +24 -0
  7. package/lib/comparison.d.ts.map +1 -0
  8. package/lib/comparison.js +731 -0
  9. package/lib/comparison.js.map +1 -0
  10. package/lib/errors.d.ts +13 -0
  11. package/lib/errors.d.ts.map +1 -0
  12. package/lib/errors.js +17 -0
  13. package/lib/errors.js.map +1 -0
  14. package/lib/evaluate.d.ts +5 -0
  15. package/lib/evaluate.d.ts.map +1 -0
  16. package/lib/evaluate.js +118 -0
  17. package/lib/evaluate.js.map +1 -0
  18. package/lib/fields.d.ts +34 -0
  19. package/lib/fields.d.ts.map +1 -0
  20. package/lib/fields.js +253 -0
  21. package/lib/fields.js.map +1 -0
  22. package/lib/functions.d.ts +5 -0
  23. package/lib/functions.d.ts.map +1 -0
  24. package/lib/functions.js +408 -0
  25. package/lib/functions.js.map +1 -0
  26. package/lib/hierarchy.d.ts +6 -0
  27. package/lib/hierarchy.d.ts.map +1 -0
  28. package/lib/hierarchy.js +266 -0
  29. package/lib/hierarchy.js.map +1 -0
  30. package/lib/index.d.ts +91 -8
  31. package/lib/index.d.ts.map +1 -1
  32. package/lib/index.js +34 -2301
  33. package/lib/index.js.map +1 -1
  34. package/lib/literals.d.ts +20 -0
  35. package/lib/literals.d.ts.map +1 -0
  36. package/lib/literals.js +290 -0
  37. package/lib/literals.js.map +1 -0
  38. package/lib/mapping.d.ts +95 -0
  39. package/lib/mapping.d.ts.map +1 -0
  40. package/lib/mapping.js +316 -0
  41. package/lib/mapping.js.map +1 -0
  42. package/lib/narrowing.d.ts +12 -0
  43. package/lib/narrowing.d.ts.map +1 -0
  44. package/lib/narrowing.js +32 -0
  45. package/lib/narrowing.js.map +1 -0
  46. package/lib/plan.d.ts +49 -0
  47. package/lib/plan.d.ts.map +1 -0
  48. package/lib/plan.js +86 -0
  49. package/lib/plan.js.map +1 -0
  50. package/lib/presence.d.ts +25 -0
  51. package/lib/presence.d.ts.map +1 -0
  52. package/lib/presence.js +82 -0
  53. package/lib/presence.js.map +1 -0
  54. package/lib/regex.d.ts +33 -0
  55. package/lib/regex.d.ts.map +1 -0
  56. package/lib/regex.js +480 -0
  57. package/lib/regex.js.map +1 -0
  58. package/lib/relations.d.ts +58 -0
  59. package/lib/relations.d.ts.map +1 -0
  60. package/lib/relations.js +175 -0
  61. package/lib/relations.js.map +1 -0
  62. package/lib/rewrite.d.ts +36 -0
  63. package/lib/rewrite.d.ts.map +1 -0
  64. package/lib/rewrite.js +366 -0
  65. package/lib/rewrite.js.map +1 -0
  66. package/lib/solve.d.ts +20 -0
  67. package/lib/solve.d.ts.map +1 -0
  68. package/lib/solve.js +77 -0
  69. package/lib/solve.js.map +1 -0
  70. package/lib/strings.d.ts +12 -0
  71. package/lib/strings.d.ts.map +1 -0
  72. package/lib/strings.js +110 -0
  73. package/lib/strings.js.map +1 -0
  74. package/lib/ternary.d.ts +12 -0
  75. package/lib/ternary.d.ts.map +1 -0
  76. package/lib/ternary.js +192 -0
  77. package/lib/ternary.js.map +1 -0
  78. package/lib/timestamp.d.ts +45 -0
  79. package/lib/timestamp.d.ts.map +1 -0
  80. package/lib/timestamp.js +225 -0
  81. package/lib/timestamp.js.map +1 -0
  82. package/lib/translate.d.ts +20 -0
  83. package/lib/translate.d.ts.map +1 -0
  84. package/lib/translate.js +287 -0
  85. package/lib/translate.js.map +1 -0
  86. package/lib/types.d.ts +29 -0
  87. package/lib/types.d.ts.map +1 -0
  88. package/lib/types.js +980 -0
  89. package/lib/types.js.map +1 -0
  90. package/lib/value.d.ts +8 -0
  91. package/lib/value.d.ts.map +1 -0
  92. package/lib/value.js +7 -0
  93. package/lib/value.js.map +1 -0
  94. package/package.json +31 -18
  95. package/src/adversarial.test.ts +488 -488
  96. package/src/collections.ts +738 -0
  97. package/src/comparison.ts +1157 -0
  98. package/src/corpus.ts +597 -0
  99. package/src/errors.ts +12 -0
  100. package/src/evaluate.ts +170 -0
  101. package/src/fields.ts +373 -0
  102. package/src/functions.ts +548 -0
  103. package/src/generated/prisma-adversarial/browser.ts +20 -0
  104. package/src/generated/prisma-adversarial/client.ts +20 -0
  105. package/src/generated/prisma-adversarial/commonInputTypes.ts +116 -127
  106. package/src/generated/prisma-adversarial/internal/class.ts +44 -4
  107. package/src/generated/prisma-adversarial/internal/prismaNamespace.ts +350 -3
  108. package/src/generated/prisma-adversarial/internal/prismaNamespaceBrowser.ts +49 -2
  109. package/src/generated/prisma-adversarial/models/AdversarialBoolListElement.ts +1272 -0
  110. package/src/generated/prisma-adversarial/models/AdversarialInner.ts +1369 -0
  111. package/src/generated/prisma-adversarial/models/AdversarialNumberListElement.ts +1316 -0
  112. package/src/generated/prisma-adversarial/models/AdversarialParent.ts +1474 -0
  113. package/src/generated/prisma-adversarial/models/AdversarialResource.ts +547 -75
  114. package/src/generated/prisma-adversarial/models.ts +4 -0
  115. package/src/generated/prisma-adversarial-mysql/browser.ts +64 -0
  116. package/src/generated/{prisma → prisma-adversarial-mysql}/client.ts +23 -18
  117. package/src/generated/{prisma → prisma-adversarial-mysql}/commonInputTypes.ts +167 -92
  118. package/src/generated/prisma-adversarial-mysql/internal/class.ts +284 -0
  119. package/src/generated/prisma-adversarial-mysql/internal/prismaNamespace.ts +1518 -0
  120. package/src/generated/prisma-adversarial-mysql/internal/prismaNamespaceBrowser.ts +274 -0
  121. package/src/generated/prisma-adversarial-mysql/models/AdversarialBoolListElement.ts +1157 -0
  122. package/src/generated/prisma-adversarial-mysql/models/AdversarialCategory.ts +1286 -0
  123. package/src/generated/prisma-adversarial-mysql/models/AdversarialInner.ts +1247 -0
  124. package/src/generated/prisma-adversarial-mysql/models/AdversarialLabel.ts +1157 -0
  125. package/src/generated/prisma-adversarial-mysql/models/AdversarialNumberListElement.ts +1201 -0
  126. package/src/generated/prisma-adversarial-mysql/models/AdversarialParent.ts +1352 -0
  127. package/src/generated/prisma-adversarial-mysql/models/AdversarialResource.ts +2021 -0
  128. package/src/generated/prisma-adversarial-mysql/models/AdversarialSubCategory.ts +1286 -0
  129. package/src/generated/prisma-adversarial-mysql/models/AdversarialTag.ts +1190 -0
  130. package/src/generated/prisma-adversarial-mysql/models.ts +20 -0
  131. package/src/generated/prisma-adversarial-mysql-v6/index.d.ts +13822 -0
  132. package/src/generated/prisma-adversarial-pg/browser.ts +64 -0
  133. package/src/generated/prisma-adversarial-pg/client.ts +86 -0
  134. package/src/generated/prisma-adversarial-pg/commonInputTypes.ts +345 -0
  135. package/src/generated/prisma-adversarial-pg/enums.ts +15 -0
  136. package/src/generated/prisma-adversarial-pg/internal/class.ts +284 -0
  137. package/src/generated/prisma-adversarial-pg/internal/prismaNamespace.ts +1542 -0
  138. package/src/generated/{prisma → prisma-adversarial-pg}/internal/prismaNamespaceBrowser.ts +72 -43
  139. package/src/generated/prisma-adversarial-pg/models/AdversarialBoolListElement.ts +1275 -0
  140. package/src/generated/prisma-adversarial-pg/models/AdversarialCategory.ts +1404 -0
  141. package/src/generated/prisma-adversarial-pg/models/AdversarialInner.ts +1371 -0
  142. package/src/generated/prisma-adversarial-pg/models/AdversarialLabel.ts +1275 -0
  143. package/src/generated/prisma-adversarial-pg/models/AdversarialNumberListElement.ts +1319 -0
  144. package/src/generated/prisma-adversarial-pg/models/AdversarialParent.ts +1476 -0
  145. package/src/generated/prisma-adversarial-pg/models/AdversarialResource.ts +2139 -0
  146. package/src/generated/prisma-adversarial-pg/models/AdversarialSubCategory.ts +1404 -0
  147. package/src/generated/prisma-adversarial-pg/models/AdversarialTag.ts +1310 -0
  148. package/src/generated/prisma-adversarial-pg/models.ts +20 -0
  149. package/src/generated/prisma-adversarial-pg-v6/client.d.ts +1 -0
  150. package/src/generated/prisma-adversarial-pg-v6/default.d.ts +1 -0
  151. package/src/generated/prisma-adversarial-pg-v6/edge.d.ts +1 -0
  152. package/src/generated/prisma-adversarial-pg-v6/index.d.ts +14918 -0
  153. package/src/generated/prisma-adversarial-pg-v6/runtime/index-browser.d.ts +370 -0
  154. package/src/generated/prisma-adversarial-pg-v6/runtime/library.d.ts +3982 -0
  155. package/src/generated/prisma-adversarial-pg-v6/wasm.d.ts +1 -0
  156. package/src/generated/prisma-adversarial-v6/index.d.ts +6515 -304
  157. package/src/hierarchy.ts +405 -0
  158. package/src/index.ts +134 -3325
  159. package/src/literals.ts +363 -0
  160. package/src/mapping.ts +474 -0
  161. package/src/narrowing.ts +33 -0
  162. package/src/plan.ts +125 -0
  163. package/src/presence.ts +114 -0
  164. package/src/regex.ts +596 -0
  165. package/src/relations.ts +226 -0
  166. package/src/rewrite.ts +524 -0
  167. package/src/solve.ts +96 -0
  168. package/src/strings.ts +152 -0
  169. package/src/ternary.ts +359 -0
  170. package/src/test-setup.adversarial-url.ts +21 -0
  171. package/src/test-setup.adversarial.mysql.v6.ts +13 -0
  172. package/src/test-setup.adversarial.mysql.v7.ts +12 -0
  173. package/src/test-setup.adversarial.pg.v6.ts +13 -0
  174. package/src/test-setup.adversarial.pg.v7.ts +9 -0
  175. package/src/test-setup.adversarial.v7.ts +1 -0
  176. package/src/timestamp.ts +308 -0
  177. package/src/translate.ts +419 -0
  178. package/src/translator.test.ts +766 -0
  179. package/src/types.ts +1310 -0
  180. package/src/value.ts +16 -0
  181. package/src/generated/prisma/browser.ts +0 -59
  182. package/src/generated/prisma/internal/class.ts +0 -274
  183. package/src/generated/prisma/internal/prismaNamespace.ts +0 -1403
  184. package/src/generated/prisma/models/Category.ts +0 -1412
  185. package/src/generated/prisma/models/Label.ts +0 -1276
  186. package/src/generated/prisma/models/NestedResource.ts +0 -1562
  187. package/src/generated/prisma/models/NextLevelNestedResource.ts +0 -1337
  188. package/src/generated/prisma/models/Resource.ts +0 -2196
  189. package/src/generated/prisma/models/SubCategory.ts +0 -1412
  190. package/src/generated/prisma/models/Tag.ts +0 -1276
  191. package/src/generated/prisma/models/User.ts +0 -1503
  192. package/src/generated/prisma/models.ts +0 -19
  193. package/src/generated/prisma-v6/index.d.ts +0 -13726
  194. package/src/index.test.ts +0 -8885
  195. package/src/test-setup.v6.ts +0 -5
  196. package/src/test-setup.v7.ts +0 -7
  197. /package/src/generated/{prisma → prisma-adversarial-mysql}/enums.ts +0 -0
  198. /package/src/generated/{prisma-v6 → prisma-adversarial-mysql-v6}/client.d.ts +0 -0
  199. /package/src/generated/{prisma-v6 → prisma-adversarial-mysql-v6}/default.d.ts +0 -0
  200. /package/src/generated/{prisma-v6 → prisma-adversarial-mysql-v6}/edge.d.ts +0 -0
  201. /package/src/generated/{prisma-v6 → prisma-adversarial-mysql-v6}/runtime/index-browser.d.ts +0 -0
  202. /package/src/generated/{prisma-v6 → prisma-adversarial-mysql-v6}/runtime/library.d.ts +0 -0
  203. /package/src/generated/{prisma-v6 → prisma-adversarial-mysql-v6}/wasm.d.ts +0 -0
@@ -0,0 +1,266 @@
1
+ "use strict";
2
+ // The hierarchy operators: `overlaps`, `ancestorOf`, `descendentOf` over `hierarchy(...)`
3
+ // operands, lowered to equality, IN-lists of strict prefixes, and a prefix match on a column.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.handleOverlapsOperator = handleOverlapsOperator;
6
+ exports.handleAncestorDescendantOperator = handleAncestorDescendantOperator;
7
+ const fields_1 = require("./fields");
8
+ const mapping_1 = require("./mapping");
9
+ const plan_1 = require("./plan");
10
+ const translate_1 = require("./translate");
11
+ const errors_1 = require("./errors");
12
+ function resolveHierarchy(expr, context) {
13
+ const operands = expr.operands;
14
+ if (operands.length === 2) {
15
+ const strOperand = (0, plan_1.assertDefined)(operands[0], "hierarchy requires operands");
16
+ const delimOperand = (0, plan_1.assertDefined)(operands[1], "hierarchy requires a delimiter");
17
+ if (!(0, plan_1.isValueOperand)(delimOperand)) {
18
+ throw new errors_1.UnsupportedQueryPlanError("hierarchy delimiter must be a value");
19
+ }
20
+ const delimiter = String(delimOperand.value);
21
+ if ((0, plan_1.isValueOperand)(strOperand)) {
22
+ return {
23
+ type: "constant",
24
+ segments: splitPath(String(strOperand.value), delimiter),
25
+ };
26
+ }
27
+ if ((0, plan_1.isNamedOperand)(strOperand)) {
28
+ return {
29
+ type: "field",
30
+ fieldRef: (0, mapping_1.resolveFieldReference)(strOperand.name, context),
31
+ delimiter,
32
+ };
33
+ }
34
+ throw new errors_1.UnsupportedQueryPlanError("hierarchy(string, delimiter) requires a value or field operand");
35
+ }
36
+ if (operands.length === 1) {
37
+ const inner = (0, plan_1.assertDefined)(operands[0], "hierarchy requires an operand");
38
+ if ((0, plan_1.isValueOperand)(inner)) {
39
+ return { type: "constant", segments: String(inner.value).split(".") };
40
+ }
41
+ if ((0, plan_1.isNamedOperand)(inner)) {
42
+ return {
43
+ type: "field",
44
+ fieldRef: (0, mapping_1.resolveFieldReference)(inner.name, context),
45
+ delimiter: ".",
46
+ };
47
+ }
48
+ if ((0, plan_1.isOperatorOperand)(inner) && inner.operator === "list") {
49
+ const segments = inner.operands.map((op) => {
50
+ const resolved = (0, translate_1.resolveOperand)(op, context);
51
+ if ((0, mapping_1.isResolvedValue)(resolved)) {
52
+ return { type: "constant", value: String(resolved.value) };
53
+ }
54
+ return { type: "field", fieldRef: resolved };
55
+ });
56
+ return { type: "segmented", segments };
57
+ }
58
+ throw new errors_1.UnsupportedQueryPlanError("hierarchy requires a value, field, or list operand");
59
+ }
60
+ throw new errors_1.UnsupportedQueryPlanError("hierarchy requires 1 or 2 operands");
61
+ }
62
+ /**
63
+ * Cerbos splits a path with Go's `strings.Split`: an empty delimiter yields one segment per code
64
+ * point, and an empty path then has no segments at all.
65
+ */
66
+ function splitPath(path, delimiter) {
67
+ return delimiter === "" ? Array.from(path) : path.split(delimiter);
68
+ }
69
+ function toSegments(resolved) {
70
+ switch (resolved.type) {
71
+ case "constant":
72
+ return resolved.segments.map((s) => ({ type: "constant", value: s }));
73
+ case "segmented":
74
+ return resolved.segments;
75
+ case "field":
76
+ throw new errors_1.UnsupportedQueryPlanError("Cannot get segments from a field-reference hierarchy");
77
+ }
78
+ }
79
+ /** A segmented hierarchy whose segments are all constants is a constant hierarchy. */
80
+ function normalizeHierarchy(h) {
81
+ if (h.type !== "segmented")
82
+ return h;
83
+ const constants = [];
84
+ for (const segment of h.segments) {
85
+ if (segment.type !== "constant")
86
+ return h;
87
+ constants.push(segment.value);
88
+ }
89
+ return { type: "constant", segments: constants };
90
+ }
91
+ function checkPrefixConditions(shorter, longer) {
92
+ if (shorter.length > longer.length)
93
+ return null;
94
+ const conditions = [];
95
+ for (let i = 0; i < shorter.length; i++) {
96
+ const s = shorter[i];
97
+ const l = longer[i];
98
+ if (s.type === "constant" && l.type === "constant") {
99
+ if (s.value !== l.value)
100
+ return null;
101
+ }
102
+ else if (s.type === "field" && l.type === "constant") {
103
+ conditions.push((0, fields_1.buildFieldFilter)(s.fieldRef, "equals", l.value));
104
+ }
105
+ else if (s.type === "constant" && l.type === "field") {
106
+ conditions.push((0, fields_1.buildFieldFilter)(l.fieldRef, "equals", s.value));
107
+ }
108
+ else {
109
+ throw new errors_1.UnsupportedQueryPlanError("Cannot compare two field references in hierarchy overlap");
110
+ }
111
+ }
112
+ if (conditions.length === 0)
113
+ return {};
114
+ if (conditions.length === 1)
115
+ return conditions[0];
116
+ return { AND: conditions };
117
+ }
118
+ function handleOverlapsOperator(operands, context) {
119
+ const [left, right] = extractHierarchyOperands("overlaps", operands, context);
120
+ if (left.type === "field" || right.type === "field") {
121
+ return handleFieldOverlaps(left, right);
122
+ }
123
+ const leftSegs = toSegments(left);
124
+ const rightSegs = toSegments(right);
125
+ const leftPrefixOfRight = checkPrefixConditions(leftSegs, rightSegs);
126
+ const rightPrefixOfLeft = checkPrefixConditions(rightSegs, leftSegs);
127
+ const validConditions = [leftPrefixOfRight, rightPrefixOfLeft].filter((c) => c !== null);
128
+ // Hierarchy construction evaluates every segment, including a trailing segment that
129
+ // neither prefix comparison needs. Preserve its SQL UNKNOWN under outer negation too.
130
+ const fields = [...leftSegs, ...rightSegs]
131
+ .filter((segment) => segment.type === "field")
132
+ .filter((segment) => segment.fieldRef.nullable !== false);
133
+ const pairs = fields.map(({ fieldRef }) => ({
134
+ equal: (0, fields_1.buildFieldFilter)(fieldRef, "equals", ""),
135
+ unequal: (0, fields_1.buildFieldFilter)(fieldRef, "not", ""),
136
+ }));
137
+ const presence = pairs.map(({ equal, unequal }) => ({
138
+ OR: [equal, unequal],
139
+ }));
140
+ const unknown = pairs.map(({ equal, unequal }) => ({
141
+ AND: [equal, unequal],
142
+ }));
143
+ if (validConditions.length === 0) {
144
+ if (unknown.length > 0)
145
+ return { OR: unknown };
146
+ const field = [...leftSegs, ...rightSegs].find((segment) => segment.type === "field");
147
+ if (field)
148
+ return (0, fields_1.buildImpossibleFilter)(field.fieldRef);
149
+ throw new errors_1.UnsupportedQueryPlanError("Cannot determine overlap: no field references found");
150
+ }
151
+ if (validConditions.some((condition) => Object.keys(condition).length === 0)) {
152
+ return presence.length === 0 ? {} : { AND: presence };
153
+ }
154
+ // Equal-length comparisons are identical in either direction. A contradiction is
155
+ // FALSE for a present field and UNKNOWN for NULL, restoring errors even if the
156
+ // prefix comparison is FALSE (FALSE AND NULL alone would lose that error).
157
+ const condition = validConditions[0];
158
+ return presence.length === 0
159
+ ? condition
160
+ : {
161
+ OR: [{ AND: [condition, ...presence] }, ...unknown],
162
+ };
163
+ }
164
+ function handleFieldOverlaps(left, right) {
165
+ if (left.type === "field" && right.type === "field") {
166
+ throw new errors_1.UnsupportedQueryPlanError("overlaps: cannot compare two field-reference hierarchies");
167
+ }
168
+ // The caller routes here only when at least one side is a field hierarchy.
169
+ const field = left.type === "field" ? left : right.type === "field" ? right : undefined;
170
+ if (field === undefined) {
171
+ throw new errors_1.UnsupportedQueryPlanError("overlaps: neither side is a field-reference hierarchy");
172
+ }
173
+ const other = field === left ? right : left;
174
+ if (other.type !== "constant") {
175
+ throw new errors_1.UnsupportedQueryPlanError("overlaps: segmented hierarchies with field hierarchies are not supported");
176
+ }
177
+ const delimiter = field.delimiter;
178
+ const otherRaw = other.segments.join(delimiter);
179
+ const strictPrefixes = getStrictPrefixes(other.segments, delimiter);
180
+ const conditions = [];
181
+ if (strictPrefixes.length > 0) {
182
+ conditions.push((0, fields_1.buildFieldFilter)(field.fieldRef, "in", strictPrefixes));
183
+ }
184
+ conditions.push((0, fields_1.buildFieldFilter)(field.fieldRef, "equals", otherRaw));
185
+ conditions.push((0, fields_1.buildPrefixFilter)(field.fieldRef, otherRaw + delimiter));
186
+ return { OR: conditions };
187
+ }
188
+ function extractHierarchyOperands(operatorName, operands, context) {
189
+ if (operands.length !== 2) {
190
+ throw new errors_1.UnsupportedQueryPlanError(`${operatorName} requires exactly two operands`);
191
+ }
192
+ const leftOp = (0, plan_1.assertDefined)(operands[0], `${operatorName} requires a left operand`);
193
+ const rightOp = (0, plan_1.assertDefined)(operands[1], `${operatorName} requires a right operand`);
194
+ if (!(0, plan_1.isOperatorOperand)(leftOp) || leftOp.operator !== "hierarchy" ||
195
+ !(0, plan_1.isOperatorOperand)(rightOp) || rightOp.operator !== "hierarchy") {
196
+ throw new errors_1.UnsupportedQueryPlanError(`${operatorName} requires two hierarchy operands`);
197
+ }
198
+ return [
199
+ normalizeHierarchy(resolveHierarchy(leftOp, context)),
200
+ normalizeHierarchy(resolveHierarchy(rightOp, context)),
201
+ ];
202
+ }
203
+ function getStrictPrefixes(segments, delimiter) {
204
+ if (delimiter === "") {
205
+ // Per code point, the empty path is itself a (zero-segment) strict prefix.
206
+ return segments.map((_, length) => segments.slice(0, length).join(""));
207
+ }
208
+ if (segments.length <= 1)
209
+ return [];
210
+ const prefixes = [];
211
+ let current = segments[0];
212
+ prefixes.push(current);
213
+ for (let i = 1; i < segments.length - 1; i++) {
214
+ current = current + delimiter + segments[i];
215
+ prefixes.push(current);
216
+ }
217
+ return prefixes;
218
+ }
219
+ function handleAncestorDescendantOperator(operands, context, direction) {
220
+ const operatorName = direction === "ancestor" ? "ancestorOf" : "descendentOf";
221
+ const [left, right] = extractHierarchyOperands(operatorName, operands, context);
222
+ // ancestorOf(A, B) = A is strict prefix of B
223
+ // descendentOf(A, B) = B is strict prefix of A
224
+ const ancestor = direction === "ancestor" ? left : right;
225
+ const descendant = direction === "ancestor" ? right : left;
226
+ if (ancestor.type === "field")
227
+ (0, fields_1.assertStringField)(ancestor.fieldRef, operatorName);
228
+ if (descendant.type === "field")
229
+ (0, fields_1.assertStringField)(descendant.fieldRef, operatorName);
230
+ if (ancestor.type === "constant" && descendant.type === "field") {
231
+ if (descendant.delimiter === "") {
232
+ // Per code point, a descendant is the ancestor followed by at least one more character.
233
+ return (0, fields_1.buildPrefixFilter)(descendant.fieldRef, ancestor.segments.join(""), true);
234
+ }
235
+ return (0, fields_1.buildPrefixFilter)(descendant.fieldRef, ancestor.segments.join(descendant.delimiter) + descendant.delimiter);
236
+ }
237
+ if (ancestor.type === "field" && descendant.type === "constant") {
238
+ const delimiter = ancestor.delimiter;
239
+ const prefixes = getStrictPrefixes(descendant.segments, delimiter);
240
+ if (prefixes.length === 0) {
241
+ if (ancestor.fieldRef.nullable === false)
242
+ return (0, fields_1.buildImpossibleFilter)(ancestor.fieldRef);
243
+ return {
244
+ AND: [
245
+ (0, fields_1.buildFieldFilter)(ancestor.fieldRef, "equals", ""),
246
+ (0, fields_1.buildFieldFilter)(ancestor.fieldRef, "not", ""),
247
+ ],
248
+ };
249
+ }
250
+ if (prefixes.length === 1) {
251
+ return (0, fields_1.buildFieldFilter)(ancestor.fieldRef, "equals", prefixes[0]);
252
+ }
253
+ return (0, fields_1.buildFieldFilter)(ancestor.fieldRef, "in", prefixes);
254
+ }
255
+ if (ancestor.type === "constant" && descendant.type === "constant") {
256
+ const ancestorSegs = ancestor.segments;
257
+ const descendantSegs = descendant.segments;
258
+ if (descendantSegs.length > ancestorSegs.length &&
259
+ ancestorSegs.every((seg, i) => seg === descendantSegs[i])) {
260
+ return {};
261
+ }
262
+ throw new errors_1.UnsupportedQueryPlanError(`${operatorName}: constants do not satisfy ${direction} relationship`);
263
+ }
264
+ throw new errors_1.UnsupportedQueryPlanError(`${operatorName}: unsupported hierarchy type combination`);
265
+ }
266
+ //# sourceMappingURL=hierarchy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hierarchy.js","sourceRoot":"","sources":["../src/hierarchy.ts"],"names":[],"mappings":"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"}
package/lib/index.d.ts CHANGED
@@ -1,23 +1,59 @@
1
1
  import { PlanKind } from "@cerbos/core";
2
2
  import type { PlanResourcesResponse } from "@cerbos/core";
3
- export { PlanKind };
4
- export type PrismaFilter = Record<string, any>;
3
+ import { UnsupportedQueryPlanError } from "./errors";
4
+ import type { PrismaFilter } from "./value";
5
+ export { PlanKind, UnsupportedQueryPlanError };
6
+ export type { PrismaFilter, PrismaValue } from "./value";
5
7
  export type MapperConfig = {
6
8
  field?: string;
7
9
  /**
8
- * Declares the database value kind when the Cerbos expression wraps a field in a typed
9
- * constructor. Date-time metadata is required for timestamp(field) so a string column is
10
- * never silently treated as a temporal column merely because it happens to contain ISO text.
10
+ * Declares the Prisma scalar kind so incompatible operands are rejected before query
11
+ * execution. Undeclared scalar kinds preserve the historical behavior. Date-time metadata
12
+ * is required for timestamp(field); raw DateTime column comparisons lose lexical spelling.
11
13
  */
12
- valueType?: "dateTime";
14
+ valueType?: "dateTime" | "string" | "number" | "boolean";
13
15
  /**
14
16
  * Marks the mapped column as nullable in the database. Cerbos treats a missing attribute as
15
17
  * an evaluation error (deny), which matches SQL three-valued logic for simple predicates —
16
18
  * but relation subqueries (some/every/none) collapse UNKNOWN to false at the EXISTS boundary,
17
19
  * so collection macros over elements with NULL fields need an explicit guard to stay
18
- * deny-aligned. Declaring nullability here enables those guards.
20
+ * deny-aligned. An element column is treated as nullable unless this says `false`, because
21
+ * the unguarded filter is the one that over-grants; declare `nullable: false` on every required
22
+ * element column, since Prisma rejects a `null` comparison against one. Scalar hierarchy
23
+ * segments likewise preserve missing-value errors unless nullable: false declares that a
24
+ * segment cannot be NULL.
19
25
  */
20
26
  nullable?: boolean;
27
+ /**
28
+ * Declares that this column can be SQL NULL **and** how the caller represents that NULL in the
29
+ * attributes it sends to `check()`. Declaring it asserts both facts; leaving it undeclared means
30
+ * "treat this column as NOT NULL", which is the historical rendering.
31
+ *
32
+ * This is per attribute rather than per call because one policy suite can legitimately mix the
33
+ * two conventions — the same column can be mapped twice, sent as an explicit null under one
34
+ * attribute name and omitted under another. The call-level option cannot express that, which is
35
+ * what made cerbos/query-plan-adapters#308 unfixable with #302's option alone.
36
+ *
37
+ * - `"explicit"` — a NULL column is sent as an explicit `null` attribute, so CEL holds a null
38
+ * VALUE. `null != "x"` is then TRUE and `null == "x"` is FALSE, both definite, while Prisma's
39
+ * `{ not: "x" }` drops the row under both polarities. The equality family (`equals`, `not`,
40
+ * `in`) is therefore rendered so it can never depend on SQL's UNKNOWN.
41
+ * - `"omitted"` — a NULL column sends no attribute, so CEL raises a missing-attribute error and
42
+ * `check()` denies. Dropping the row is already right, so the rendering is unchanged; what the
43
+ * declaration adds is the same null-operand rejection the call-level `"omitted"` performs,
44
+ * scoped to this attribute.
45
+ *
46
+ * Only the equality family is affected. `lt`/`lte`/`gt`/`gte` and the string operators raise a
47
+ * no-overload error on a null receiver in CEL, which denies under both polarities exactly as a
48
+ * dropped row does, so they are left alone.
49
+ *
50
+ * Distinct from `nullable` above, which declares whether a *relation element* column can be NULL so
51
+ * collection macros gain their three-valued guards. The two are independent: `nullable` is about
52
+ * what a subquery does with an UNKNOWN element, this is about what the caller sent to the PDP.
53
+ *
54
+ * See https://github.com/cerbos/query-plan-adapters/issues/308.
55
+ */
56
+ nullAttributeRepresentation?: NullAttributeRepresentation;
21
57
  relation?: {
22
58
  name: string;
23
59
  type: "one" | "many";
@@ -29,9 +65,51 @@ export type MapperConfig = {
29
65
  model?: string;
30
66
  field?: string;
31
67
  fields?: Record<string, MapperConfig>;
68
+ /**
69
+ * The predicate the application itself applies when it reads this relation — a soft-delete
70
+ * flag, a tenant column, a subtype discriminator, whatever narrows the rows that became the
71
+ * resource attributes.
72
+ *
73
+ * Prisma has no schema-level filtered relation. A `where` injected by a client extension or
74
+ * middleware rewrites the *top-level* query, never the nested `some`/`every`/`none` this
75
+ * adapter generates, so a narrowing the application applies to its own reads does not reach
76
+ * the subquery — and the subquery then matches records the application never serialised, a
77
+ * filter that returns rows the PDP denies. Declaring the predicate here restores the
78
+ * equality; the adapter cannot detect the omission, which is why the field is optional and
79
+ * silence is not a warning. See "Mapping hazards" in the README.
80
+ *
81
+ * It is a Prisma where-input over the RELATED model, ANDed into the nested filter, and it
82
+ * constrains every operator reached through this relation under both polarities. `every` is
83
+ * rewritten to the equivalent `none` so the restriction narrows the records examined rather
84
+ * than the records required to match.
85
+ *
86
+ * ```ts
87
+ * relation: { name: "tags", type: "many", subqueryFilter: { deletedAt: null } }
88
+ * ```
89
+ */
90
+ subqueryFilter?: PrismaFilter;
32
91
  };
33
92
  };
34
93
  export type Mapper = Record<string, MapperConfig> | ((key: string) => MapperConfig);
94
+ /**
95
+ * How the caller represents a NULL column when building the attributes it sends to `check()`.
96
+ *
97
+ * The planner emits the same `eq(attr, null)` node either way, so the plan cannot reveal which
98
+ * convention is in use and the adapter has to be told.
99
+ *
100
+ * - `"explicit"` — a NULL column is sent as an explicit `null` attribute. CEL compares
101
+ * `null == null`, so `IS NULL` selects exactly the rows `check()` allows.
102
+ * - `"omitted"` (default) — a NULL column sends no attribute at all. CEL then raises a
103
+ * missing-attribute error, which Cerbos treats as a deny, so a filter that *selects* NULL rows returns rows the
104
+ * PDP denies. A null comparison operand is never translated into a NULL-selecting filter.
105
+ *
106
+ * The default is the convention whose wrong guess fails closed: a caller that actually sends
107
+ * explicit nulls loses the NULL rows, never gains rows the PDP denies
108
+ * (docs/adr/0011-denial-fails-closed-in-the-result.md).
109
+ *
110
+ * See https://github.com/cerbos/query-plan-adapters/issues/302.
111
+ */
112
+ export type NullAttributeRepresentation = "explicit" | "omitted";
35
113
  export interface QueryPlanToPrismaArgs {
36
114
  queryPlan: PlanResourcesResponse;
37
115
  mapper?: Mapper;
@@ -41,6 +119,11 @@ export interface QueryPlanToPrismaArgs {
41
119
  * references and need the model name as their container.
42
120
  */
43
121
  model?: string;
122
+ /**
123
+ * Which NULL-column representation the caller uses when building `check()` attributes.
124
+ * Defaults to `"omitted"`, which never selects NULL rows for an undeclared attribute.
125
+ */
126
+ nullAttributeRepresentation?: NullAttributeRepresentation;
44
127
  }
45
128
  export type QueryPlanToPrismaResult = {
46
129
  kind: PlanKind.ALWAYS_ALLOWED | PlanKind.ALWAYS_DENIED;
@@ -51,5 +134,5 @@ export type QueryPlanToPrismaResult = {
51
134
  /**
52
135
  * Converts a Cerbos query plan to a Prisma filter.
53
136
  */
54
- export declare function queryPlanToPrisma({ queryPlan, mapper, model, }: QueryPlanToPrismaArgs): QueryPlanToPrismaResult;
137
+ export declare function queryPlanToPrisma({ queryPlan, mapper, model, nullAttributeRepresentation, }: QueryPlanToPrismaArgs): QueryPlanToPrismaResult;
55
138
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,KAAK,EACV,qBAAqB,EAGtB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,QAAQ,EAAE,CAAC;AAqGpB,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAE/C,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,SAAS,CAAC,EAAE,UAAU,CAAC;IACvB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,KAAK,GAAG,MAAM,CAAC;QACrB;;;;WAIG;QACH,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;KACvC,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,MAAM,GACd,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAC5B,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,YAAY,CAAC,CAAC;AAEpC,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,qBAAqB,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,uBAAuB,GAC/B;IACE,IAAI,EAAE,QAAQ,CAAC,cAAc,GAAG,QAAQ,CAAC,aAAa,CAAC;CACxD,GACD;IACE,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC;IAC3B,OAAO,EAAE,YAAY,CAAC;CACvB,CAAC;AAoZN;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,MAAW,EACX,KAAK,GACN,EAAE,qBAAqB,GAAG,uBAAuB,CAgCjD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAW1D,OAAO,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,EAAE,QAAQ,EAAE,yBAAyB,EAAE,CAAC;AAE/C,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEzD,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,SAAS,CAAC,EAAE,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IACzD;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACH,2BAA2B,CAAC,EAAE,2BAA2B,CAAC;IAC1D,QAAQ,CAAC,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,KAAK,GAAG,MAAM,CAAC;QACrB;;;;WAIG;QACH,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QACtC;;;;;;;;;;;;;;;;;;;;;WAqBG;QACH,cAAc,CAAC,EAAE,YAAY,CAAC;KAC/B,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,MAAM,GACd,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAC5B,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,YAAY,CAAC,CAAC;AAEpC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,2BAA2B,GAAG,UAAU,GAAG,SAAS,CAAC;AAEjE,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,qBAAqB,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,2BAA2B,CAAC,EAAE,2BAA2B,CAAC;CAC3D;AAED,MAAM,MAAM,uBAAuB,GAC/B;IACE,IAAI,EAAE,QAAQ,CAAC,cAAc,GAAG,QAAQ,CAAC,aAAa,CAAC;CACxD,GACD;IACE,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC;IAC3B,OAAO,EAAE,YAAY,CAAC;CACvB,CAAC;AAEN;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,MAAW,EACX,KAAK,EACL,2BAAuC,GACxC,EAAE,qBAAqB,GAAG,uBAAuB,CAoDjD"}