@nmnmcc/ability 0.3.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +169 -14
  2. package/dist/Authorizer.d.ts +64 -39
  3. package/dist/Authorizer.d.ts.map +1 -1
  4. package/dist/Authorizer.js +291 -6
  5. package/dist/Authorizer.js.map +1 -1
  6. package/dist/Condition.d.ts +444 -65
  7. package/dist/Condition.d.ts.map +1 -1
  8. package/dist/Condition.js +1007 -25
  9. package/dist/Condition.js.map +1 -1
  10. package/dist/Domain.d.ts +27 -17
  11. package/dist/Domain.d.ts.map +1 -1
  12. package/dist/Domain.js +52 -10
  13. package/dist/Domain.js.map +1 -1
  14. package/dist/HttpApi.d.ts +84 -40
  15. package/dist/HttpApi.d.ts.map +1 -1
  16. package/dist/HttpApi.js +101 -11
  17. package/dist/HttpApi.js.map +1 -1
  18. package/dist/Policy.d.ts +311 -53
  19. package/dist/Policy.d.ts.map +1 -1
  20. package/dist/Policy.js +1212 -35
  21. package/dist/Policy.js.map +1 -1
  22. package/dist/Resource.d.ts +167 -16
  23. package/dist/Resource.d.ts.map +1 -1
  24. package/dist/Resource.js +784 -11
  25. package/dist/Resource.js.map +1 -1
  26. package/dist/Rule.d.ts +113 -27
  27. package/dist/Rule.d.ts.map +1 -1
  28. package/dist/Rule.js +217 -10
  29. package/dist/Rule.js.map +1 -1
  30. package/dist/index.js +4 -4
  31. package/package.json +1 -1
  32. package/src/Authorizer.ts +623 -59
  33. package/src/Condition.ts +2403 -112
  34. package/src/Domain.ts +79 -22
  35. package/src/HttpApi.ts +223 -23
  36. package/src/Policy.ts +2833 -93
  37. package/src/Resource.ts +1537 -22
  38. package/src/Rule.ts +461 -43
  39. package/dist/internal/authorizer.d.ts +0 -28
  40. package/dist/internal/authorizer.d.ts.map +0 -1
  41. package/dist/internal/authorizer.js +0 -153
  42. package/dist/internal/authorizer.js.map +0 -1
  43. package/dist/internal/condition.d.ts +0 -11
  44. package/dist/internal/condition.d.ts.map +0 -1
  45. package/dist/internal/condition.js +0 -393
  46. package/dist/internal/condition.js.map +0 -1
  47. package/dist/internal/domain.js +0 -34
  48. package/dist/internal/domain.js.map +0 -1
  49. package/dist/internal/httpApi.js +0 -41
  50. package/dist/internal/httpApi.js.map +0 -1
  51. package/dist/internal/policy.js +0 -524
  52. package/dist/internal/policy.js.map +0 -1
  53. package/dist/internal/resource.js +0 -66
  54. package/dist/internal/resource.js.map +0 -1
  55. package/dist/internal/rule.js +0 -131
  56. package/dist/internal/rule.js.map +0 -1
  57. package/src/internal/authorizer.ts +0 -271
  58. package/src/internal/condition.ts +0 -607
  59. package/src/internal/domain.ts +0 -56
  60. package/src/internal/httpApi.ts +0 -84
  61. package/src/internal/policy.ts +0 -815
  62. package/src/internal/resource.ts +0 -98
  63. package/src/internal/rule.ts +0 -203
@@ -1,9 +1,20 @@
1
1
  import { PathSegment } from "./Resource.js";
2
- import { Untranslatable as Untranslatable$1 } from "./internal/condition.js";
2
+ import * as Context from "effect/Context";
3
3
  import * as Effect from "effect/Effect";
4
+ import * as Option from "effect/Option";
4
5
  import * as Schema from "effect/Schema";
6
+ import * as Data from "effect/Data";
7
+ import * as HashMap from "effect/HashMap";
8
+ import * as HashSet from "effect/HashSet";
9
+ import * as Chunk from "effect/Chunk";
10
+ import * as Duration from "effect/Duration";
11
+ import * as BigDecimal from "effect/BigDecimal";
12
+ import * as Cause from "effect/Cause";
13
+ import * as DateTime from "effect/DateTime";
14
+ import * as Redacted from "effect/Redacted";
15
+ import * as Result from "effect/Result";
5
16
  declare namespace Condition_d_exports {
6
- export { And, Any, Ast, Builder, Compare, CompareOperator, Condition, Encoded, EncodedAnd, EncodedNot, EncodedOr, Error, Exists, False, FieldPath, In, Input, Interpreter, Literal, Not, Opaque, OpaqueOf, Operand, OperandOf, Or, PathValue, Predicate, PrincipalRef, Ref, Scalar, Services, True, Under, Untranslatable, Variance, always, and, builder, evaluate, evaluateSync, fields, fold, never, not, or, partial, schema, simplify };
17
+ export { And, AndCondition, Any, Ast, Builder, Checked, Compare, CompareOperator, Condition, Encoded, EncodedAnd, EncodedNot, EncodedOr, Error, Example, Exists, False, FieldPath, FieldSelector, FieldValue, In, Input, Interpreter, Literal, Marks, Not, NotCondition, Opaque, OpaqueOf, Operand, OperandOf, Or, OrCondition, PathValue, PlainCondition, Predicate, PredicateCondition, PredicateRun, PrincipalRef, Reads, ReadsOf, Ref, Satisfiability, SatisfiableOptions, Scalar, Services, Test, True, Under, Untranslatable, Variance, always, and, andAll, builder, evaluate, evaluateSync, fields, fold, hasPredicate, isAst, never, not, or, orAll, partial, provideContext, satisfiable, schema, simplifier, simplify, toJsonValue };
7
18
  }
