@nmnmcc/ability 2.0.6 → 2.1.1

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 (89) hide show
  1. package/README.md +56 -32
  2. package/dist/Authorizer.d.ts +21 -12
  3. package/dist/Authorizer.d.ts.map +1 -1
  4. package/dist/Authorizer.js.map +1 -1
  5. package/dist/Condition.d.ts +118 -18
  6. package/dist/Condition.d.ts.map +1 -1
  7. package/dist/Condition.js +27 -18
  8. package/dist/Condition.js.map +1 -1
  9. package/dist/Domain.d.ts +9 -0
  10. package/dist/Domain.d.ts.map +1 -1
  11. package/dist/Domain.js +5 -0
  12. package/dist/Domain.js.map +1 -1
  13. package/dist/Limits.d.ts +44 -13
  14. package/dist/Limits.d.ts.map +1 -1
  15. package/dist/Limits.js +52 -22
  16. package/dist/Limits.js.map +1 -1
  17. package/dist/Policy.d.ts +95 -12
  18. package/dist/Policy.d.ts.map +1 -1
  19. package/dist/Policy.js.map +1 -1
  20. package/dist/index.d.ts +1 -1
  21. package/dist/internal/algebra.js +101 -74
  22. package/dist/internal/algebra.js.map +1 -1
  23. package/dist/internal/analysis.js +81 -75
  24. package/dist/internal/analysis.js.map +1 -1
  25. package/dist/internal/authorizer.d.ts.map +1 -1
  26. package/dist/internal/authorizer.js +16 -11
  27. package/dist/internal/authorizer.js.map +1 -1
  28. package/dist/internal/bind.js +119 -80
  29. package/dist/internal/bind.js.map +1 -1
  30. package/dist/internal/catalog.d.ts +33 -10
  31. package/dist/internal/catalog.d.ts.map +1 -1
  32. package/dist/internal/catalog.js +153 -78
  33. package/dist/internal/catalog.js.map +1 -1
  34. package/dist/internal/decide.js +25 -29
  35. package/dist/internal/decide.js.map +1 -1
  36. package/dist/internal/domain.js +19 -5
  37. package/dist/internal/domain.js.map +1 -1
  38. package/dist/internal/json.js +120 -76
  39. package/dist/internal/json.js.map +1 -1
  40. package/dist/internal/limits.d.ts +28 -0
  41. package/dist/internal/limits.d.ts.map +1 -1
  42. package/dist/internal/limits.js +75 -16
  43. package/dist/internal/limits.js.map +1 -1
  44. package/dist/internal/nodes.d.ts +7 -0
  45. package/dist/internal/nodes.d.ts.map +1 -1
  46. package/dist/internal/nodes.js +86 -47
  47. package/dist/internal/nodes.js.map +1 -1
  48. package/dist/internal/patterns.js +50 -15
  49. package/dist/internal/patterns.js.map +1 -1
  50. package/dist/internal/policy-json.js +169 -127
  51. package/dist/internal/policy-json.js.map +1 -1
  52. package/dist/internal/policy-nodes.d.ts.map +1 -1
  53. package/dist/internal/policy-nodes.js +17 -14
  54. package/dist/internal/policy-nodes.js.map +1 -1
  55. package/dist/internal/policy.d.ts.map +1 -1
  56. package/dist/internal/policy.js +38 -22
  57. package/dist/internal/policy.js.map +1 -1
  58. package/dist/internal/resource.js +1 -1
  59. package/dist/internal/rule.d.ts.map +1 -1
  60. package/dist/internal/rule.js +6 -5
  61. package/dist/internal/rule.js.map +1 -1
  62. package/dist/internal/search.d.ts.map +1 -1
  63. package/dist/internal/search.js +106 -92
  64. package/dist/internal/search.js.map +1 -1
  65. package/dist/internal/trampoline.js +89 -0
  66. package/dist/internal/trampoline.js.map +1 -0
  67. package/package.json +1 -1
  68. package/src/Authorizer.ts +30 -20
  69. package/src/Condition.ts +308 -83
  70. package/src/Domain.ts +9 -0
  71. package/src/Limits.ts +69 -29
  72. package/src/Policy.ts +131 -15
  73. package/src/internal/algebra.ts +218 -135
  74. package/src/internal/analysis.ts +154 -122
  75. package/src/internal/authorizer.ts +34 -16
  76. package/src/internal/bind.ts +279 -148
  77. package/src/internal/catalog.ts +307 -133
  78. package/src/internal/decide.ts +58 -49
  79. package/src/internal/domain.ts +39 -3
  80. package/src/internal/json.ts +212 -117
  81. package/src/internal/limits.ts +101 -31
  82. package/src/internal/nodes.ts +101 -59
  83. package/src/internal/patterns.ts +72 -26
  84. package/src/internal/policy-json.ts +266 -197
  85. package/src/internal/policy-nodes.ts +33 -24
  86. package/src/internal/policy.ts +63 -23
  87. package/src/internal/rule.ts +16 -3
  88. package/src/internal/search.ts +186 -136
  89. package/src/internal/trampoline.ts +194 -0
@@ -1,16 +1,18 @@
1
+ import { loop, run, toEffect } from "./trampoline.js";
1
2
  import { And, Compare, In, Not, Or, Predicate, isScalar, literal, nodes_exports, runOf } from "./nodes.js";
2
3
  import { readPath } from "./read.js";
3
- import * as Effect from "effect/Effect";
4
4
  import * as Arr from "effect/Array";
5
+ import * as Effect from "effect/Effect";
5
6
  import * as Option from "effect/Option";
6
7
  // src/internal/algebra.ts
7
8
  /**
8
9
  * The work on condition nodes: smart constructors, simplification, the step
9
10
  * that puts the principal in, tests on a value, and folds.
10
11
  *
11
- * The constructors of the nodes keep each condition small and low, so each
12
- * walk here is a plain walk with no memo. A shared child is walked again for
13
- * each place, and the limits of the nodes keep that work small.
12
+ * The constructors of the nodes keep each condition small, so each walk here
13
+ * has no memo. A shared child is walked again for each place, and the limits
14
+ * of the nodes keep that work small. A walk takes the steps of a trampoline,
15
+ * so a deep condition does not fill the stack: see `Trampoline`.
14
16
  */
15
17
  const { always, never } = nodes_exports;
16
18
  /** The text of an operand. The type is in it, so `"1"` is not `1`. */
@@ -158,16 +160,24 @@ const not = (child) => {
158
160
  default: return new Not(child);
159
161
  }
160
162
  };
163
+ /** The children of a node, each walked by `go` as a step of `R`. */
164
+ const eachChild = (R, children, go) => R.forEach(children, (child) => R.suspend(() => go(child)));
161
165
  /** Makes a condition simple, from its leaves up. */
