@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.
- package/README.md +56 -32
- package/dist/Authorizer.d.ts +21 -12
- package/dist/Authorizer.d.ts.map +1 -1
- package/dist/Authorizer.js.map +1 -1
- package/dist/Condition.d.ts +118 -18
- package/dist/Condition.d.ts.map +1 -1
- package/dist/Condition.js +27 -18
- package/dist/Condition.js.map +1 -1
- package/dist/Domain.d.ts +9 -0
- package/dist/Domain.d.ts.map +1 -1
- package/dist/Domain.js +5 -0
- package/dist/Domain.js.map +1 -1
- package/dist/Limits.d.ts +44 -13
- package/dist/Limits.d.ts.map +1 -1
- package/dist/Limits.js +52 -22
- package/dist/Limits.js.map +1 -1
- package/dist/Policy.d.ts +95 -12
- package/dist/Policy.d.ts.map +1 -1
- package/dist/Policy.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/internal/algebra.js +101 -74
- package/dist/internal/algebra.js.map +1 -1
- package/dist/internal/analysis.js +81 -75
- package/dist/internal/analysis.js.map +1 -1
- package/dist/internal/authorizer.d.ts.map +1 -1
- package/dist/internal/authorizer.js +16 -11
- package/dist/internal/authorizer.js.map +1 -1
- package/dist/internal/bind.js +119 -80
- package/dist/internal/bind.js.map +1 -1
- package/dist/internal/catalog.d.ts +33 -10
- package/dist/internal/catalog.d.ts.map +1 -1
- package/dist/internal/catalog.js +153 -78
- package/dist/internal/catalog.js.map +1 -1
- package/dist/internal/decide.js +25 -29
- package/dist/internal/decide.js.map +1 -1
- package/dist/internal/domain.js +19 -5
- package/dist/internal/domain.js.map +1 -1
- package/dist/internal/json.js +120 -76
- package/dist/internal/json.js.map +1 -1
- package/dist/internal/limits.d.ts +28 -0
- package/dist/internal/limits.d.ts.map +1 -1
- package/dist/internal/limits.js +75 -16
- package/dist/internal/limits.js.map +1 -1
- package/dist/internal/nodes.d.ts +7 -0
- package/dist/internal/nodes.d.ts.map +1 -1
- package/dist/internal/nodes.js +86 -47
- package/dist/internal/nodes.js.map +1 -1
- package/dist/internal/patterns.js +50 -15
- package/dist/internal/patterns.js.map +1 -1
- package/dist/internal/policy-json.js +169 -127
- package/dist/internal/policy-json.js.map +1 -1
- package/dist/internal/policy-nodes.d.ts.map +1 -1
- package/dist/internal/policy-nodes.js +17 -14
- package/dist/internal/policy-nodes.js.map +1 -1
- package/dist/internal/policy.d.ts.map +1 -1
- package/dist/internal/policy.js +38 -22
- package/dist/internal/policy.js.map +1 -1
- package/dist/internal/resource.js +1 -1
- package/dist/internal/rule.d.ts.map +1 -1
- package/dist/internal/rule.js +6 -5
- package/dist/internal/rule.js.map +1 -1
- package/dist/internal/search.d.ts.map +1 -1
- package/dist/internal/search.js +106 -92
- package/dist/internal/search.js.map +1 -1
- package/dist/internal/trampoline.js +89 -0
- package/dist/internal/trampoline.js.map +1 -0
- package/package.json +1 -1
- package/src/Authorizer.ts +30 -20
- package/src/Condition.ts +308 -83
- package/src/Domain.ts +9 -0
- package/src/Limits.ts +69 -29
- package/src/Policy.ts +131 -15
- package/src/internal/algebra.ts +218 -135
- package/src/internal/analysis.ts +154 -122
- package/src/internal/authorizer.ts +34 -16
- package/src/internal/bind.ts +279 -148
- package/src/internal/catalog.ts +307 -133
- package/src/internal/decide.ts +58 -49
- package/src/internal/domain.ts +39 -3
- package/src/internal/json.ts +212 -117
- package/src/internal/limits.ts +101 -31
- package/src/internal/nodes.ts +101 -59
- package/src/internal/patterns.ts +72 -26
- package/src/internal/policy-json.ts +266 -197
- package/src/internal/policy-nodes.ts +33 -24
- package/src/internal/policy.ts +63 -23
- package/src/internal/rule.ts +16 -3
- package/src/internal/search.ts +186 -136
- package/src/internal/trampoline.ts +194 -0
package/dist/internal/algebra.js
CHANGED
|
@@ -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
|
|
12
|
-
*
|
|
13
|
-
*
|
|
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
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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
|
-
/**
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
return
|
|
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
|
-
|
|
227
|
-
|
|
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
|
|
304
|
-
case "Or": return
|
|
305
|
-
case "Not": return
|
|
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
|
-
|
|
321
|
-
|
|
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 "
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
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
|
|
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":";;;;;;;;;;;;;;AAqBA,MAAM,EAAE,QAAQ,UAAUA;;AAK1B,MAAM,eAAe,YACpB,QAAQ,SAAS,YACd,CAAC,OAAO,QAAQ,OAAO,OAAO,QAAQ,KAAK,CAAC,IAC5C,CAAC,aAAa,QAAQ,IAAI;;AAG9B,MAAM,WAAW,SAAwB;CACxC,QAAQ,KAAK,MAAb;EACC,KAAK;EACL,KAAK,SACJ,OAAO,CAAC,KAAK,IAAI;EAClB,KAAK,WACJ,OAAO;GAAC,KAAK;GAAM,KAAK;GAAI,KAAK;GAAO,YAAY,KAAK,KAAK;EAAC;EAChE,KAAK,MACJ,OAAO;GAAC,KAAK;GAAM,KAAK;GAAO,IAAI,IAAI,KAAK,QAAQ,WAAW;EAAC;EACjE,KAAK,UACJ,OAAO,CAAC,KAAK,MAAM,KAAK,KAAK;EAC9B,KAAK,SACJ,OAAO,CAAC,KAAK,MAAM,IAAI,IAAI,KAAK,QAAQ,WAAW,CAAC;EACrD,KAAK;EACL,KAAK,MACJ,OAAO,CAAC,KAAK,MAAM,IAAI,IAAI,KAAK,YAAY,OAAO,CAAC;EACrD,KAAK,OACJ,OAAO,CAAC,KAAK,MAAM,QAAQ,KAAK,SAAS,CAAC;EAC3C,KAAK,aAGJ,MAAM,IAAI,MAAM,sCAAsC;CACxD;AACD;;;;;;AAOA,MAAM,iBAAiB,SAAuB,KAAK,UAAU,QAAQ,IAAI,CAAC;;;;;;;AAQ1E,MAAM,YAAY,SAAuB;CACxC,QAAQ,KAAK,MAAb;EACC,KAAK,MACJ,OAAO,IAAI,KAAK,OAAO;EACxB,KAAK,SACJ,OAAO,IAAI,KAAK,OAAO;EACxB,KAAK;EACL,KAAK,MACJ,OAAO,IAAI,OACV,KAAK,YACL,IACC,OAAO,UAAU,QAAQ,SAAS,KAAK,CACzC;EACD,KAAK,OACJ,OAAO,IAAI,SAAS,KAAK,SAAS;EACnC,SACC,OAAO;CACT;AACD;;;;;;;;AASA,MAAM,WAAW;;AAGjB,MAAM,YAAY;;;;;;;;;AAUlB,MAAa,SAAS,SACrB,KAAK,OAAO,YAAY,SAAS,IAAI,IAAI,YACtC,OACA,cAAc,IAAI;;;;;AAMtB,MAAM,UAAU,UAAoD;CAEnE,MAAM,uBAAO,IAAI,IAAmB;CACpC,OAAO,IAAI,OAAO,QAAQ,SAAS;EAClC,MAAM,MAAM,MAAM,IAAI;EACtB,IAAI,KAAK,IAAI,GAAG,GACf,OAAO;EAER,KAAK,IAAI,GAAG;EACZ,OAAO;CACR,CAAC;AACF;;;;;AAMA,MAAM,UACL,OACA,UACyB;CAEzB,MAAM,MAAM,IAAI,IAAI,IAAI,IAAI,OAAO,KAAK,CAAC;CACzC,OAAO,IAAI,OACV,QACC,SACA,KAAK,SAAS,SACd,CAAC,IAAI,KAAK,KAAK,aAAa,SAAS,IAAI,IAAI,MAAM,IAAI,CAAC,CAAC,CAC3D;AACD;;;;;;;AAUA,MAAM,gBACL,KACA,UACA,UACU;CACV,MAAM,WAAW,QAAQ,QAAQ,QAAQ;CACzC,MAAM,UAAU,QAAQ,QAAQ,SAAS;CACzC,MAAM,SAAS,IAAI,OAClB,IAAI,KAAK,UAAU,KAAK,IACvB,UAAU,MAAM,SAAS,OAC3B;CACA,IAAI,CAAC,IAAI,KAAK,SAAS,UAAU,MAAM,MAAM,GAC5C,OAAO;CAER,OAAO,QAAQ,QACZ,IAAIC,IAAU,CAAC,GAAG,QAAQ,QAAQ,CAAC,IACnC,IAAIC,GAAS,CAAC,GAAG,QAAQ,QAAQ,CAAC;AACtC;;;;;;;;;;;;;;AAeA,MAAM,YAAY,KAAmB,aAAwC;CAC5E,MAAM,WAAW,QAAQ,QAAQ,UAAU;CAC3C,MAAM,UAAU,QAAQ,QAAQ,SAAS;CACzC,MAAM,OAAO,IAAI,QAAQ,WAAW,UACnC,MAAM,SAAS,OAAO,CAAC,MAAM,UAAU,MAAM,WAAW,UAAU,WAC/D,MAAM,aACN,CAAC,KAAK,CACV;CACA,OAAO,OAAO,MACb,IAAI,eAAe,OAAO,UAAU,MAAM,SAAS,QAAQ,GAC3D;EACC,SAAS,SAAS,aAAa,KAAK,MAAM,IAAI;EAC9C,cAAc;GACb,MAAM,OAAO,IAAI,OAAO,OAAO,UAAU,MAAM,SAAS,OAAO;GAC/D,MAAM,SAAS,IAAI,KAAK,OAAO,UAAU,MAAM,MAAM,IAClD,OACA,OAAO,QAAQ,QAAQ,OAAO,OAAO,OAAO,IAAI,CAAC;GACpD,OAAO,OAAO,WAAW,IACtB,QAAQ,QACP,SACA,QACD,OAAO,WAAW,IACjB,OAAO,KACP,QAAQ,QACP,IAAID,IAAU,MAAM,IACpB,IAAIC,GAAS,MAAM;EACzB;CACD,CACD;AACD;;AAGA,MAAa,OAAO,aACnB,SAAS,OAAO,QAAQ;;AAGzB,MAAa,MAAM,aAClB,SAAS,MAAM,QAAQ;;AAGxB,MAAa,OAAO,UAAsB;CACzC,QAAQ,MAAM,MAAd;EACC,KAAK,QACJ,OAAO;EACR,KAAK,SACJ,OAAO;EACR,KAAK,OACJ,OAAO,MAAM;EACd,KAAK,WAGJ,OAAO,MAAM,MAAM,SAAS,cAC1B,MAAM,OAAO,QAAQ,MAAM,OAAO,QACjC,IAAIC,QAAc;GAClB,IAAI,MAAM,OAAO,OAAO,OAAO;GAC/B,OAAO,MAAM;GACb,OAAO,MAAM;EACd,CAAC,IACA,IAAIC,IAAU,KAAK;EACvB,SACC,OAAO,IAAIA,IAAU,KAAK;CAC5B;AACD;;AAGA,MAAa,YAAY,SAAqB;CAC7C,QAAQ,KAAK,MAAb;EACC,KAAK;EACL,KAAK,MACJ,OAAO,SAAS,KAAK,MAAM,IAAI,IAAI,KAAK,YAAY,QAAQ,CAAC;EAC9D,KAAK,OACJ,OAAO,KAAK,UAAU,KAAK,UAAU,GAAG;EACzC,KAAK,MACJ,OAAO,KAAK,OAAO,WAAW,IAAI,QAAQ;EAC3C,SACC,OAAO;CACT;AACD;;;;;;AAgBA,MAAM,YAAY,OAAgB,SACjC,SAAS,OAAO,KAAK,MAAM,GAAG,CAAC;;;;;;;AAQhC,MAAM,WAAW,SAAwB,cAAgC;CACxE,IAAI,QAAQ,SAAS,WACpB,OAAO,QAAQ;CAEhB,MAAM,QAAQ,SAAS,WAAW,QAAQ,IAAI;CAC9C,OAAO,UAAU,QAAQC,SAAe,KAAK,IAAI,QAAQ,KAAA;AAC1D;AAEA,MAAa,eACZ,IACA,MACA,UACa;CACb,IAAI,UAAU,KAAA,GACb,OAAO;CAER,QAAQ,IAAR;EACC,KAAK,MACJ,OAAO,SAAS;EACjB,KAAK,MACJ,OAAO,SAAS;EACjB,SAAS;GAIR,IAAI,EAFF,OAAO,SAAS,YAAY,OAAO,UAAU,YAC7C,OAAO,SAAS,YAAY,OAAO,UAAU,WAE9C,OAAO;GAER,MAAM,IAAI;GACV,MAAM,IAAI;GACV,QAAQ,IAAR;IACC,KAAK,MACJ,OAAO,IAAI;IACZ,KAAK,OACJ,OAAO,KAAK;IACb,KAAK,MACJ,OAAO,IAAI;IACZ,KAAK,OACJ,OAAO,KAAK;GACd;EACD;CACD;AACD;;AAGA,MAAM,cACL,OACA,SAEA,MAAM,KAAK,YACV,OAAO,YAAY,WAAW,UAAU,SAAS,OAAO,QAAQ,KAAK,CACtE;AAED,MAAM,aACL,QACA,UACa;CACb,MAAM,SAAS,WAAW,MAAM,OAAO,MAAM,IAAI;CACjD,IAAI,WAAW,KAAA,KAAa,OAAO,SAAS,OAAO,QAClD,OAAO;CAIR,OAAO,OAAO,OAAO,SAAS,UAAU;EACvC,MAAM,QAAQ,QAAQ,SAAS,MAAM,SAAS;EAC9C,OAAO,UAAU,KAAA,KAAa,UAAU,OAAO;CAChD,CAAC;AACF;;AAGA,MAAM,YAAY,MAAY,UAA0B;CACvD,QAAQ,KAAK,MAAb;EACC,KAAK,QACJ,OAAO;EACR,KAAK,SACJ,OAAO;EACR,KAAK,WACJ,OAAO,YACN,KAAK,IACL,SAAS,MAAM,OAAO,KAAK,KAAK,GAChC,QAAQ,KAAK,OAAO,MAAM,SAAS,CACpC;EACD,KAAK,MAAM;GACV,MAAM,QAAQ,SAAS,MAAM,OAAO,KAAK,KAAK;GAC9C,OAAO,KAAK,OAAO,MACjB,YAAY,QAAQ,SAAS,MAAM,SAAS,MAAM,KACpD;EACD;EACA,KAAK,UACJ,OAAO,SAAS,MAAM,OAAO,KAAK,KAAK,MAAM;EAC9C,KAAK,SACJ,OAAO,UAAU,KAAK,QAAQ,KAAK;EACpC,KAAK,OACJ,OAAO,IAAI,MAAM,KAAK,aAAa,UAAU,SAAS,OAAO,KAAK,CAAC;EACpE,KAAK,MACJ,OAAO,IAAI,KAAK,KAAK,aAAa,UAAU,SAAS,OAAO,KAAK,CAAC;EACnE,KAAK,OACJ,OAAO,CAAC,SAAS,KAAK,WAAW,KAAK;EACvC,KAAK,aAEJ,MAAM,IAAI,MACT,kBAAkB,KAAK,KAAK,2CAC7B;CACF;AACD;;;;;AAMA,MAAM,QACL,MACA,UAC8C;CAC9C,IAAI,CAAC,KAAK,QACT,OAAO,OAAO,WAAW,SAAS,MAAM,KAAK,CAAC;CAE/C,QAAQ,KAAK,MAAb;EACC,KAAK,aACJ,OAAOC,MAAY,IAAI,CAAC,CAAC,MAAM,OAAO,MAAM,SAAS;EACtD,KAAK,OACJ,OAAO,OAAO,IAAI,KAAK,KAAK,WAAW,KAAK,IAAI,UAAU,CAAC,KAAK;EACjE,KAAK,OACJ,OAAO,OAAO,IACb,OAAO,UAAU,KAAK,aAAa,UAClC,OAAO,IAAI,KAAK,OAAO,KAAK,IAAI,UAAU,CAAC,KAAK,CACjD,GACA,OAAO,MACR;EACD,KAAK,MACJ,OAAO,OAAO,IACb,OAAO,UAAU,KAAK,aAAa,UAAU,KAAK,OAAO,KAAK,CAAC,GAC/D,OAAO,MACR;EACD,SACC,OAAO,OAAO,WAAW,SAAS,MAAM,KAAK,CAAC;CAChD;AACD;;;;;;;;AASA,MAAa,gBAAgB,MAAY,UACxC,SAAS,QAAQ,MAAM,KAAK,GAAG,KAAK;;AAGrC,MAAa,YACZ,MACA,UAEA,OAAO,cAAc,KAAK,QAAQ,MAAM,KAAK,GAAG,KAAK,CAAC;;;;;AAQvD,MAAM,eACL,SACA,cAC+B;CAC/B,IAAI,QAAQ,SAAS,WACpB,OAAO;CAER,MAAM,QAAQ,QAAQ,SAAS,SAAS;CACxC,OAAO,UAAU,KAAA,IAAY,KAAA,IAAYC,QAAc,KAAqB;AAC7E;AAEA,MAAM,eACL,QACA,WACA,SACU;CACV,IAAI,SAAS,KAAA,KAAa,OAAO,SAAS,KAAK,QAC9C,OAAO;CAER,OAAO,IACN,IAAI,IAAI,SAAS,SAAS,UAAgB;EACzC,MAAM,QAAQ,QAAQ,SAAS,SAAS;EACxC,MAAM,UAAU,KAAK;EACrB,OAAO,UAAU,KAAA,IACd,QACA,OAAO,YAAY,WAClB,YAAY,QACX,SACA,QACD,IAAIJ,QAAc;GAClB,IAAI;GACJ,OAAO,QAAQ;GACf,OAAOI,QAAc,KAAqB;EAC3C,CAAC;CACL,CAAC,CACF;AACD;;;;;;AAaA,MAAa,WAAW,MAAY,UAA8B;CACjE,MAAM,QAAQ,YAAwB;EACrC,QAAQ,QAAQ,MAAhB;GACC,KAAK,WAAW;IACf,MAAM,QAAQ,YAAY,QAAQ,OAAO,MAAM,SAAS;IACxD,OAAO,UAAU,KAAA,IACd,QACA,UAAU,QAAQ,QACjB,UACA,IAAIJ,QAAc;KAAE,IAAI,QAAQ;KAAI,OAAO,QAAQ;KAAO;IAAM,CAAC;GACtE;GACA,KAAK,MAAM;IACV,MAAM,SAAS,IAAI,QAAQ,QAAQ,SAAS,YAC3C,OAAO,QACN,OAAO,gBAAgB,YAAY,SAAS,MAAM,SAAS,CAAC,CAC7D,CACD;IACA,OAAO,OAAO,WAAW,IACtB,QACA,IAAIK,GAAS;KAAE,OAAO,QAAQ;KAAO;IAAO,CAAC;GACjD;GACA,KAAK,SACJ,OAAO,YAAY,QAAQ,QAAQ,MAAM,WAAW,MAAM,IAAI;GAC/D,KAAK,OACJ,OAAO,IAAI,IAAI,IAAI,QAAQ,YAAY,IAAI,CAAC;GAC7C,KAAK,MACJ,OAAO,GAAG,IAAI,IAAI,QAAQ,YAAY,IAAI,CAAC;GAC5C,KAAK,OACJ,OAAO,QAAQ,UAAU,KAAK,MAAM,GAAG;GACxC,KAAK,aAAa;IACjB,MAAM,MAAMF,MAAY,OAAO;IAC/B,OAAO,IAAIG,UAAgB;KAC1B,MAAM,QAAQ;KACd,MAAM,UAAU,IAAI,OAAO,MAAM,SAAS;IAC3C,CAAC;GACF;GACA,SACC,OAAO;EACT;CACD;CACA,OAAO,KAAK,IAAI;AACjB;;AAGA,MAAa,WAAW,MAAY,YAA0C;CAC7E,IAAI,CAAC,KAAK,QACT,OAAO;CAER,QAAQ,KAAK,MAAb;EACC,KAAK,aAAa;GACjB,MAAM,MAAMH,MAAY,IAAI;GAC5B,OAAO,IAAIG,UAAgB;IAC1B,MAAM,KAAK;IACX,MAAM,OAAO,cACZ,OAAO,eAAe,IAAI,OAAO,SAAS,GAAG,OAAO;GACtD,CAAC;EACF;EACA,KAAK,OACJ,OAAO,IAAIR,IACV,IAAI,IAAI,KAAK,aAAa,UAAU,QAAQ,OAAO,OAAO,CAAC,CAC5D;EACD,KAAK,MACJ,OAAO,IAAIC,GACV,IAAI,IAAI,KAAK,aAAa,UAAU,QAAQ,OAAO,OAAO,CAAC,CAC5D;EACD,KAAK,OACJ,OAAO,IAAIE,IAAU,QAAQ,KAAK,WAAW,OAAO,CAAC;EACtD,SACC,OAAO;CACT;AACD;;AAGA,MAAa,UAAU,SAAsC;CAC5D,MAAM,OAAO,YAAyC;EACrD,QAAQ,QAAQ,MAAhB;GACC,KAAK;GACL,KAAK;GACL,KAAK,UACJ,OAAO,CAAC,QAAQ,KAAK;GACtB,KAAK;GACL,KAAK,MACJ,OAAO,IAAI,QAAQ,QAAQ,YAAY,GAAG;GAC3C,KAAK,OACJ,OAAO,IAAI,QAAQ,SAAS;GAC7B,SACC,OAAO,CAAC;EACV;CACD;CAGA,OAAO,MAAM,KAAK,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC;AACrC"}
|
|
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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"}
|