8
19
  /**
9
20
  * A value that a condition can compare.
@@ -42,14 +53,20 @@ export interface PrincipalRef {
42
53
  readonly path: string;
43
54
  }
44
55
  /**
45
- * A field of the principal with a known value type.
56
+ * A field of the principal with a known value type `A`, from a principal of
57
+ * the type `P`. The type fields are only in the types. A reference with no
58
+ * type does not have them, so it can not stand for a field of any type. A
59
+ * test with the reference reads a principal of the type `P`, so it can not go
60
+ * into a rule of a domain with another principal. With no `P`, it is `never`,
61
+ * and a test with the reference fits no rule.
46
62
  *
47
63
  * @stability stable
48
64
  * @category models
49
65
  * @since 0.3.0
50
66
  */
51
- export type Ref<A> = PrincipalRef & {
52
- readonly "~Ref"?: () => A;
67
+ export type Ref<A, P = never> = PrincipalRef & {
68
+ readonly "~Ref": () => A;
69
+ readonly "~Principal": (principal: P) => void;
53
70
  };
54
71
  /**
55
72
  * @stability stable
@@ -170,7 +187,7 @@ export interface Not {
170
187
  export interface Predicate {
171
188
  readonly _tag: "Predicate";
172
189
  readonly name: string;
173
- readonly run: (value: any, principal: any) => Effect.Effect<boolean, unknown, unknown>;
190
+ run(value: any, principal: any): Effect.Effect<boolean, unknown, unknown>;
174
191
  }
175
192
  /**
176
193
  * The nodes of a condition, without types.
@@ -198,18 +215,112 @@ export interface Variance<E, R, O> {
198
215
  readonly R: () => R;
199
216
  readonly O: () => O;
200
217
  }
218
+ /**
219
+ * What the predicates of a condition read: a resource value of the type `V`
220
+ * and a principal of the type `P`. It is only in the types.
221
+ *
222
+ * @stability stable
223
+ * @category models
224
+ * @since 1.0.0
225
+ */
226
+ export interface Reads<V, P> {
227
+ readonly value: V;
228
+ readonly principal: P;
229
+ }
230
+ /**
231
+ * The type fields of a condition. They are only in the types.
232
+ *
233
+ * @stability stable
234
+ * @category models
235
+ * @since 1.0.0
236
+ */
237
+ export interface Marks<E, R, O, I> {
238
+ readonly "~Condition": Variance<E, R, O>;
239
+ /** `I` is what the predicates read. See {@link Reads}. */
240
+ readonly "~Reads": (reads: I) => void;
241
+ }
242
+ /**
243
+ * An `And` node with the types of its children.
244
+ *
245
+ * @stability stable
246
+ * @category models
247
+ * @since 1.0.0
248
+ */
249
+ export interface AndCondition<E, R, O, I> extends Marks<E, R, O, I> {
250
+ readonly _tag: "And";
251
+ readonly conditions: ReadonlyArray<Condition<E, R, O, I>>;
252
+ }
253
+ /**
254
+ * An `Or` node with the types of its children.
255
+ *
256
+ * @stability stable
257
+ * @category models
258
+ * @since 1.0.0
259
+ */
260
+ export interface OrCondition<E, R, O, I> extends Marks<E, R, O, I> {
261
+ readonly _tag: "Or";
262
+ readonly conditions: ReadonlyArray<Condition<E, R, O, I>>;
263
+ }
264
+ /**
265
+ * A `Not` node with the types of its child.
266
+ *
267
+ * @stability stable
268
+ * @category models
269
+ * @since 1.0.0
270
+ */
271
+ export interface NotCondition<E, R, O, I> extends Marks<E, R, O, I> {
272
+ readonly _tag: "Not";
273
+ readonly condition: Condition<E, R, O, I>;
274
+ }
275
+ /**
276
+ * A predicate node with its types. `"~Predicate"` is only in the types. It has
277
+ * the type `O`, so a plain condition, with `O` as `never`, can not be a
278
+ * predicate. The builder makes predicates with `O` as {@link Opaque}.
279
+ *
280
+ * @stability stable
281
+ * @category models
282
+ * @since 1.0.0
283
+ */
284
+ export interface PredicateCondition<E, R, O, I> extends Marks<E, R, O, I> {
285
+ readonly _tag: "Predicate";
286
+ readonly name: string;
287
+ /**
288
+ * The test. Its inputs have the type `never`, so it can not be called with
289
+ * a value that it does not read. Use {@link evaluate}, which checks the
290
+ * input against `I`.
291
+ */
292
+ readonly run: PredicateRun<E, R, I>;
293
+ readonly "~Predicate": O;
294
+ }
295
+ /**
296
+ * The test of a predicate node. The type field `"~Reads"` is only in the
297
+ * types. It ties the test to what it reads, so the test of one predicate can
298
+ * not go into a node that says it reads other values.
299
+ *
300
+ * @stability stable
301
+ * @category models
302
+ * @since 1.0.0
303
+ */
304
+ export type PredicateRun<E, R, I> = ((value: never, principal: never) => Effect.Effect<boolean, E, R>) & {
305
+ readonly "~Reads": (reads: I) => void;
306
+ };
201
307
  /**
202
308
  * A condition. `E` and `R` are the error type and the service type of its
203
309
  * predicates. `O` is {@link Opaque} when the condition has a predicate, and
204
- * `never` when it is plain data.
310
+ * `never` when it is plain data. `I` is what its predicates read. See
311
+ * {@link Reads}.
312
+ *
313
+ * The type fields are only in the types. A plain node made by hand does not
314
+ * have them, so it is not a condition. Use the builder. Each child of a node
315
+ * is a condition with the same types, so a node can not hide the types of a
316
+ * predicate inside it. A predicate is a condition only when `O` is
317
+ * {@link Opaque}.
205
318
  *
206
319
  * @stability stable
207
320
  * @category models
208
321
  * @since 0.3.0
209
322
  */
210
- export type Condition<E = never, R = never, O = never> = Ast & {
211
- readonly "~Condition"?: Variance<E, R, O>;
212
- };
323
+ export type Condition<E = never, R = never, O = never, I = unknown> = ((True | False | Compare | In | Exists | Under) & Marks<E, R, O, I>) | AndCondition<E, R, O, I> | OrCondition<E, R, O, I> | NotCondition<E, R, O, I> | PredicateCondition<E, R, O, I>;
213
324
  /**
214
325
  * Any condition.
215
326
  *
@@ -217,7 +328,7 @@ export type Condition<E = never, R = never, O = never> = Ast & {
217
328
  * @category models
218
329
  * @since 0.3.0
219
330
  */
220
- export type Any = Condition<any, any, any>;
331
+ export type Any = Condition<any, any, any, any>;
221
332
  /**
222
333
  * The error type of a condition.
223
334
  *
@@ -238,6 +349,34 @@ export type Error<C> = C extends {
238
349
  export type Services<C> = C extends {
239
350
  readonly "~Condition"?: Variance<infer _E, infer R, infer _O>;
240
351
  } ? R : never;
352
+ /**
353
+ * What the predicates of a condition read. For a union of conditions, it is
354
+ * what all of them read.
355
+ *
356
+ * @stability stable
357
+ * @category utility types
358
+ * @since 1.0.0
359
+ */
360
+ export type ReadsOf<C> = [C] extends [{
361
+ readonly "~Reads": (reads: infer I) => void;
362
+ }] ? I : unknown;
363
+ /**
364
+ * `unknown` when a condition is a condition of its own type fields: each of
365
+ * its children has them too. A node made with a spread may keep the type
366
+ * fields of another node, and then it is `never`, so the call stops.
367
+ *
368
+ * @stability stable
369
+ * @category utility types
370
+ * @since 1.0.0
371
+ */
372
+ export type Checked<C> = [NotChecked<C>] extends [never] ? unknown : never;
373
+ /**
374
+ * The members of a union of conditions that do not fit their own type fields.
375
+ * Each member is checked alone, so a good member does not hide a bad one.
376
+ */
377
+ type NotChecked<C> = C extends Condition<Error<C>, Services<C>, OpaqueOf<C>, ReadsOf<C>> ? never : C;
378
+ /** Each condition, checked with {@link Checked}. */
379
+ type Consistent<Cs extends ReadonlyArray<Any>> = { readonly [K in keyof Cs]: Cs[K] & Checked<Cs[K]>; };
241
380
  /**
242
381
  * {@link Opaque} when a condition has a predicate.
243
382
  *
@@ -249,11 +388,19 @@ export type OpaqueOf<C> = C extends {
249
388
  readonly "~Condition"?: Variance<infer _E, infer _R, infer O>;
250
389
  } ? O : never;
251
390
  type Leaf = string | number | boolean | bigint | symbol | null | undefined;
391
+ /**
392
+ * Values of a class that keeps its data inside. A path does not go into them,
393
+ * as in the field paths of a resource, so a field with such a value is one
394
+ * field. A condition can test only if it exists.
395
+ */
396
+ type Whole = ReadonlyMap<unknown, unknown> | ReadonlySet<unknown> | HashMap.HashMap<unknown, unknown> | HashSet.HashSet<unknown> | Date | URL | Uint8Array | Option.Option<unknown> | BigDecimal.BigDecimal | Duration.Duration | DateTime.DateTime | Redacted.Redacted<unknown> | Chunk.Chunk<unknown> | Cause.Cause<unknown> | Result.Result<unknown, unknown> | File | FormData | RegExp;
252
397
  type PreviousDepth = [never, 0, 1, 2, 3];
253
- type FieldPathInternal<T, Depth extends number> = [Depth] extends [never] ? never : { [K in keyof T & string]-?: NonNullable<T[K]> extends Leaf ? K : NonNullable<T[K]> extends ReadonlyArray<unknown> | Function ? never : NonNullable<T[K]> extends object ? `${K}.${FieldPathInternal<NonNullable<T[K]>, PreviousDepth[Depth]>}` : never; }[keyof T & string];
398
+ type FieldPathInternal<T, Depth extends number, Arrays extends boolean> = [Depth] extends [never] ? never : { [K in keyof T & string]-?: NonNullable<T[K]> extends Leaf | Whole ? K : NonNullable<T[K]> extends Function ? never : NonNullable<T[K]> extends ReadonlyArray<unknown> ? Arrays extends true ? K : never : NonNullable<T[K]> extends object ? `${K}.${FieldPathInternal<NonNullable<T[K]>, PreviousDepth[Depth], Arrays>}` : never; }[keyof T & string];
254
399
  /**
255
400
  * The paths of the fields of `T` that hold one value, with dots for nested
256
- * fields. Arrays are left out. The type goes down four levels, so type
401
+ * fields. Arrays are left out. A map, a set, a date, a URL, a byte array, an
402
+ * `Option` and the other value types of Effect, such as `BigDecimal` and
403
+ * `Duration`, are one field, and a path does not go into them. The type goes down four levels, so type
257
404
  * checking stays fast. For a union of types, only the common fields are
258
405
  * paths.
259
406
  *
@@ -261,7 +408,30 @@ type FieldPathInternal<T, Depth extends number> = [Depth] extends [never] ? neve
261
408
  * @category utility types
262
409
  * @since 0.3.0
263
410
  */
264
- export type FieldPath<T> = [T] extends [object] ? FieldPathInternal<T, 4> : never;
411
+ export type FieldPath<T> = [T] extends [object] ? FieldPathInternal<T, 4, false> : never;
412
+ /**
413
+ * The paths of the fields of `T` that a rule or a request may name, as in
414
+ * `Rule.Options.fields`. They are the paths of {@link FieldPath}, and the
415
+ * paths of arrays too: a rule may allow or deny a whole array field, and
416
+ * `permittedFields` lists it.
417
+ *
418
+ * @stability stable
419
+ * @category utility types
420
+ * @since 1.0.0
421
+ */
422
+ export type FieldSelector<T> = [T] extends [object] ? FieldPathInternal<T, 4, true> : never;
423
+ /**
424
+ * The value type that fits every field in `F`. For one field, it is the type
425
+ * of the field. For a union of fields, it is the values that each of them can
426
+ * hold, so a value of a union type can not test a field of another type. For
427
+ * a union of data types, as for a rule on two kinds, it is the values that
428
+ * the field can hold in each of them.
429
+ *
430
+ * @stability stable
431
+ * @category utility types
432
+ * @since 1.0.0
433
+ */
434
+ export type FieldValue<Data, F extends string> = (Data extends unknown ? F extends unknown ? (value: PathValue<Data, F>) => void : never : never) extends ((value: infer V) => void) ? V : never;
265
435
  type Normalize<A> = Exclude<A, undefined> | (undefined extends A ? null : never);
266
436
  /**
267
437
  * The type of the field of `T` at `Path`. A field that may be missing may also
@@ -280,8 +450,28 @@ export type PathValue<T, Path extends string> = Path extends `${infer Head}.${in
280
450
  * @category models
281
451
  * @since 0.3.0
282
452
  */
283
- export type OperandOf<A> = Extract<A, Scalar> | Ref<A>;
453
+ export type OperandOf<A, P = never> = Extract<A, Scalar> | Ref<A, P>;
454
+ type ScalarPath<T> = { [F in FieldPath<T>]: PathValue<T, F> extends Scalar ? F : never; }[FieldPath<T>];
284
455
  type OrderedPath<T> = { [F in FieldPath<T>]: Exclude<PathValue<T, F>, null> extends number | string ? F : never; }[FieldPath<T>];
456
+ /**
457
+ * A test made by a {@link Builder}. It runs no code, but it keeps the value
458
+ * type of its resource, so a test on the fields of one resource can not go
459
+ * into a rule for another resource. A test with a field of the principal
460
+ * keeps the principal type `P` too.
461
+ *
462
+ * @stability stable
463
+ * @category models
464
+ * @since 1.0.0
465
+ */
466
+ export type Test<Value, P = unknown> = Condition<never, never, never, Reads<Value, P>>;
467
+ /**
468
+ * The principal type that a test reads: the principal of each field of the
469
+ * principal in the values `V`, and `unknown` when there is none. A reference
470
+ * from another builder keeps the principal of that builder.
471
+ */
472
+ type PrincipalOf<V, _P> = [Extract<V, PrincipalRef>] extends [never] ? unknown : [Extract<V, PrincipalRef>] extends [{
473
+ readonly "~Principal": (principal: infer Q) => void;
474
+ }] ? Q : unknown;
285
475
  /**
286
476
  * Makes conditions for a resource with the data type `Data` and the value type
287
477
  * `Value`, and a principal with the type `P`.
@@ -292,29 +482,32 @@ type OrderedPath<T> = { [F in FieldPath<T>]: Exclude<PathValue<T, F>, null> exte
292
482
  */
293
483
  export interface Builder<Data, Value, P> {
294
484
  /** The field is equal to the value. */
295
- readonly eq: <const F extends FieldPath<Data>>(field: F, value: OperandOf<PathValue<Data, F>>) => Condition;
485
+ readonly eq: <const F extends FieldPath<Data>, const V extends OperandOf<FieldValue<Data, F>, any>>(field: F, value: V) => Test<Value, PrincipalOf<V, P>>;
296
486
  /** The field is not equal to the value. */
297
- readonly ne: <const F extends FieldPath<Data>>(field: F, value: OperandOf<PathValue<Data, F>>) => Condition;
298
- readonly lt: <const F extends OrderedPath<Data>>(field: F, value: OperandOf<Exclude<PathValue<Data, F>, null>>) => Condition;
299
- readonly lte: <const F extends OrderedPath<Data>>(field: F, value: OperandOf<Exclude<PathValue<Data, F>, null>>) => Condition;
300
- readonly gt: <const F extends OrderedPath<Data>>(field: F, value: OperandOf<Exclude<PathValue<Data, F>, null>>) => Condition;
301
- readonly gte: <const F extends OrderedPath<Data>>(field: F, value: OperandOf<Exclude<PathValue<Data, F>, null>>) => Condition;
487
+ readonly ne: <const F extends FieldPath<Data>, const V extends OperandOf<FieldValue<Data, F>, any>>(field: F, value: V) => Test<Value, PrincipalOf<V, P>>;
488
+ readonly lt: <const F extends OrderedPath<Data>, const V extends OperandOf<Exclude<FieldValue<Data, F>, null>, any>>(field: F, value: V) => Test<Value, PrincipalOf<V, P>>;
489
+ readonly lte: <const F extends OrderedPath<Data>, const V extends OperandOf<Exclude<FieldValue<Data, F>, null>, any>>(field: F, value: V) => Test<Value, PrincipalOf<V, P>>;
490
+ readonly gt: <const F extends OrderedPath<Data>, const V extends OperandOf<Exclude<FieldValue<Data, F>, null>, any>>(field: F, value: V) => Test<Value, PrincipalOf<V, P>>;
491
+ readonly gte: <const F extends OrderedPath<Data>, const V extends OperandOf<Exclude<FieldValue<Data, F>, null>, any>>(field: F, value: V) => Test<Value, PrincipalOf<V, P>>;
302
492
  /** The field is equal to one of the values. */
303
- readonly in: <const F extends FieldPath<Data>>(field: F, values: ReadonlyArray<OperandOf<PathValue<Data, F>>>) => Condition;
493
+ readonly in: <const F extends FieldPath<Data>, const Vs extends ReadonlyArray<OperandOf<FieldValue<Data, F>, any>>>(field: F, values: Vs) => Test<Value, PrincipalOf<Vs[number], P>>;
304
494
  /** The field has a value that is not `null`. */
305
- readonly exists: <const F extends FieldPath<Data>>(field: F) => Condition;
495
+ readonly exists: <const F extends FieldPath<Data>>(field: F) => Test<Value>;
306
496
  /** The path of the resource starts with these parts. */
307
- readonly under: (...prefix: ReadonlyArray<string | null | Ref<string | null>>) => Condition;
308
- /** A field of the principal, to use as a value. */
309
- readonly principal: <const F extends FieldPath<P>>(field: F) => Ref<PathValue<P, F>>;
310
- readonly and: <const Cs extends ReadonlyArray<Any>>(...conditions: Cs) => Condition<Error<Cs[number]>, Services<Cs[number]>, OpaqueOf<Cs[number]>>;
311
- readonly or: <const Cs extends ReadonlyArray<Any>>(...conditions: Cs) => Condition<Error<Cs[number]>, Services<Cs[number]>, OpaqueOf<Cs[number]>>;
312
- readonly not: <C extends Any>(condition: C) => Condition<Error<C>, Services<C>, OpaqueOf<C>>;
497
+ readonly under: <const Ps extends ReadonlyArray<string | null | Ref<string | null, any>>>(...prefix: Ps) => Test<Value, PrincipalOf<Ps[number], P>>;
498
+ /**
499
+ * A field of the principal, to use as a value. The field must have a
500
+ * {@link Scalar} type.
501
+ */
502
+ readonly principal: <const F extends ScalarPath<P>>(field: F) => Ref<PathValue<P, F>, P>;
503
+ readonly and: <const Cs extends ReadonlyArray<Any>>(...conditions: Consistent<Cs>) => Condition<Error<Cs[number]>, Services<Cs[number]>, OpaqueOf<Cs[number]>, ReadsOf<Cs[number]>>;
504
+ readonly or: <const Cs extends ReadonlyArray<Any>>(...conditions: Consistent<Cs>) => Condition<Error<Cs[number]>, Services<Cs[number]>, OpaqueOf<Cs[number]>, ReadsOf<Cs[number]>>;
505
+ readonly not: <C extends Any>(condition: C & Checked<C>) => Condition<Error<C>, Services<C>, OpaqueOf<C>, ReadsOf<C>>;
313
506
  /**
314
507
  * A test that runs any code. It may give a boolean or an `Effect`. A
315
508
  * condition with a predicate can not become JSON or a query.
316
509
  */
317
- readonly predicate: <E = never, R = never>(name: string, test: (value: Value, principal: P) => boolean | Effect.Effect<boolean, E, R>) => Condition<E, R, Opaque>;
510
+ readonly predicate: <E = never, R = never>(name: string, test: (value: Value, principal: P) => boolean | Effect.Effect<boolean, E, R>) => Condition<E, R, Opaque, Reads<Value, P>>;
318
511
  }
319
512
  /**
320
513
  * Makes a builder. Rules give you a builder with the right types, so you do not
@@ -348,7 +541,25 @@ export declare const never: Condition;
348
541
  * @category combinators
349
542
  * @since 0.3.0
350
543
  */
351
- export declare const and: <const Cs extends ReadonlyArray<Any>>(...conditions: Cs) => Condition<Error<Cs[number]>, Services<Cs[number]>, OpaqueOf<Cs[number]>>;
544
+ export declare const and: <const Cs extends ReadonlyArray<Any>>(...conditions: Consistent<Cs>) => Condition<Error<Cs[number]>, Services<Cs[number]>, OpaqueOf<Cs[number]>, ReadsOf<Cs[number]>>;
545
+ /**
546
+ * The same as {@link and}, for a list of conditions of one type. Use it for a
547
+ * long list: a function call may take only so many arguments.
548
+ *
549
+ * @stability stable
550
+ * @category combinators
551
+ * @since 1.0.0
552
+ */
553
+ export declare const andAll: <C extends Any>(conditions: ReadonlyArray<C & Checked<C>>) => Condition<Error<C>, Services<C>, OpaqueOf<C>, ReadsOf<C>>;
554
+ /**
555
+ * The same as {@link or}, for a list of conditions of one type. Use it for a
556
+ * long list: a function call may take only so many arguments.
557
+ *
558
+ * @stability stable
559
+ * @category combinators
560
+ * @since 1.0.0
561
+ */
562
+ export declare const orAll: <C extends Any>(conditions: ReadonlyArray<C & Checked<C>>) => Condition<Error<C>, Services<C>, OpaqueOf<C>, ReadsOf<C>>;
352
563
  /**
353
564
  * True when one of the conditions is true. With no conditions, it is false.
354
565
  *
@@ -356,13 +567,13 @@ export declare const and: <const Cs extends ReadonlyArray<Any>>(...conditions: C
356
567
  * @category combinators
357
568
  * @since 0.3.0
358
569
  */
359
- export declare const or: <const Cs extends ReadonlyArray<Any>>(...conditions: Cs) => Condition<Error<Cs[number]>, Services<Cs[number]>, OpaqueOf<Cs[number]>>;
570
+ export declare const or: <const Cs extends ReadonlyArray<Any>>(...conditions: Consistent<Cs>) => Condition<Error<Cs[number]>, Services<Cs[number]>, OpaqueOf<Cs[number]>, ReadsOf<Cs[number]>>;
360
571
  /**
361
572
  * @stability stable
362
573
  * @category combinators
363
574
  * @since 0.3.0
364
575
  */
365
- export declare const not: <C extends Any>(condition: C) => Condition<Error<C>, Services<C>, OpaqueOf<C>>;
576
+ export declare const not: <C extends Any>(condition: C & Checked<C>) => Condition<Error<C>, Services<C>, OpaqueOf<C>, ReadsOf<C>>;
366
577
  /**
367
578
  * The data that a condition needs for a test.
368
579
  *
@@ -382,15 +593,51 @@ export interface Input {
382
593
  readonly path?: ReadonlyArray<PathSegment> | undefined;
383
594
  }
384
595
  /**
385
- * Tests a condition on a value. A predicate may fail with its error.
596
+ * True when a condition has a {@link Predicate}.
597
+ *
598
+ * @stability stable
599
+ * @category predicates
600
+ * @since 1.0.0
601
+ */
602
+ export declare const hasPredicate: (condition: Ast) => boolean;
603
+ /**
604
+ * Gives the services in `context` to every predicate of a condition, so the
605
+ * condition needs no services when it runs.
606
+ *
607
+ * @stability stable
608
+ * @category services
609
+ * @since 1.0.0
610
+ */
611
+ export declare const provideContext: {
612
+ <R>(context: Context.Context<R>): <E, O, I>(condition: Condition<E, R, O, I>) => Condition<E, never, O, I>;
613
+ <E, R, O, I>(condition: Condition<E, R, O, I>, context: Context.Context<R>): Condition<E, never, O, I>;
614
+ };
615
+ /**
616
+ * The input of {@link evaluate} that the predicates of a condition need: a
617
+ * value and a principal of the types in `I`. See {@link Reads}.
618
+ */
619
+ type ReadsInput<I> = I extends Reads<infer V, infer P> ? {
620
+ readonly value: V;
621
+ } & (unknown extends P ? unknown : {
622
+ readonly principal: P;
623
+ }) : unknown;
624
+ /**
625
+ * `unknown` when `In` gives what `I` reads, and `never` when it does not. For
626
+ * a union, each member must give it, so the test is not split over the union.
627
+ */
628
+ type ReadsFrom<I, In> = [In] extends [ReadsInput<I>] ? unknown : never;
629
+ /**
630
+ * Tests a condition on a value. A predicate may fail with its error. When the
631
+ * condition has a predicate, the input must have the value and the principal
632
+ * that the predicate reads.
386
633
  *
387
634
  * @stability stable
388
635
  * @category evaluation
389
636
  * @since 0.3.0
390
637
  */
391
638
  export declare const evaluate: {
392
- (input: Input): <E, R, O>(condition: Condition<E, R, O>) => Effect.Effect<boolean, E, R>;
393
- <E, R, O>(condition: Condition<E, R, O>, input: Input): Effect.Effect<boolean, E, R>;
639
+ <In extends Input>(input: In): <E, R, O, I>(condition: Condition<E, R, O, I> & ReadsFrom<I, In>) => Effect.Effect<boolean, E, R>;
640
+ <E, R, O, I, In extends Input>(condition: Condition<E, R, O, I>, input: In & ReadsInput<I>): Effect.Effect<boolean, E, R>;
394
641
  };
395
642
  /**
396
643
  * Tests a condition with no predicate on a value, at once.
@@ -400,39 +647,60 @@ export declare const evaluate: {
400
647
  * @since 0.3.0
401
648
  */
402
649
  export declare const evaluateSync: {
403
- (input: Input): (condition: Condition) => boolean;
404
- (condition: Condition, input: Input): boolean;
650
+ <In extends Input>(input: In): <I>(condition: Condition<never, never, never, I> & ReadsFrom<I, In>) => boolean;
651
+ <I, In extends Input>(condition: Condition<never, never, never, I>, input: In & ReadsInput<I>): boolean;
405
652
  };
406
653
  /**
407
- * Puts the principal into a condition and expands `Under` with the path of the
408
- * resource. The result is simplified. It has no principal fields and no
409
- * `Under` nodes. It is `True` or `False` when the answer does not depend on the
410
- * resource value.
654
+ * Makes a condition smaller without a change to its meaning. It removes `True`
655
+ * and `False` from `And` and `Or`, joins nested `And` and `Or` nodes, and
656
+ * removes double `Not` nodes.
411
657
  *
412
658
  * @stability stable
413
659
  * @category evaluation
414
660
  * @since 0.3.0
415
661
  */
416
- export declare const partial: {
417
- (input: {
418
- readonly principal?: object | undefined;
419
- readonly path?: ReadonlyArray<PathSegment> | undefined;
420
- }): <E, R, O>(condition: Condition<E, R, O>) => Condition<E, R, O>;
421
- <E, R, O>(condition: Condition<E, R, O>, input: {
422
- readonly principal?: object | undefined;
423
- readonly path?: ReadonlyArray<PathSegment> | undefined;
424
- }): Condition<E, R, O>;
425
- };
662
+ export declare const simplify: <E, R, O, I>(condition: Condition<E, R, O, I>) => Condition<E, R, O, I>;
426
663
  /**
427
- * Makes a condition smaller without a change to its meaning. It removes `True`
428
- * and `False` from `And` and `Or`, joins nested `And` and `Or` nodes, and
429
- * removes double `Not` nodes.
664
+ * Makes a {@link simplify} function that keeps its work for the parts it has
665
+ * seen. Use one for many calls on conditions that share parts, such as the
666
+ * steps of one residual condition. Do not keep it for long: it keeps every
667
+ * part that it has seen.
668
+ *
669
+ * @stability stable
670
+ * @category evaluation
671
+ * @since 1.0.0
672
+ */
673
+ export declare const simplifier: () => (<E, R, O, I>(condition: Condition<E, R, O, I>) => Condition<E, R, O, I>);
674
+ interface PartialInput {
675
+ readonly principal?: object | undefined;
676
+ readonly path?: ReadonlyArray<PathSegment> | undefined;
677
+ }
678
+ /**
679
+ * The principal that {@link partial} must get for the predicates of a
680
+ * condition. A predicate keeps the principal that it gets, so the principal
681
+ * must have the type that the predicate reads.
682
+ */
683
+ type PrincipalInput<I> = I extends Reads<infer _V, infer P> ? unknown extends P ? unknown : {
684
+ readonly principal: P;
685
+ } : unknown;
686
+ /** `unknown` when `In` gives what `I` reads, and `never` when it does not. */
687
+ type PrincipalFrom<I, In> = [In] extends [PrincipalInput<I>] ? unknown : never;
688
+ /** What a condition reads after {@link partial}: the value, and no principal. */
689
+ type Bound<I> = I extends Reads<infer V, infer _P> ? Reads<V, unknown> : I;
690
+ /**
691
+ * Puts the principal into a condition and expands `Under` with the path of the
692
+ * resource. The result is simplified. It has no principal fields and no
693
+ * `Under` nodes. It is `True` or `False` when the answer does not depend on the
694
+ * resource value.
430
695
  *
431
696
  * @stability stable
432
697
  * @category evaluation
433
698
  * @since 0.3.0
434
699
  */
435
- export declare const simplify: <E, R, O>(condition: Condition<E, R, O>) => Condition<E, R, O>;
700
+ export declare const partial: {
701
+ <In extends PartialInput>(input: In): <E, R, O, I>(condition: Condition<E, R, O, I> & PrincipalFrom<I, In>) => Condition<E, R, O, Bound<I>>;
702
+ <E, R, O, I>(condition: Condition<E, R, O, I>, input: PartialInput & PrincipalInput<I>): Condition<E, R, O, Bound<I>>;
703
+ };
436
704
  /**
437
705
  * The functions that change each node of a condition into another form, such
438
706
  * as a database query.
@@ -453,6 +721,9 @@ export interface Interpreter<A> {
453
721
  /** Optional. Without it, a predicate makes `fold` fail. */
454
722
  readonly predicate?: (name: string) => A;
455
723
  }