162
- const simplify = (node) => {
163
- switch (node._tag) {
164
- case "And":
165
- case "Or": return junction(node._tag, Arr.map(node.conditions, simplify));
166
- case "Not": return node.condition.pipe(simplify, not);
167
- case "In": return node.values.length === 0 ? never : node;
168
- default: return node;
169
- }
170
- };
166
+ const simplify = (node) => run(node.depth, (R) => {
167
+ const go = (current) => {
168
+ switch (current._tag) {
169
+ case "And":
170
+ case "Or": {
171
+ const tag = current._tag;
172
+ return R.map(eachChild(R, current.conditions, go), (children) => junction(tag, children));
173
+ }
174
+ case "Not": return R.map(R.suspend(() => go(current.condition)), not);
175
+ case "In": return R.succeed(current.values.length === 0 ? never : current);
176
+ default: return R.succeed(current);
177
+ }
178
+ };
179
+ return go(node);
180
+ });
171
181
  /**
172
182
  * Gets a field of a value by a path with dots. It reads only plain data: see
173
183
  * `readPart`. A missing field, or a field under a value that is not an object,
@@ -213,35 +223,46 @@ const testUnder = (prefix, input) => {
213
223
  return value !== void 0 && value === values[index];
214
224
  });
215
225
  };
216
- /** Tests a simple condition with no predicate on a value. */
217
- const testSync = (node, input) => {
218
- switch (node._tag) {
219
- case "True": return true;
220
- case "False": return false;
221
- case "Compare": return testCompare(node.op, getField(input.value, node.field), resolve(node.value, input.principal));
222
- case "In": {
223
- const field = getField(input.value, node.field);
224
- return node.values.some((operand) => resolve(operand, input.principal) === field);
226
+ /**
227
+ * The test of a simple condition with no predicate on a value, as a walk.
228
+ * The children of `And` and `Or` run in order, and they stop at the first
229
+ * child that gives the answer.
230
+ */
231
+ const testWith = (input) => (R) => {
232
+ const go = (node) => {
233
+ switch (node._tag) {
234
+ case "True": return R.succeed(true);
235
+ case "False": return R.succeed(false);
236
+ case "Compare": return R.succeed(testCompare(node.op, getField(input.value, node.field), resolve(node.value, input.principal)));
237
+ case "In": {
238
+ const field = getField(input.value, node.field);
239
+ return R.succeed(node.values.some((operand) => resolve(operand, input.principal) === field));
240
+ }
241
+ case "Exists": return R.succeed(getField(input.value, node.field) !== null);
242
+ case "Under": return R.succeed(testUnder(node.prefix, input));
243
+ case "And": return R.every(node.conditions, (child) => R.suspend(() => go(child)));
244
+ case "Or": return R.some(node.conditions, (child) => R.suspend(() => go(child)));
245
+ case "Not": return R.map(R.suspend(() => go(node.condition)), (value) => !value);
246
+ case "Predicate": throw new Error(`The predicate "${node.name}" needs an Effect. Use Condition.evaluate.`);
225
247
  }
226
- case "Exists": return getField(input.value, node.field) !== null;
227
- case "Under": return testUnder(node.prefix, input);
228
- case "And": return Arr.every(node.conditions, (child) => testSync(child, input));
229
- case "Or": return Arr.some(node.conditions, (child) => testSync(child, input));
230
- case "Not": return !testSync(node.condition, input);
231
- case "Predicate": throw new Error(`The predicate "${node.name}" needs an Effect. Use Condition.evaluate.`);
232
- }
248
+ };
249
+ return go;
233
250
  };
251
+ /** Tests a simple condition with no predicate on a value. */
252
+ const testSync = (node, input) => run(node.depth, (R) => testWith(input)(R)(node));
234
253
  /**
235
254
  * Tests a simple condition on a value. The children of `And` and `Or` run in
236
- * order, and they stop at the first child that gives the answer.
255
+ * order, and they stop at the first child that gives the answer. Each call
256
+ * for a child is a step of the Effect, so a deep condition does not fill the
257
+ * stack. A part with no predicate runs as a walk in the same loop.
237
258
  */
238
259
  const test = (node, input) => {
239
- if (!node.opaque) return Effect.sync(() => testSync(node, input));
260
+ if (!node.opaque) return node.depth <= 200 ? Effect.sync(() => testSync(node, input)) : node.pipe(testWith(input)(loop), toEffect);
240
261
  switch (node._tag) {
241
262
  case "Predicate": return runOf(node)(input.value, input.principal);
242
- case "Not": return Effect.map(test(node.condition, input), (value) => !value);
243
- case "And": return Effect.map(Effect.findFirst(node.conditions, (child) => Effect.map(test(child, input), (value) => !value)), Option.isNone);
244
- case "Or": return Effect.map(Effect.findFirst(node.conditions, (child) => test(child, input)), Option.isSome);
263
+ case "Not": return Effect.map(Effect.suspend(() => test(node.condition, input)), (value) => !value);
264
+ case "And": return Effect.map(Effect.findFirst(node.conditions, (child) => Effect.map(Effect.suspend(() => test(child, input)), (value) => !value)), Option.isNone);
265
+ case "Or": return Effect.map(Effect.findFirst(node.conditions, (child) => Effect.suspend(() => test(child, input))), Option.isSome);
245
266
  default: return Effect.sync(() => testSync(node, input));
246
267
  }
247
268
  };
@@ -281,71 +302,77 @@ const expandUnder = (prefix, principal, path) => {
281
302
  * resource. The result is simple. It has no principal fields and no `Under`
282
303
  * nodes. A predicate keeps the principal.
283
304
  */
284
- const partial = (node, input) => {
305
+ const partial = (node, input) => run(node.depth, (R) => {
285
306
  const bind = (current) => {
286
307
  switch (current._tag) {
287
308
  case "Compare": {
288
309
  const value = bindOperand(current.value, input.principal);
289
- return value === void 0 ? never : value === current.value ? current : new Compare({
310
+ return R.succeed(value === void 0 ? never : value === current.value ? current : new Compare({
290
311
  op: current.op,
291
312
  field: current.field,
292
313
  value
293
- });
314
+ }));
294
315
  }
295
316
  case "In": {
296
317
  const values = Arr.flatMap(current.values, (operand) => Option.toArray(Option.fromUndefinedOr(bindOperand(operand, input.principal))));
297
- return values.length === 0 ? never : new In({
318
+ return R.succeed(values.length === 0 ? never : new In({
298
319
  field: current.field,
299
320
  values
300
- });
321
+ }));
301
322
  }
302
- case "Under": return expandUnder(current.prefix, input.principal, input.path);
303
- case "And": return and(Arr.map(current.conditions, bind));
304
- case "Or": return or(Arr.map(current.conditions, bind));
305
- case "Not": return current.condition.pipe(bind, not);
323
+ case "Under": return R.succeed(expandUnder(current.prefix, input.principal, input.path));
324
+ case "And": return R.map(eachChild(R, current.conditions, bind), and);
325
+ case "Or": return R.map(eachChild(R, current.conditions, bind), or);
326
+ case "Not": return R.map(R.suspend(() => bind(current.condition)), not);
306
327
  case "Predicate": {
307
328
  const run = runOf(current);
308
- return new Predicate({
329
+ return R.succeed(new Predicate({
309
330
  name: current.name,
310
331
  run: (value) => run(value, input.principal)
311
- });
332
+ }));
312
333
  }
313
- default: return current;
334
+ default: return R.succeed(current);
314
335
  }
315
336
  };
316
337
  return bind(node);
317
- };
338
+ });
318
339
  /** Gives the services in `context` to every predicate of a condition. */
319
- const provide = (node, context) => {
320
- if (!node.opaque) return node;
321
- switch (node._tag) {
322
- case "Predicate": {
323
- const run = runOf(node);
324
- return new Predicate({
325
- name: node.name,
326
- run: (value, principal) => Effect.provideContext(run(value, principal), context)
327
- });
328
- }
329
- case "And": return new And(Arr.map(node.conditions, (child) => provide(child, context)));
330
- case "Or": return new Or(Arr.map(node.conditions, (child) => provide(child, context)));
331
- case "Not": return new Not(provide(node.condition, context));
332
- default: return node;
333
- }
334
- };
335
- /** The fields that a condition tests, in the order that they first come. */
336
- const fields = (node) => {
337
- const all = (current) => {
340
+ const provide = (node, context) => run(node.depth, (R) => {
341
+ const go = (current) => {
342
+ if (!current.opaque) return R.succeed(current);
338
343
  switch (current._tag) {
339
- case "Compare":
340
- case "In":
341
- case "Exists": return [current.field];
342
- case "And":
343
- case "Or": return Arr.flatMap(current.conditions, all);
344
- case "Not": return all(current.condition);
345
- default: return [];
344
+ case "Predicate": {
345
+ const run = runOf(current);
346
+ return R.succeed(new Predicate({
347
+ name: current.name,
348
+ run: (value, principal) => Effect.provideContext(run(value, principal), context)
349
+ }));
350
+ }
351
+ case "And": return R.map(eachChild(R, current.conditions, go), (children) => new And(children));
352
+ case "Or": return R.map(eachChild(R, current.conditions, go), (children) => new Or(children));
353
+ case "Not": return R.map(R.suspend(() => go(current.condition)), (child) => new Not(child));
354
+ default: return R.succeed(current);
346
355
  }
347
356
  };
348
- return Array.from(new Set(all(node)));
357
+ return go(node);
358
+ });
359
+ /** The fields that a condition tests, in the order that they first come. */
360
+ const fields = (node) => {
361
+ const all = run(node.depth, (R) => {
362
+ const go = (current) => {
363
+ switch (current._tag) {
364
+ case "Compare":
365
+ case "In":
366
+ case "Exists": return R.succeed([current.field]);
367
+ case "And":
368
+ case "Or": return R.map(eachChild(R, current.conditions, go), Arr.flatten);
369
+ case "Not": return R.suspend(() => go(current.condition));
370
+ default: return R.succeed([]);
371
+ }
372
+ };
373
+ return go(node);
374
+ });
375
+ return Array.from(new Set(all));
349
376
  };
350
377
  export { and, evaluate, evaluateSync, fields, keyOf, not, or, partial, provide, simplify, testCompare };
351
378
 
@@ -1 +1 @@
1
- {"version":3,"file":"algebra.js","names":["Nodes","Nodes.And","Nodes.Or","Nodes.Compare","Nodes.Not","Nodes.isScalar","Nodes.runOf","Nodes.literal","Nodes.In","Nodes.Predicate"],"sources":["../../src/internal/algebra.ts"],"sourcesContent":["/**\n * The work on condition nodes: smart constructors, simplification, the step\n * that puts the principal in, tests on a value, and folds.\n *\n * The constructors of the nodes keep each condition small and low, so each\n * walk here is a plain walk with no memo. A shared child is walked again for\n * each place, and the limits of the nodes keep that work small.\n */\n// A predicate gives an Effect with an error type and a service type that this\n// code does not know, so they are `unknown` here.\n// @effect-diagnostics anyUnknownInErrorContext:off\nimport * as Arr from \"effect/Array\"\nimport type * as Context from \"effect/Context\"\nimport * as Effect from \"effect/Effect\"\nimport * as Option from \"effect/Option\"\nimport type * as Resource from \"../Resource.ts\"\nimport * as Nodes from \"./nodes.ts\"\nimport { readPath } from \"./read.ts\"\n\ntype Node = Nodes.Node\n\nconst { always, never } = Nodes\n\n// Keys of structure\n\n/** The text of an operand. The type is in it, so `\"1\"` is not `1`. */\nconst operandText = (operand: Nodes.Operand): ReadonlyArray<string> =>\n\toperand._tag === \"Literal\"\n\t\t? [typeof operand.value, String(operand.value)]\n\t\t: [\"principal\", operand.path]\n\n/** The parts of the text of a condition with no predicate. */\nconst shapeOf = (node: Node): unknown => {\n\tswitch (node._tag) {\n\t\tcase \"True\":\n\t\tcase \"False\":\n\t\t\treturn [node._tag]\n\t\tcase \"Compare\":\n\t\t\treturn [node._tag, node.op, node.field, operandText(node.value)]\n\t\tcase \"In\":\n\t\t\treturn [node._tag, node.field, Arr.map(node.values, operandText)]\n\t\tcase \"Exists\":\n\t\t\treturn [node._tag, node.field]\n\t\tcase \"Under\":\n\t\t\treturn [node._tag, Arr.map(node.prefix, operandText)]\n\t\tcase \"And\":\n\t\tcase \"Or\":\n\t\t\treturn [node._tag, Arr.map(node.conditions, shapeOf)]\n\t\tcase \"Not\":\n\t\t\treturn [node._tag, shapeOf(node.condition)]\n\t\tcase \"Predicate\":\n\t\t\t// A smart constructor and a search do not ask for the text of a\n\t\t\t// predicate: it is equal only to itself.\n\t\t\tthrow new Error(\"A predicate has no text of structure\")\n\t}\n}\n\n/**\n * The text of the structure of a condition with no predicate. Two conditions\n * with one text give the same answer for every value. It reads all of the\n * condition, so a search counts its size in the budget.\n */\nconst structureText = (node: Node): string => JSON.stringify(shapeOf(node))\n\n/**\n * The work of the text of the structure of a condition: each node, and each\n * value of an `In` test or an `Under` test. A node counts as one in `size`,\n * also an `In` test with very many values. This walk reads the nodes only,\n * so it takes `size` steps.\n */\nconst weightOf = (node: Node): number => {\n\tswitch (node._tag) {\n\t\tcase \"In\":\n\t\t\treturn 1 + node.values.length\n\t\tcase \"Under\":\n\t\t\treturn 1 + node.prefix.length\n\t\tcase \"And\":\n\t\tcase \"Or\":\n\t\t\treturn Arr.reduce(\n\t\t\t\tnode.conditions,\n\t\t\t\t1,\n\t\t\t\t(total, child) => total + weightOf(child),\n\t\t\t)\n\t\tcase \"Not\":\n\t\t\treturn 1 + weightOf(node.condition)\n\t\tdefault:\n\t\t\treturn 1\n\t}\n}\n\n/**\n * The most nodes of a condition that a smart constructor reads for its key,\n * and the most children of a child that it puts into a node. A larger child\n * is its own key, and it stays one child, so the work of a constructor stays\n * small. A deep chain of `And` nodes, for one, does not copy all its leaves\n * at each level.\n */\nconst keyNodes = 64\n\n/** The most work of a key, with the values of its tests: see {@link weightOf}. */\nconst keyWeight = 256\n\n/**\n * The key of a child in a smart constructor: the text of its structure, or\n * the node itself when it is large. The keys go into a native `Set`, not a\n * `HashSet` of Effect. The hash of a string in Effect has no random seed, so\n * a policy could hold very many strings with one hash, and each test of the\n * set would read all of them. A native `Set` finds a node by the node itself,\n * and it hashes a string with the random seed of the engine.\n */\nexport const keyOf = (node: Node): string | Node =>\n\tnode.size > keyNodes || weightOf(node) > keyWeight\n\t\t? node\n\t\t: structureText(node)\n\n/**\n * Keeps the first node of each structure, in order. A large node is a copy\n * only of itself.\n */\nconst dedupe = (nodes: ReadonlyArray<Node>): ReadonlyArray<Node> => {\n\t// The set belongs to this call.\n\tconst seen = new Set<string | Node>()\n\treturn Arr.filter(nodes, (node) => {\n\t\tconst key = keyOf(node)\n\t\tif (seen.has(key)) {\n\t\t\treturn false\n\t\t}\n\t\tseen.add(key)\n\t\treturn true\n\t})\n}\n\n/**\n * Removes the children that the other children make useless. In an `Or`,\n * `a OR (a AND b)` is `a`. In an `And`, `a AND (a OR b)` is `a`.\n */\nconst absorb = (\n\tinner: \"And\" | \"Or\",\n\tnodes: ReadonlyArray<Node>,\n): ReadonlyArray<Node> => {\n\t// A native `Set`, as in `dedupe`.\n\tconst all = new Set(Arr.map(nodes, keyOf))\n\treturn Arr.filter(\n\t\tnodes,\n\t\t(node) =>\n\t\t\tnode._tag !== inner ||\n\t\t\t!Arr.some(node.conditions, (part) => all.has(keyOf(part))),\n\t)\n}\n\n// Smart constructors\n\n/**\n * Gives the result of an `And` with a `False` child, or of an `Or` with a\n * `True` child. The children are tested in order, so a predicate before the\n * constant still runs, and it may fail. When there is such a predicate, the\n * children before the constant stay, so the failure is not lost.\n */\nconst shortCircuit = (\n\ttag: \"And\" | \"Or\",\n\tchildren: ReadonlyArray<Node>,\n\tindex: number,\n): Node => {\n\tconst constant = tag === \"And\" ? never : always\n\tconst neutral = tag === \"And\" ? \"True\" : \"False\"\n\tconst before = Arr.filter(\n\t\tArr.take(children, index),\n\t\t(child) => child._tag !== neutral,\n\t)\n\tif (!Arr.some(before, (child) => child.opaque)) {\n\t\treturn constant\n\t}\n\treturn tag === \"And\"\n\t\t? new Nodes.And([...before, constant])\n\t\t: new Nodes.Or([...before, constant])\n}\n\n/**\n * Makes an `And` or an `Or` of simple children, and makes it simple. It looks\n * one level down only:\n * - it puts the children of a child of the same kind into the node, when\n * the child has at most `keyNodes` of them;\n * - it stops at a `False` in an `And`, or at a `True` in an `Or`;\n * - it removes `True` from an `And`, `False` from an `Or`, copies, and the\n * children that other children make useless.\n *\n * A predicate may fail, and it may give another answer when it runs again. So\n * when a child has a predicate, the children stay as they are, and each one\n * runs in its place. A child with a predicate is not put into the node either.\n */\nconst junction = (tag: \"And\" | \"Or\", children: ReadonlyArray<Node>): Node => {\n\tconst constant = tag === \"And\" ? \"False\" : \"True\"\n\tconst neutral = tag === \"And\" ? \"True\" : \"False\"\n\tconst flat = Arr.flatMap(children, (child) =>\n\t\tchild._tag === tag && !child.opaque && child.conditions.length <= keyNodes\n\t\t\t? child.conditions\n\t\t\t: [child],\n\t)\n\treturn Option.match(\n\t\tArr.findFirstIndex(flat, (child) => child._tag === constant),\n\t\t{\n\t\t\tonSome: (stop) => shortCircuit(tag, flat, stop),\n\t\t\tonNone: () => {\n\t\t\t\tconst kept = Arr.filter(flat, (child) => child._tag !== neutral)\n\t\t\t\tconst unique = Arr.some(kept, (child) => child.opaque)\n\t\t\t\t\t? kept\n\t\t\t\t\t: absorb(tag === \"And\" ? \"Or\" : \"And\", dedupe(kept))\n\t\t\t\treturn unique.length === 0\n\t\t\t\t\t? tag === \"And\"\n\t\t\t\t\t\t? always\n\t\t\t\t\t\t: never\n\t\t\t\t\t: unique.length === 1\n\t\t\t\t\t\t? unique[0]!\n\t\t\t\t\t\t: tag === \"And\"\n\t\t\t\t\t\t\t? new Nodes.And(unique)\n\t\t\t\t\t\t\t: new Nodes.Or(unique)\n\t\t\t},\n\t\t},\n\t)\n}\n\n/** An `And` of simple children, made simple. */\nexport const and = (children: ReadonlyArray<Node>): Node =>\n\tjunction(\"And\", children)\n\n/** An `Or` of simple children, made simple. */\nexport const or = (children: ReadonlyArray<Node>): Node =>\n\tjunction(\"Or\", children)\n\n/** A `Not` of a simple child, made simple. */\nexport const not = (child: Node): Node => {\n\tswitch (child._tag) {\n\t\tcase \"True\":\n\t\t\treturn never\n\t\tcase \"False\":\n\t\t\treturn always\n\t\tcase \"Not\":\n\t\t\treturn child.condition\n\t\tcase \"Compare\":\n\t\t\t// A principal field with no value makes `eq` and `ne` both false, so\n\t\t\t// only a fixed value lets `not eq` become `ne`.\n\t\t\treturn child.value._tag === \"Literal\" &&\n\t\t\t\t(child.op === \"eq\" || child.op === \"ne\")\n\t\t\t\t? new Nodes.Compare({\n\t\t\t\t\t\top: child.op === \"eq\" ? \"ne\" : \"eq\",\n\t\t\t\t\t\tfield: child.field,\n\t\t\t\t\t\tvalue: child.value,\n\t\t\t\t\t})\n\t\t\t\t: new Nodes.Not(child)\n\t\tdefault:\n\t\t\treturn new Nodes.Not(child)\n\t}\n}\n\n/** Makes a condition simple, from its leaves up. */\nexport const simplify = (node: Node): Node => {\n\tswitch (node._tag) {\n\t\tcase \"And\":\n\t\tcase \"Or\":\n\t\t\treturn junction(node._tag, Arr.map(node.conditions, simplify))\n\t\tcase \"Not\":\n\t\t\treturn node.condition.pipe(simplify, not)\n\t\tcase \"In\":\n\t\t\treturn node.values.length === 0 ? never : node\n\t\tdefault:\n\t\t\treturn node\n\t}\n}\n\n// Tests on a value\n\n/** The data that a condition needs for a test. */\nexport interface Input {\n\treadonly value: object\n\treadonly principal?: object | undefined\n\treadonly path?: ReadonlyArray<Resource.PathSegment> | undefined\n}\n\n/**\n * Gets a field of a value by a path with dots. It reads only plain data: see\n * `readPart`. A missing field, or a field under a value that is not an object,\n * gives `null`.\n */\nconst getField = (value: unknown, path: string): unknown =>\n\treadPath(value, path.split(\".\"))\n\n/**\n * Gives the value of an operand. A principal field that is `null`, missing, or\n * not a scalar gives `undefined`. No field of a resource is `undefined`, so a\n * test with it is never true. This keeps the check closed: a principal with no\n * id never matches a resource with no owner.\n */\nconst resolve = (operand: Nodes.Operand, principal: unknown): unknown => {\n\tif (operand._tag === \"Literal\") {\n\t\treturn operand.value\n\t}\n\tconst value = getField(principal, operand.path)\n\treturn value !== null && Nodes.isScalar(value) ? value : undefined\n}\n\nexport const testCompare = (\n\top: Nodes.CompareOperator,\n\tleft: unknown,\n\tright: unknown,\n): boolean => {\n\tif (right === undefined) {\n\t\treturn false\n\t}\n\tswitch (op) {\n\t\tcase \"eq\":\n\t\t\treturn left === right\n\t\tcase \"ne\":\n\t\t\treturn left !== right\n\t\tdefault: {\n\t\t\tconst ordered =\n\t\t\t\t(typeof left === \"number\" && typeof right === \"number\") ||\n\t\t\t\t(typeof left === \"string\" && typeof right === \"string\")\n\t\t\tif (!ordered) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tconst a = left as number | string\n\t\t\tconst b = right as number | string\n\t\t\tswitch (op) {\n\t\t\t\tcase \"lt\":\n\t\t\t\t\treturn a < b\n\t\t\t\tcase \"lte\":\n\t\t\t\t\treturn a <= b\n\t\t\t\tcase \"gt\":\n\t\t\t\t\treturn a > b\n\t\t\t\tcase \"gte\":\n\t\t\t\t\treturn a >= b\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Gives the values of the path of a resource, or `undefined` for no path. */\nconst pathValues = (\n\tvalue: unknown,\n\tpath: ReadonlyArray<Resource.PathSegment> | undefined,\n): ReadonlyArray<unknown> | undefined =>\n\tpath?.map((segment) =>\n\t\ttypeof segment === \"string\" ? segment : getField(value, segment.field),\n\t)\n\nconst testUnder = (\n\tprefix: ReadonlyArray<Nodes.Operand>,\n\tinput: Input,\n): boolean => {\n\tconst values = pathValues(input.value, input.path)\n\tif (values === undefined || prefix.length > values.length) {\n\t\treturn false\n\t}\n\t// An operand with no value never matches, also a hole in a path that gives\n\t// `undefined` too.\n\treturn prefix.every((operand, index) => {\n\t\tconst value = resolve(operand, input.principal)\n\t\treturn value !== undefined && value === values[index]\n\t})\n}\n\n/** Tests a simple condition with no predicate on a value. */\nconst testSync = (node: Node, input: Input): boolean => {\n\tswitch (node._tag) {\n\t\tcase \"True\":\n\t\t\treturn true\n\t\tcase \"False\":\n\t\t\treturn false\n\t\tcase \"Compare\":\n\t\t\treturn testCompare(\n\t\t\t\tnode.op,\n\t\t\t\tgetField(input.value, node.field),\n\t\t\t\tresolve(node.value, input.principal),\n\t\t\t)\n\t\tcase \"In\": {\n\t\t\tconst field = getField(input.value, node.field)\n\t\t\treturn node.values.some(\n\t\t\t\t(operand) => resolve(operand, input.principal) === field,\n\t\t\t)\n\t\t}\n\t\tcase \"Exists\":\n\t\t\treturn getField(input.value, node.field) !== null\n\t\tcase \"Under\":\n\t\t\treturn testUnder(node.prefix, input)\n\t\tcase \"And\":\n\t\t\treturn Arr.every(node.conditions, (child) => testSync(child, input))\n\t\tcase \"Or\":\n\t\t\treturn Arr.some(node.conditions, (child) => testSync(child, input))\n\t\tcase \"Not\":\n\t\t\treturn !testSync(node.condition, input)\n\t\tcase \"Predicate\":\n\t\t\t// The types stop this. A predicate needs `evaluate`.\n\t\t\tthrow new Error(\n\t\t\t\t`The predicate \"${node.name}\" needs an Effect. Use Condition.evaluate.`,\n\t\t\t)\n\t}\n}\n\n/**\n * Tests a simple condition on a value. The children of `And` and `Or` run in\n * order, and they stop at the first child that gives the answer.\n */\nconst test = (\n\tnode: Node,\n\tinput: Input,\n): Effect.Effect<boolean, unknown, unknown> => {\n\tif (!node.opaque) {\n\t\treturn Effect.sync(() => testSync(node, input))\n\t}\n\tswitch (node._tag) {\n\t\tcase \"Predicate\":\n\t\t\treturn Nodes.runOf(node)(input.value, input.principal)\n\t\tcase \"Not\":\n\t\t\treturn Effect.map(test(node.condition, input), (value) => !value)\n\t\tcase \"And\":\n\t\t\treturn Effect.map(\n\t\t\t\tEffect.findFirst(node.conditions, (child) =>\n\t\t\t\t\tEffect.map(test(child, input), (value) => !value),\n\t\t\t\t),\n\t\t\t\tOption.isNone,\n\t\t\t)\n\t\tcase \"Or\":\n\t\t\treturn Effect.map(\n\t\t\t\tEffect.findFirst(node.conditions, (child) => test(child, input)),\n\t\t\t\tOption.isSome,\n\t\t\t)\n\t\tdefault:\n\t\t\treturn Effect.sync(() => testSync(node, input))\n\t}\n}\n\n/**\n * Tests a condition with no predicate on a value. The test runs on the\n * simple form of the condition with the principal in it, as a residual does.\n * So a test reads only the fields that the residual reads: a read of a field\n * that is not plain data is a defect, and a field that the answer does not\n * need, as in `x AND False`, is not read.\n */\nexport const evaluateSync = (node: Node, input: Input): boolean =>\n\ttestSync(partial(node, input), input)\n\n/** Tests a condition on a value, as {@link evaluateSync} does. */\nexport const evaluate = (\n\tnode: Node,\n\tinput: Input,\n): Effect.Effect<boolean, unknown, unknown> =>\n\tEffect.suspend(() => test(partial(node, input), input))\n\n// The principal and the path\n\n/**\n * Puts the value of the principal into an operand. It gives `undefined` for a\n * principal field with no value. See {@link resolve}.\n */\nconst bindOperand = (\n\toperand: Nodes.Operand,\n\tprincipal: unknown,\n): Nodes.Literal | undefined => {\n\tif (operand._tag === \"Literal\") {\n\t\treturn operand\n\t}\n\tconst value = resolve(operand, principal)\n\treturn value === undefined ? undefined : Nodes.literal(value as Nodes.Scalar)\n}\n\nconst expandUnder = (\n\tprefix: ReadonlyArray<Nodes.Operand>,\n\tprincipal: unknown,\n\tpath: ReadonlyArray<Resource.PathSegment> | undefined,\n): Node => {\n\tif (path === undefined || prefix.length > path.length) {\n\t\treturn never\n\t}\n\treturn and(\n\t\tArr.map(prefix, (operand, index): Node => {\n\t\t\tconst value = resolve(operand, principal)\n\t\t\tconst segment = path[index]!\n\t\t\treturn value === undefined\n\t\t\t\t? never\n\t\t\t\t: typeof segment === \"string\"\n\t\t\t\t\t? segment === value\n\t\t\t\t\t\t? always\n\t\t\t\t\t\t: never\n\t\t\t\t\t: new Nodes.Compare({\n\t\t\t\t\t\t\top: \"eq\",\n\t\t\t\t\t\t\tfield: segment.field,\n\t\t\t\t\t\t\tvalue: Nodes.literal(value as Nodes.Scalar),\n\t\t\t\t\t\t})\n\t\t}),\n\t)\n}\n\n/** The principal and the path of the resource, for {@link partial}. */\nexport interface PartialInput {\n\treadonly principal?: object | undefined\n\treadonly path?: ReadonlyArray<Resource.PathSegment> | undefined\n}\n\n/**\n * Puts the principal into a condition and expands `Under` with the path of the\n * resource. The result is simple. It has no principal fields and no `Under`\n * nodes. A predicate keeps the principal.\n */\nexport const partial = (node: Node, input: PartialInput): Node => {\n\tconst bind = (current: Node): Node => {\n\t\tswitch (current._tag) {\n\t\t\tcase \"Compare\": {\n\t\t\t\tconst value = bindOperand(current.value, input.principal)\n\t\t\t\treturn value === undefined\n\t\t\t\t\t? never\n\t\t\t\t\t: value === current.value\n\t\t\t\t\t\t? current\n\t\t\t\t\t\t: new Nodes.Compare({ op: current.op, field: current.field, value })\n\t\t\t}\n\t\t\tcase \"In\": {\n\t\t\t\tconst values = Arr.flatMap(current.values, (operand) =>\n\t\t\t\t\tOption.toArray(\n\t\t\t\t\t\tOption.fromUndefinedOr(bindOperand(operand, input.principal)),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t\treturn values.length === 0\n\t\t\t\t\t? never\n\t\t\t\t\t: new Nodes.In({ field: current.field, values })\n\t\t\t}\n\t\t\tcase \"Under\":\n\t\t\t\treturn expandUnder(current.prefix, input.principal, input.path)\n\t\t\tcase \"And\":\n\t\t\t\treturn and(Arr.map(current.conditions, bind))\n\t\t\tcase \"Or\":\n\t\t\t\treturn or(Arr.map(current.conditions, bind))\n\t\t\tcase \"Not\":\n\t\t\t\treturn current.condition.pipe(bind, not)\n\t\t\tcase \"Predicate\": {\n\t\t\t\tconst run = Nodes.runOf(current)\n\t\t\t\treturn new Nodes.Predicate({\n\t\t\t\t\tname: current.name,\n\t\t\t\t\trun: (value) => run(value, input.principal),\n\t\t\t\t})\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn current\n\t\t}\n\t}\n\treturn bind(node)\n}\n\n/** Gives the services in `context` to every predicate of a condition. */\nexport const provide = (node: Node, context: Context.Context<never>): Node => {\n\tif (!node.opaque) {\n\t\treturn node\n\t}\n\tswitch (node._tag) {\n\t\tcase \"Predicate\": {\n\t\t\tconst run = Nodes.runOf(node)\n\t\t\treturn new Nodes.Predicate({\n\t\t\t\tname: node.name,\n\t\t\t\trun: (value, principal) =>\n\t\t\t\t\tEffect.provideContext(run(value, principal), context),\n\t\t\t})\n\t\t}\n\t\tcase \"And\":\n\t\t\treturn new Nodes.And(\n\t\t\t\tArr.map(node.conditions, (child) => provide(child, context)),\n\t\t\t)\n\t\tcase \"Or\":\n\t\t\treturn new Nodes.Or(\n\t\t\t\tArr.map(node.conditions, (child) => provide(child, context)),\n\t\t\t)\n\t\tcase \"Not\":\n\t\t\treturn new Nodes.Not(provide(node.condition, context))\n\t\tdefault:\n\t\t\treturn node\n\t}\n}\n\n/** The fields that a condition tests, in the order that they first come. */\nexport const fields = (node: Node): ReadonlyArray<string> => {\n\tconst all = (current: Node): ReadonlyArray<string> => {\n\t\tswitch (current._tag) {\n\t\t\tcase \"Compare\":\n\t\t\tcase \"In\":\n\t\t\tcase \"Exists\":\n\t\t\t\treturn [current.field]\n\t\t\tcase \"And\":\n\t\t\tcase \"Or\":\n\t\t\t\treturn Arr.flatMap(current.conditions, all)\n\t\t\tcase \"Not\":\n\t\t\t\treturn all(current.condition)\n\t\t\tdefault:\n\t\t\t\treturn []\n\t\t}\n\t}\n\t// A native `Set`, as in `dedupe`: a field of a condition that is not bound\n\t// to a domain may be any string.\n\treturn Array.from(new Set(all(node)))\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"algebra.js","names":["Nodes","Nodes.And","Nodes.Or","Nodes.Compare","Nodes.Not","Trampoline.run","Nodes.isScalar","Trampoline.loop","Trampoline.toEffect","Nodes.runOf","Nodes.literal","Nodes.In","Nodes.Predicate"],"sources":["../../src/internal/algebra.ts"],"sourcesContent":["/**\n * The work on condition nodes: smart constructors, simplification, the step\n * that puts the principal in, tests on a value, and folds.\n *\n * The constructors of the nodes keep each condition small, so each walk here\n * has no memo. A shared child is walked again for each place, and the limits\n * of the nodes keep that work small. A walk takes the steps of a trampoline,\n * so a deep condition does not fill the stack: see `Trampoline`.\n */\n// A predicate gives an Effect with an error type and a service type that this\n// code does not know, so they are `unknown` here.\n// @effect-diagnostics anyUnknownInErrorContext:off\nimport * as Arr from \"effect/Array\"\nimport type * as Context from \"effect/Context\"\nimport * as Effect from \"effect/Effect\"\nimport * as Option from \"effect/Option\"\nimport type * as Resource from \"../Resource.ts\"\nimport * as Nodes from \"./nodes.ts\"\nimport { readPath } from \"./read.ts\"\nimport * as Trampoline from \"./trampoline.ts\"\n\ntype Node = Nodes.Node\n\nconst { always, never } = Nodes\n\n// Keys of structure\n\n/** The text of an operand. The type is in it, so `\"1\"` is not `1`. */\nconst operandText = (operand: Nodes.Operand): ReadonlyArray<string> =>\n\toperand._tag === \"Literal\"\n\t\t? [typeof operand.value, String(operand.value)]\n\t\t: [\"principal\", operand.path]\n\n/** The parts of the text of a condition with no predicate. */\nconst shapeOf = (node: Node): unknown => {\n\tswitch (node._tag) {\n\t\tcase \"True\":\n\t\tcase \"False\":\n\t\t\treturn [node._tag]\n\t\tcase \"Compare\":\n\t\t\treturn [node._tag, node.op, node.field, operandText(node.value)]\n\t\tcase \"In\":\n\t\t\treturn [node._tag, node.field, Arr.map(node.values, operandText)]\n\t\tcase \"Exists\":\n\t\t\treturn [node._tag, node.field]\n\t\tcase \"Under\":\n\t\t\treturn [node._tag, Arr.map(node.prefix, operandText)]\n\t\tcase \"And\":\n\t\tcase \"Or\":\n\t\t\treturn [node._tag, Arr.map(node.conditions, shapeOf)]\n\t\tcase \"Not\":\n\t\t\treturn [node._tag, shapeOf(node.condition)]\n\t\tcase \"Predicate\":\n\t\t\t// A smart constructor and a search do not ask for the text of a\n\t\t\t// predicate: it is equal only to itself.\n\t\t\tthrow new Error(\"A predicate has no text of structure\")\n\t}\n}\n\n/**\n * The text of the structure of a condition with no predicate. Two conditions\n * with one text give the same answer for every value. It reads all of the\n * condition, so a search counts its size in the budget.\n */\nconst structureText = (node: Node): string => JSON.stringify(shapeOf(node))\n\n/**\n * The work of the text of the structure of a condition: each node, and each\n * value of an `In` test or an `Under` test. A node counts as one in `size`,\n * also an `In` test with very many values. This walk reads the nodes only,\n * so it takes `size` steps.\n */\nconst weightOf = (node: Node): number => {\n\tswitch (node._tag) {\n\t\tcase \"In\":\n\t\t\treturn 1 + node.values.length\n\t\tcase \"Under\":\n\t\t\treturn 1 + node.prefix.length\n\t\tcase \"And\":\n\t\tcase \"Or\":\n\t\t\treturn Arr.reduce(\n\t\t\t\tnode.conditions,\n\t\t\t\t1,\n\t\t\t\t(total, child) => total + weightOf(child),\n\t\t\t)\n\t\tcase \"Not\":\n\t\t\treturn 1 + weightOf(node.condition)\n\t\tdefault:\n\t\t\treturn 1\n\t}\n}\n\n/**\n * The most nodes of a condition that a smart constructor reads for its key,\n * and the most children of a child that it puts into a node. A larger child\n * is its own key, and it stays one child, so the work of a constructor stays\n * small. A deep chain of `And` nodes, for one, does not copy all its leaves\n * at each level.\n */\nconst keyNodes = 64\n\n/** The most work of a key, with the values of its tests: see {@link weightOf}. */\nconst keyWeight = 256\n\n/**\n * The key of a child in a smart constructor: the text of its structure, or\n * the node itself when it is large. The keys go into a native `Set`, not a\n * `HashSet` of Effect. The hash of a string in Effect has no random seed, so\n * a policy could hold very many strings with one hash, and each test of the\n * set would read all of them. A native `Set` finds a node by the node itself,\n * and it hashes a string with the random seed of the engine.\n */\nexport const keyOf = (node: Node): string | Node =>\n\tnode.size > keyNodes || weightOf(node) > keyWeight\n\t\t? node\n\t\t: structureText(node)\n\n/**\n * Keeps the first node of each structure, in order. A large node is a copy\n * only of itself.\n */\nconst dedupe = (nodes: ReadonlyArray<Node>): ReadonlyArray<Node> => {\n\t// The set belongs to this call.\n\tconst seen = new Set<string | Node>()\n\treturn Arr.filter(nodes, (node) => {\n\t\tconst key = keyOf(node)\n\t\tif (seen.has(key)) {\n\t\t\treturn false\n\t\t}\n\t\tseen.add(key)\n\t\treturn true\n\t})\n}\n\n/**\n * Removes the children that the other children make useless. In an `Or`,\n * `a OR (a AND b)` is `a`. In an `And`, `a AND (a OR b)` is `a`.\n */\nconst absorb = (\n\tinner: \"And\" | \"Or\",\n\tnodes: ReadonlyArray<Node>,\n): ReadonlyArray<Node> => {\n\t// A native `Set`, as in `dedupe`.\n\tconst all = new Set(Arr.map(nodes, keyOf))\n\treturn Arr.filter(\n\t\tnodes,\n\t\t(node) =>\n\t\t\tnode._tag !== inner ||\n\t\t\t!Arr.some(node.conditions, (part) => all.has(keyOf(part))),\n\t)\n}\n\n// Smart constructors\n\n/**\n * Gives the result of an `And` with a `False` child, or of an `Or` with a\n * `True` child. The children are tested in order, so a predicate before the\n * constant still runs, and it may fail. When there is such a predicate, the\n * children before the constant stay, so the failure is not lost.\n */\nconst shortCircuit = (\n\ttag: \"And\" | \"Or\",\n\tchildren: ReadonlyArray<Node>,\n\tindex: number,\n): Node => {\n\tconst constant = tag === \"And\" ? never : always\n\tconst neutral = tag === \"And\" ? \"True\" : \"False\"\n\tconst before = Arr.filter(\n\t\tArr.take(children, index),\n\t\t(child) => child._tag !== neutral,\n\t)\n\tif (!Arr.some(before, (child) => child.opaque)) {\n\t\treturn constant\n\t}\n\treturn tag === \"And\"\n\t\t? new Nodes.And([...before, constant])\n\t\t: new Nodes.Or([...before, constant])\n}\n\n/**\n * Makes an `And` or an `Or` of simple children, and makes it simple. It looks\n * one level down only:\n * - it puts the children of a child of the same kind into the node, when\n * the child has at most `keyNodes` of them;\n * - it stops at a `False` in an `And`, or at a `True` in an `Or`;\n * - it removes `True` from an `And`, `False` from an `Or`, copies, and the\n * children that other children make useless.\n *\n * A predicate may fail, and it may give another answer when it runs again. So\n * when a child has a predicate, the children stay as they are, and each one\n * runs in its place. A child with a predicate is not put into the node either.\n */\nconst junction = (tag: \"And\" | \"Or\", children: ReadonlyArray<Node>): Node => {\n\tconst constant = tag === \"And\" ? \"False\" : \"True\"\n\tconst neutral = tag === \"And\" ? \"True\" : \"False\"\n\tconst flat = Arr.flatMap(children, (child) =>\n\t\tchild._tag === tag && !child.opaque && child.conditions.length <= keyNodes\n\t\t\t? child.conditions\n\t\t\t: [child],\n\t)\n\treturn Option.match(\n\t\tArr.findFirstIndex(flat, (child) => child._tag === constant),\n\t\t{\n\t\t\tonSome: (stop) => shortCircuit(tag, flat, stop),\n\t\t\tonNone: () => {\n\t\t\t\tconst kept = Arr.filter(flat, (child) => child._tag !== neutral)\n\t\t\t\tconst unique = Arr.some(kept, (child) => child.opaque)\n\t\t\t\t\t? kept\n\t\t\t\t\t: absorb(tag === \"And\" ? \"Or\" : \"And\", dedupe(kept))\n\t\t\t\treturn unique.length === 0\n\t\t\t\t\t? tag === \"And\"\n\t\t\t\t\t\t? always\n\t\t\t\t\t\t: never\n\t\t\t\t\t: unique.length === 1\n\t\t\t\t\t\t? unique[0]!\n\t\t\t\t\t\t: tag === \"And\"\n\t\t\t\t\t\t\t? new Nodes.And(unique)\n\t\t\t\t\t\t\t: new Nodes.Or(unique)\n\t\t\t},\n\t\t},\n\t)\n}\n\n/** An `And` of simple children, made simple. */\nexport const and = (children: ReadonlyArray<Node>): Node =>\n\tjunction(\"And\", children)\n\n/** An `Or` of simple children, made simple. */\nexport const or = (children: ReadonlyArray<Node>): Node =>\n\tjunction(\"Or\", children)\n\n/** A `Not` of a simple child, made simple. */\nexport const not = (child: Node): Node => {\n\tswitch (child._tag) {\n\t\tcase \"True\":\n\t\t\treturn never\n\t\tcase \"False\":\n\t\t\treturn always\n\t\tcase \"Not\":\n\t\t\treturn child.condition\n\t\tcase \"Compare\":\n\t\t\t// A principal field with no value makes `eq` and `ne` both false, so\n\t\t\t// only a fixed value lets `not eq` become `ne`.\n\t\t\treturn child.value._tag === \"Literal\" &&\n\t\t\t\t(child.op === \"eq\" || child.op === \"ne\")\n\t\t\t\t? new Nodes.Compare({\n\t\t\t\t\t\top: child.op === \"eq\" ? \"ne\" : \"eq\",\n\t\t\t\t\t\tfield: child.field,\n\t\t\t\t\t\tvalue: child.value,\n\t\t\t\t\t})\n\t\t\t\t: new Nodes.Not(child)\n\t\tdefault:\n\t\t\treturn new Nodes.Not(child)\n\t}\n}\n\ntype Step<A> = Trampoline.Step<A>\n\n/** The children of a node, each walked by `go` as a step of `R`. */\nconst eachChild = <A>(\n\tR: Trampoline.Runner,\n\tchildren: ReadonlyArray<Node>,\n\tgo: (child: Node) => Step<A>,\n): Step<ReadonlyArray<A>> =>\n\tR.forEach(children, (child) => R.suspend(() => go(child)))\n\n/** Makes a condition simple, from its leaves up. */\nexport const simplify = (node: Node): Node =>\n\tTrampoline.run(node.depth, (R) => {\n\t\tconst go = (current: Node): Step<Node> => {\n\t\t\tswitch (current._tag) {\n\t\t\t\tcase \"And\":\n\t\t\t\tcase \"Or\": {\n\t\t\t\t\tconst tag = current._tag\n\t\t\t\t\treturn R.map(eachChild(R, current.conditions, go), (children) =>\n\t\t\t\t\t\tjunction(tag, children),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tcase \"Not\":\n\t\t\t\t\treturn R.map(\n\t\t\t\t\t\tR.suspend(() => go(current.condition)),\n\t\t\t\t\t\tnot,\n\t\t\t\t\t)\n\t\t\t\tcase \"In\":\n\t\t\t\t\treturn R.succeed(current.values.length === 0 ? never : current)\n\t\t\t\tdefault:\n\t\t\t\t\treturn R.succeed(current)\n\t\t\t}\n\t\t}\n\t\treturn go(node)\n\t})\n\n// Tests on a value\n\n/** The data that a condition needs for a test. */\nexport interface Input {\n\treadonly value: object\n\treadonly principal?: object | undefined\n\treadonly path?: ReadonlyArray<Resource.PathSegment> | undefined\n}\n\n/**\n * Gets a field of a value by a path with dots. It reads only plain data: see\n * `readPart`. A missing field, or a field under a value that is not an object,\n * gives `null`.\n */\nconst getField = (value: unknown, path: string): unknown =>\n\treadPath(value, path.split(\".\"))\n\n/**\n * Gives the value of an operand. A principal field that is `null`, missing, or\n * not a scalar gives `undefined`. No field of a resource is `undefined`, so a\n * test with it is never true. This keeps the check closed: a principal with no\n * id never matches a resource with no owner.\n */\nconst resolve = (operand: Nodes.Operand, principal: unknown): unknown => {\n\tif (operand._tag === \"Literal\") {\n\t\treturn operand.value\n\t}\n\tconst value = getField(principal, operand.path)\n\treturn value !== null && Nodes.isScalar(value) ? value : undefined\n}\n\nexport const testCompare = (\n\top: Nodes.CompareOperator,\n\tleft: unknown,\n\tright: unknown,\n): boolean => {\n\tif (right === undefined) {\n\t\treturn false\n\t}\n\tswitch (op) {\n\t\tcase \"eq\":\n\t\t\treturn left === right\n\t\tcase \"ne\":\n\t\t\treturn left !== right\n\t\tdefault: {\n\t\t\tconst ordered =\n\t\t\t\t(typeof left === \"number\" && typeof right === \"number\") ||\n\t\t\t\t(typeof left === \"string\" && typeof right === \"string\")\n\t\t\tif (!ordered) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tconst a = left as number | string\n\t\t\tconst b = right as number | string\n\t\t\tswitch (op) {\n\t\t\t\tcase \"lt\":\n\t\t\t\t\treturn a < b\n\t\t\t\tcase \"lte\":\n\t\t\t\t\treturn a <= b\n\t\t\t\tcase \"gt\":\n\t\t\t\t\treturn a > b\n\t\t\t\tcase \"gte\":\n\t\t\t\t\treturn a >= b\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Gives the values of the path of a resource, or `undefined` for no path. */\nconst pathValues = (\n\tvalue: unknown,\n\tpath: ReadonlyArray<Resource.PathSegment> | undefined,\n): ReadonlyArray<unknown> | undefined =>\n\tpath?.map((segment) =>\n\t\ttypeof segment === \"string\" ? segment : getField(value, segment.field),\n\t)\n\nconst testUnder = (\n\tprefix: ReadonlyArray<Nodes.Operand>,\n\tinput: Input,\n): boolean => {\n\tconst values = pathValues(input.value, input.path)\n\tif (values === undefined || prefix.length > values.length) {\n\t\treturn false\n\t}\n\t// An operand with no value never matches, also a hole in a path that gives\n\t// `undefined` too.\n\treturn prefix.every((operand, index) => {\n\t\tconst value = resolve(operand, input.principal)\n\t\treturn value !== undefined && value === values[index]\n\t})\n}\n\n/**\n * The test of a simple condition with no predicate on a value, as a walk.\n * The children of `And` and `Or` run in order, and they stop at the first\n * child that gives the answer.\n */\nconst testWith = (input: Input) => (R: Trampoline.Runner) => {\n\tconst go = (node: Node): Step<boolean> => {\n\t\tswitch (node._tag) {\n\t\t\tcase \"True\":\n\t\t\t\treturn R.succeed(true)\n\t\t\tcase \"False\":\n\t\t\t\treturn R.succeed(false)\n\t\t\tcase \"Compare\":\n\t\t\t\treturn R.succeed(\n\t\t\t\t\ttestCompare(\n\t\t\t\t\t\tnode.op,\n\t\t\t\t\t\tgetField(input.value, node.field),\n\t\t\t\t\t\tresolve(node.value, input.principal),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\tcase \"In\": {\n\t\t\t\tconst field = getField(input.value, node.field)\n\t\t\t\treturn R.succeed(\n\t\t\t\t\tnode.values.some(\n\t\t\t\t\t\t(operand) => resolve(operand, input.principal) === field,\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t}\n\t\t\tcase \"Exists\":\n\t\t\t\treturn R.succeed(getField(input.value, node.field) !== null)\n\t\t\tcase \"Under\":\n\t\t\t\treturn R.succeed(testUnder(node.prefix, input))\n\t\t\tcase \"And\":\n\t\t\t\treturn R.every(node.conditions, (child) => R.suspend(() => go(child)))\n\t\t\tcase \"Or\":\n\t\t\t\treturn R.some(node.conditions, (child) => R.suspend(() => go(child)))\n\t\t\tcase \"Not\":\n\t\t\t\treturn R.map(\n\t\t\t\t\tR.suspend(() => go(node.condition)),\n\t\t\t\t\t(value) => !value,\n\t\t\t\t)\n\t\t\tcase \"Predicate\":\n\t\t\t\t// The types stop this. A predicate needs `evaluate`.\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The predicate \"${node.name}\" needs an Effect. Use Condition.evaluate.`,\n\t\t\t\t)\n\t\t}\n\t}\n\treturn go\n}\n\n/** Tests a simple condition with no predicate on a value. */\nconst testSync = (node: Node, input: Input): boolean =>\n\tTrampoline.run(node.depth, (R) => testWith(input)(R)(node))\n\n/**\n * Tests a simple condition on a value. The children of `And` and `Or` run in\n * order, and they stop at the first child that gives the answer. Each call\n * for a child is a step of the Effect, so a deep condition does not fill the\n * stack. A part with no predicate runs as a walk in the same loop.\n */\nconst test = (\n\tnode: Node,\n\tinput: Input,\n): Effect.Effect<boolean, unknown, unknown> => {\n\tif (!node.opaque) {\n\t\treturn node.depth <= Trampoline.directDepth\n\t\t\t? Effect.sync(() => testSync(node, input))\n\t\t\t: node.pipe(testWith(input)(Trampoline.loop), Trampoline.toEffect)\n\t}\n\tswitch (node._tag) {\n\t\tcase \"Predicate\":\n\t\t\treturn Nodes.runOf(node)(input.value, input.principal)\n\t\tcase \"Not\":\n\t\t\treturn Effect.map(\n\t\t\t\tEffect.suspend(() => test(node.condition, input)),\n\t\t\t\t(value) => !value,\n\t\t\t)\n\t\tcase \"And\":\n\t\t\treturn Effect.map(\n\t\t\t\tEffect.findFirst(node.conditions, (child) =>\n\t\t\t\t\tEffect.map(\n\t\t\t\t\t\tEffect.suspend(() => test(child, input)),\n\t\t\t\t\t\t(value) => !value,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t\tOption.isNone,\n\t\t\t)\n\t\tcase \"Or\":\n\t\t\treturn Effect.map(\n\t\t\t\tEffect.findFirst(node.conditions, (child) =>\n\t\t\t\t\tEffect.suspend(() => test(child, input)),\n\t\t\t\t),\n\t\t\t\tOption.isSome,\n\t\t\t)\n\t\tdefault:\n\t\t\treturn Effect.sync(() => testSync(node, input))\n\t}\n}\n\n/**\n * Tests a condition with no predicate on a value. The test runs on the\n * simple form of the condition with the principal in it, as a residual does.\n * So a test reads only the fields that the residual reads: a read of a field\n * that is not plain data is a defect, and a field that the answer does not\n * need, as in `x AND False`, is not read.\n */\nexport const evaluateSync = (node: Node, input: Input): boolean =>\n\ttestSync(partial(node, input), input)\n\n/** Tests a condition on a value, as {@link evaluateSync} does. */\nexport const evaluate = (\n\tnode: Node,\n\tinput: Input,\n): Effect.Effect<boolean, unknown, unknown> =>\n\tEffect.suspend(() => test(partial(node, input), input))\n\n// The principal and the path\n\n/**\n * Puts the value of the principal into an operand. It gives `undefined` for a\n * principal field with no value. See {@link resolve}.\n */\nconst bindOperand = (\n\toperand: Nodes.Operand,\n\tprincipal: unknown,\n): Nodes.Literal | undefined => {\n\tif (operand._tag === \"Literal\") {\n\t\treturn operand\n\t}\n\tconst value = resolve(operand, principal)\n\treturn value === undefined ? undefined : Nodes.literal(value as Nodes.Scalar)\n}\n\nconst expandUnder = (\n\tprefix: ReadonlyArray<Nodes.Operand>,\n\tprincipal: unknown,\n\tpath: ReadonlyArray<Resource.PathSegment> | undefined,\n): Node => {\n\tif (path === undefined || prefix.length > path.length) {\n\t\treturn never\n\t}\n\treturn and(\n\t\tArr.map(prefix, (operand, index): Node => {\n\t\t\tconst value = resolve(operand, principal)\n\t\t\tconst segment = path[index]!\n\t\t\treturn value === undefined\n\t\t\t\t? never\n\t\t\t\t: typeof segment === \"string\"\n\t\t\t\t\t? segment === value\n\t\t\t\t\t\t? always\n\t\t\t\t\t\t: never\n\t\t\t\t\t: new Nodes.Compare({\n\t\t\t\t\t\t\top: \"eq\",\n\t\t\t\t\t\t\tfield: segment.field,\n\t\t\t\t\t\t\tvalue: Nodes.literal(value as Nodes.Scalar),\n\t\t\t\t\t\t})\n\t\t}),\n\t)\n}\n\n/** The principal and the path of the resource, for {@link partial}. */\nexport interface PartialInput {\n\treadonly principal?: object | undefined\n\treadonly path?: ReadonlyArray<Resource.PathSegment> | undefined\n}\n\n/**\n * Puts the principal into a condition and expands `Under` with the path of the\n * resource. The result is simple. It has no principal fields and no `Under`\n * nodes. A predicate keeps the principal.\n */\nexport const partial = (node: Node, input: PartialInput): Node =>\n\tTrampoline.run(node.depth, (R) => {\n\t\tconst bind = (current: Node): Step<Node> => {\n\t\t\tswitch (current._tag) {\n\t\t\t\tcase \"Compare\": {\n\t\t\t\t\tconst value = bindOperand(current.value, input.principal)\n\t\t\t\t\treturn R.succeed(\n\t\t\t\t\t\tvalue === undefined\n\t\t\t\t\t\t\t? never\n\t\t\t\t\t\t\t: value === current.value\n\t\t\t\t\t\t\t\t? current\n\t\t\t\t\t\t\t\t: new Nodes.Compare({\n\t\t\t\t\t\t\t\t\t\top: current.op,\n\t\t\t\t\t\t\t\t\t\tfield: current.field,\n\t\t\t\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tcase \"In\": {\n\t\t\t\t\tconst values = Arr.flatMap(current.values, (operand) =>\n\t\t\t\t\t\tOption.toArray(\n\t\t\t\t\t\t\tOption.fromUndefinedOr(bindOperand(operand, input.principal)),\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\t\t\t\t\treturn R.succeed(\n\t\t\t\t\t\tvalues.length === 0\n\t\t\t\t\t\t\t? never\n\t\t\t\t\t\t\t: new Nodes.In({ field: current.field, values }),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tcase \"Under\":\n\t\t\t\t\treturn R.succeed(\n\t\t\t\t\t\texpandUnder(current.prefix, input.principal, input.path),\n\t\t\t\t\t)\n\t\t\t\tcase \"And\":\n\t\t\t\t\treturn R.map(eachChild(R, current.conditions, bind), and)\n\t\t\t\tcase \"Or\":\n\t\t\t\t\treturn R.map(eachChild(R, current.conditions, bind), or)\n\t\t\t\tcase \"Not\":\n\t\t\t\t\treturn R.map(\n\t\t\t\t\t\tR.suspend(() => bind(current.condition)),\n\t\t\t\t\t\tnot,\n\t\t\t\t\t)\n\t\t\t\tcase \"Predicate\": {\n\t\t\t\t\tconst run = Nodes.runOf(current)\n\t\t\t\t\treturn R.succeed(\n\t\t\t\t\t\tnew Nodes.Predicate({\n\t\t\t\t\t\t\tname: current.name,\n\t\t\t\t\t\t\trun: (value) => run(value, input.principal),\n\t\t\t\t\t\t}),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\treturn R.succeed(current)\n\t\t\t}\n\t\t}\n\t\treturn bind(node)\n\t})\n\n/** Gives the services in `context` to every predicate of a condition. */\nexport const provide = (node: Node, context: Context.Context<never>): Node =>\n\tTrampoline.run(node.depth, (R) => {\n\t\tconst go = (current: Node): Step<Node> => {\n\t\t\tif (!current.opaque) {\n\t\t\t\treturn R.succeed(current)\n\t\t\t}\n\t\t\tswitch (current._tag) {\n\t\t\t\tcase \"Predicate\": {\n\t\t\t\t\tconst run = Nodes.runOf(current)\n\t\t\t\t\treturn R.succeed(\n\t\t\t\t\t\tnew Nodes.Predicate({\n\t\t\t\t\t\t\tname: current.name,\n\t\t\t\t\t\t\trun: (value, principal) =>\n\t\t\t\t\t\t\t\tEffect.provideContext(run(value, principal), context),\n\t\t\t\t\t\t}),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tcase \"And\":\n\t\t\t\t\treturn R.map(\n\t\t\t\t\t\teachChild(R, current.conditions, go),\n\t\t\t\t\t\t(children) => new Nodes.And(children),\n\t\t\t\t\t)\n\t\t\t\tcase \"Or\":\n\t\t\t\t\treturn R.map(\n\t\t\t\t\t\teachChild(R, current.conditions, go),\n\t\t\t\t\t\t(children) => new Nodes.Or(children),\n\t\t\t\t\t)\n\t\t\t\tcase \"Not\":\n\t\t\t\t\treturn R.map(\n\t\t\t\t\t\tR.suspend(() => go(current.condition)),\n\t\t\t\t\t\t(child) => new Nodes.Not(child),\n\t\t\t\t\t)\n\t\t\t\tdefault:\n\t\t\t\t\treturn R.succeed(current)\n\t\t\t}\n\t\t}\n\t\treturn go(node)\n\t})\n\n/** The fields that a condition tests, in the order that they first come. */\nexport const fields = (node: Node): ReadonlyArray<string> => {\n\tconst all = Trampoline.run(node.depth, (R) => {\n\t\tconst go = (current: Node): Step<ReadonlyArray<string>> => {\n\t\t\tswitch (current._tag) {\n\t\t\t\tcase \"Compare\":\n\t\t\t\tcase \"In\":\n\t\t\t\tcase \"Exists\":\n\t\t\t\t\treturn R.succeed([current.field])\n\t\t\t\tcase \"And\":\n\t\t\t\tcase \"Or\":\n\t\t\t\t\treturn R.map(eachChild(R, current.conditions, go), Arr.flatten)\n\t\t\t\tcase \"Not\":\n\t\t\t\t\treturn R.suspend(() => go(current.condition))\n\t\t\t\tdefault:\n\t\t\t\t\treturn R.succeed([])\n\t\t\t}\n\t\t}\n\t\treturn go(node)\n\t})\n\t// A native `Set`, as in `dedupe`: a field of a condition that is not bound\n\t// to a domain may be any string.\n\treturn Array.from(new Set(all))\n}\n"],"mappings":"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"}