724
+ declare const Untranslatable_base: Schema.Class<Untranslatable, Schema.TaggedStruct<"Untranslatable", {
725
+ readonly reason: Schema.String;
726
+ }>, Cause.YieldableError>;
456
727
  /**
457
728
  * The error when `fold` can not change a node.
458
729
  *
@@ -460,13 +731,7 @@ export interface Interpreter<A> {
460
731
  * @category errors
461
732
  * @since 0.3.0
462
733
  */
463
- export declare const Untranslatable: typeof Untranslatable$1;
464
- /**
465
- * @stability stable
466
- * @category errors
467
- * @since 0.3.0
468
- */
469
- export type Untranslatable = Untranslatable$1;
734
+ export declare class Untranslatable extends Untranslatable_base {}
470
735
  /**
471
736
  * Changes a condition into another form with an interpreter. Call
472
737
  * {@link partial} first: `fold` fails on principal fields and on `Under`
@@ -487,7 +752,100 @@ export declare const fold: {
487
752
  * @category getters
488
753
  * @since 0.3.0
489
754
  */
490
- export declare const fields: (condition: Any) => ReadonlyArray<string>;
755
+ export declare const fields: (condition: Ast) => ReadonlyArray<string>;
756
+ /**
757
+ * Values of fields, as a nested object. A field that is not in it may have any
758
+ * value. A value with parts that the search does not look into, such as a
759
+ * date, is an empty object.
760
+ *
761
+ * @stability stable
762
+ * @category models
763
+ * @since 1.0.0
764
+ */
765
+ export interface Example {
766
+ readonly [field: string]: unknown;
767
+ }
768
+ /**
769
+ * The answer of {@link satisfiable}:
770
+ * - `Satisfiable`: some value makes the condition true. `example` is one.
771
+ * - `Unsatisfiable`: no value makes the condition true.
772
+ * - `Unknown`: the search can not say. The condition has a predicate, the
773
+ * search went past its budget, or it set two fields that the Schema ties
774
+ * together, as below a union or a field that may be missing.
775
+ *
776
+ * @stability stable
777
+ * @category models
778
+ * @since 1.0.0
779
+ */
780
+ export type Satisfiability = Data.TaggedEnum<{
781
+ Satisfiable: {
782
+ readonly example: Example;
783
+ };
784
+ Unsatisfiable: {};
785
+ Unknown: {
786
+ readonly reason: "predicate" | "budget" | "schema";
787
+ };
788
+ }>;
789
+ /**
790
+ * The options of {@link satisfiable}.
791
+ *
792
+ * @stability stable
793
+ * @category models
794
+ * @since 1.0.0
795
+ */
796
+ export interface SatisfiableOptions {
797
+ /**
798
+ * The Schema of the values. It gives the domain of each field. Without
799
+ * it, a field may have any value.
800
+ */
801
+ readonly schema?: Schema.Top | undefined;
802
+ /** The most nodes that the search may visit. The default is 1000000. */
803
+ readonly budget?: number | undefined;
804
+ }
805
+ /**
806
+ * Tests if some value makes a condition true, and gives such a value.
807
+ *
808
+ * Call {@link partial} first: the condition must have no principal fields and
809
+ * no `Under` nodes. A condition with a predicate gives `Unknown`.
810
+ *
811
+ * With `options.schema`, each field of the condition must be a plain scalar
812
+ * field of the Schema (see `Resource.isPlainField`). Else the answer is
813
+ * `Unknown` with the reason `"schema"`: for another field, a value may have
814
+ * data that the Schema does not show, so the model of its values is not
815
+ * exact.
816
+ *
817
+ * The answer is exact. Each test of a condition compares one field with
818
+ * constants, so the constants cut the values of each field into a few cells.
819
+ * The search tries one value from each cell, one field at a time. The values
820
+ * of a field come from the Schema in `options.schema`: its literals, `null`
821
+ * for a nullable or optional field, and finite or integer numbers. A field
822
+ * with another Schema check is not a plain field, so the search never tries a
823
+ * value that such a check stops.
824
+ *
825
+ * The problem is as hard as boolean satisfiability, so the search has a
826
+ * budget. Past it, the answer is `Unknown`. A condition with more than 256
827
+ * fields, or with a field path of more than 256 parts, gives `Unknown` too.
828
+ *
829
+ * @stability stable
830
+ * @category evaluation
831
+ * @since 1.0.0
832
+ */
833
+ export declare const satisfiable: {
834
+ (options?: SatisfiableOptions): (condition: Any) => Satisfiability;
835
+ (condition: Any, options?: SatisfiableOptions): Satisfiability;
836
+ };
837
+ /**
838
+ * Gives a condition as a value that `JSON.stringify` keeps with no loss. JSON
839
+ * has no `Infinity`, `-Infinity` or `NaN`: it writes `null` in their place,
840
+ * and a test with `null` has another meaning. Such a number becomes an object
841
+ * that {@link schema} does not decode, so a policy with it fails to load and
842
+ * never gives a wrong answer.
843
+ *
844
+ * @stability stable
845
+ * @category conversions
846
+ * @since 1.0.0
847
+ */
848
+ export declare const toJsonValue: (condition: Ast) => unknown;
491
849
  /**
492
850
  * The JSON form of a condition with no predicate.
493
851
  *
@@ -523,6 +881,17 @@ export interface EncodedNot {
523
881
  readonly _tag: "Not";
524
882
  readonly condition: Encoded;
525
883
  }
884
+ /**
885
+ * A condition with no predicate, that may read any values. It is the type of
886
+ * {@link schema}: a decoded condition reads nothing, so it fits any rule, and
887
+ * any plain condition, such as one from a builder or a residual, may be
888
+ * encoded.
889
+ *
890
+ * @stability stable
891
+ * @category models
892
+ * @since 1.0.0
893
+ */
894
+ export type PlainCondition = Condition<never, never, never, any>;
526
895
  /**
527
896
  * The Schema of a condition with no predicate. It checks the shape only. Use
528
897
  * `Policy.schema` to check the field names against a domain too.
@@ -531,6 +900,16 @@ export interface EncodedNot {
531
900
  * @category schemas
532
901
  * @since 0.3.0
533
902
  */
534
- export declare const schema: Schema.Codec<Condition, Encoded>;
903
+ export declare const schema: Schema.Codec<PlainCondition, Encoded>;
904
+ /**
905
+ * Tests if a value is a whole condition tree: each node has a known tag and
906
+ * the fields of that tag. A predicate node needs a name and a test. A tree
907
+ * deeper than 1000 levels is not taken.
908
+ *
909
+ * @stability stable
910
+ * @category guards
911
+ * @since 1.0.0
912
+ */
913
+ export declare const isAst: (u: unknown) => u is Ast;
535
914
  export { Condition_d_exports };
536
915
  //# sourceMappingURL=Condition.d.ts.map