@nmnmcc/ability 2.0.6 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +56 -32
  2. package/dist/Authorizer.d.ts +21 -12
  3. package/dist/Authorizer.d.ts.map +1 -1
  4. package/dist/Authorizer.js.map +1 -1
  5. package/dist/Condition.d.ts +118 -18
  6. package/dist/Condition.d.ts.map +1 -1
  7. package/dist/Condition.js +27 -18
  8. package/dist/Condition.js.map +1 -1
  9. package/dist/Domain.d.ts +9 -0
  10. package/dist/Domain.d.ts.map +1 -1
  11. package/dist/Domain.js +5 -0
  12. package/dist/Domain.js.map +1 -1
  13. package/dist/Limits.d.ts +44 -13
  14. package/dist/Limits.d.ts.map +1 -1
  15. package/dist/Limits.js +52 -22
  16. package/dist/Limits.js.map +1 -1
  17. package/dist/Policy.d.ts +95 -12
  18. package/dist/Policy.d.ts.map +1 -1
  19. package/dist/Policy.js.map +1 -1
  20. package/dist/index.d.ts +1 -1
  21. package/dist/internal/algebra.js +101 -74
  22. package/dist/internal/algebra.js.map +1 -1
  23. package/dist/internal/analysis.js +81 -75
  24. package/dist/internal/analysis.js.map +1 -1
  25. package/dist/internal/authorizer.d.ts.map +1 -1
  26. package/dist/internal/authorizer.js +16 -11
  27. package/dist/internal/authorizer.js.map +1 -1
  28. package/dist/internal/bind.js +119 -80
  29. package/dist/internal/bind.js.map +1 -1
  30. package/dist/internal/catalog.d.ts +33 -10
  31. package/dist/internal/catalog.d.ts.map +1 -1
  32. package/dist/internal/catalog.js +153 -78
  33. package/dist/internal/catalog.js.map +1 -1
  34. package/dist/internal/decide.js +25 -29
  35. package/dist/internal/decide.js.map +1 -1
  36. package/dist/internal/domain.js +19 -5
  37. package/dist/internal/domain.js.map +1 -1
  38. package/dist/internal/json.js +120 -76
  39. package/dist/internal/json.js.map +1 -1
  40. package/dist/internal/limits.d.ts +28 -0
  41. package/dist/internal/limits.d.ts.map +1 -1
  42. package/dist/internal/limits.js +75 -16
  43. package/dist/internal/limits.js.map +1 -1
  44. package/dist/internal/nodes.d.ts +7 -0
  45. package/dist/internal/nodes.d.ts.map +1 -1
  46. package/dist/internal/nodes.js +86 -47
  47. package/dist/internal/nodes.js.map +1 -1
  48. package/dist/internal/patterns.js +50 -15
  49. package/dist/internal/patterns.js.map +1 -1
  50. package/dist/internal/policy-json.js +169 -127
  51. package/dist/internal/policy-json.js.map +1 -1
  52. package/dist/internal/policy-nodes.d.ts.map +1 -1
  53. package/dist/internal/policy-nodes.js +17 -14
  54. package/dist/internal/policy-nodes.js.map +1 -1
  55. package/dist/internal/policy.d.ts.map +1 -1
  56. package/dist/internal/policy.js +38 -22
  57. package/dist/internal/policy.js.map +1 -1
  58. package/dist/internal/resource.js +1 -1
  59. package/dist/internal/rule.d.ts.map +1 -1
  60. package/dist/internal/rule.js +6 -5
  61. package/dist/internal/rule.js.map +1 -1
  62. package/dist/internal/search.d.ts.map +1 -1
  63. package/dist/internal/search.js +106 -92
  64. package/dist/internal/search.js.map +1 -1
  65. package/dist/internal/trampoline.js +89 -0
  66. package/dist/internal/trampoline.js.map +1 -0
  67. package/package.json +1 -1
  68. package/src/Authorizer.ts +30 -20
  69. package/src/Condition.ts +308 -83
  70. package/src/Domain.ts +9 -0
  71. package/src/Limits.ts +69 -29
  72. package/src/Policy.ts +131 -15
  73. package/src/internal/algebra.ts +218 -135
  74. package/src/internal/analysis.ts +154 -122
  75. package/src/internal/authorizer.ts +34 -16
  76. package/src/internal/bind.ts +279 -148
  77. package/src/internal/catalog.ts +307 -133
  78. package/src/internal/decide.ts +58 -49
  79. package/src/internal/domain.ts +39 -3
  80. package/src/internal/json.ts +212 -117
  81. package/src/internal/limits.ts +101 -31
  82. package/src/internal/nodes.ts +101 -59
  83. package/src/internal/patterns.ts +72 -26
  84. package/src/internal/policy-json.ts +266 -197
  85. package/src/internal/policy-nodes.ts +33 -24
  86. package/src/internal/policy.ts +63 -23
  87. package/src/internal/rule.ts +16 -3
  88. package/src/internal/search.ts +186 -136
  89. package/src/internal/trampoline.ts +194 -0
package/src/Condition.ts CHANGED
@@ -49,6 +49,7 @@ import * as Catalog from "./internal/catalog.ts"
49
49
  import * as Json from "./internal/json.ts"
50
50
  import * as Nodes from "./internal/nodes.ts"
51
51
  import * as Search from "./internal/search.ts"
52
+ import * as Trampoline from "./internal/trampoline.ts"
52
53
  import * as Resource from "./Resource.ts"
53
54
 
54
55
  /**
@@ -412,8 +413,7 @@ type ObjectPaths<
412
413
  > = [O] extends [never]
413
414
  ? never
414
415
  : // A record is one field to a rule or a request, as `permittedFields`
415
- // lists it. So is a struct at the last part that a path may have, since
416
- // a path does not go below it.
416
+ // lists it.
417
417
  | (Parents extends true
418
418
  ? K
419
419
  : Arrays extends true
@@ -421,9 +421,7 @@ type ObjectPaths<
421
421
  ? K
422
422
  : number extends keyof O
423
423
  ? K
424
- : [Depth] extends [0]
425
- ? K
426
- : never
424
+ : never
427
425
  : never)
428
426
  | `${K}.${FieldPathInternal<O, PreviousDepth[Depth], Arrays, Parents>}`
429
427
 
@@ -503,16 +501,31 @@ type Normalize<A> = Exclude<A, undefined> | (undefined extends A ? null : never)
503
501
  * @category utility types
504
502
  * @since 0.3.0
505
503
  */
506
- export type PathValue<T, Path extends string> = T extends unknown
507
- ? PathValueIn<T, Path>
504
+ export type PathValue<T, Path extends string> = ValueWalk<T, Path>
505
+
506
+ /**
507
+ * The values of the part `Name` of each type of `U`. A part below a value
508
+ * that is not an object, as below a string or `null`, is `null`.
509
+ */
510
+ type StepValue<U, Name extends string> = U extends unknown
511
+ ? U extends object
512
+ ? ChildOf<U, Name>
513
+ : null
508
514
  : never
509
515
 
510
- /** The type of the field at `Path` of `T`, which is not a union. */
511
- type PathValueIn<T, Path extends string> = T extends object
512
- ? Path extends `${infer Head}.${infer Rest}`
513
- ? PathValue<ChildOf<T, Head>, Rest>
514
- : Normalize<ChildOf<T, Path>>
515
- : null
516
+ /**
517
+ * Walks a path two parts at a time, with the values of each step. The type
518
+ * checker takes at most about 1000 steps of a type that calls itself, so a
519
+ * walk of one part at a time would stop before a path of 1000 parts.
520
+ */
521
+ type ValueWalk<
522
+ U,
523
+ Path extends string,
524
+ > = Path extends `${infer A}.${infer B}.${infer Rest}`
525
+ ? ValueWalk<StepValue<StepValue<U, A>, B>, Rest>
526
+ : Path extends `${infer A}.${infer B}`
527
+ ? Normalize<StepValue<StepValue<U, A>, B>>
528
+ : Normalize<StepValue<U, Path>>
516
529
 
517
530
  /**
518
531
  * The type of the part `Name` of `T`. A part of a path is text, so the part
@@ -528,6 +541,211 @@ type ChildOf<T, Name extends string> = Name extends keyof T
528
541
  : never
529
542
  : never
530
543
 
544
+ /**
545
+ * What a path may do, for one use of it: go below a list or a whole value,
546
+ * as a rule or a request may, and end at a struct, as the fields of a rule
547
+ * may. See {@link FieldPath}, {@link FieldSelector} and {@link FieldName},
548
+ * which list the short paths with the same rules.
549
+ */
550
+ interface PathRules {
551
+ readonly arrays: boolean
552
+ readonly parents: boolean
553
+ }
554
+
555
+ /** The rules of a path that a condition reads. */
556
+ interface ReadRules {
557
+ readonly arrays: false
558
+ readonly parents: false
559
+ }
560
+
561
+ /** The rules of the field of a request. */
562
+ interface SelectRules {
563
+ readonly arrays: true
564
+ readonly parents: false
565
+ }
566
+
567
+ /** The rules of a field of a rule, which may name a struct. */
568
+ interface NameRules {
569
+ readonly arrays: true
570
+ readonly parents: true
571
+ }
572
+
573
+ /** The objects below a field with the values `V`: see `PathsOf`. */
574
+ type ObjectsBelow<V, Arrays extends boolean> = Arrays extends true
575
+ ? Exclude<V, Leaf | Whole | Function | ReadonlyArray<unknown>>
576
+ : [Extract<V, Whole | Function | ReadonlyArray<unknown>>] extends [never]
577
+ ? Exclude<V, Leaf>
578
+ : never
579
+
580
+ /** Tests if `Name` names a field of every object of `O`, as `keyof` does. */
581
+ type HasPart<O, Name extends string> = Name extends keyof O
582
+ ? true
583
+ : Name extends `${infer N extends number}`
584
+ ? N extends keyof O
585
+ ? true
586
+ : number extends keyof O
587
+ ? true
588
+ : false
589
+ : false
590
+
591
+ /**
592
+ * The objects below the part `Name` of the objects `O`, for a path that goes
593
+ * on, or `never` when it can not go on.
594
+ */
595
+ type PathStep<O, Name extends string, R extends PathRules> =
596
+ HasPart<O, Name> extends true
597
+ ? ObjectsBelow<NonNullable<ChildOf<O, Name>>, R["arrays"]>
598
+ : never
599
+
600
+ /** Tests if a path may end at a field with the values `V`: see `PathsOf`. */
601
+ type EndsAt<V, R extends PathRules, Last extends boolean> = [V] extends [never]
602
+ ? true
603
+ : {} extends V
604
+ ? true
605
+ : [Extract<V, Leaf | Whole>] extends [never]
606
+ ? R["arrays"] extends true
607
+ ? [Extract<V, ReadonlyArray<unknown>>] extends [never]
608
+ ? EndsAtObjects<ObjectsBelow<V, true>, R, Last>
609
+ : true
610
+ : false
611
+ : true
612
+
613
+ /**
614
+ * Tests if a path may end at a field that holds the objects `O`: a field of a
615
+ * rule may name a struct, and a request may name a record, or a struct at
616
+ * the last part that a path may have.
617
+ */
618
+ type EndsAtObjects<O, R extends PathRules, Last extends boolean> = [O] extends [
619
+ never,
620
+ ]
621
+ ? false
622
+ : R["parents"] extends true
623
+ ? true
624
+ : string extends keyof O
625
+ ? true
626
+ : number extends keyof O
627
+ ? true
628
+ : Last
629
+
630
+ /** The paths one part below `Done`, as the names that may come next. */
631
+ type NextNames<O, Done extends string> = `${Done}${keyof O & (string | number)}`
632
+
633
+ /**
634
+ * Walks a path two parts at a time, from the objects `O`. It gives `true`
635
+ * for a path that the rules `R` take, or the names that may come next after
636
+ * the last good part. `Count` counts the parts before `F`, so the walk knows
637
+ * the last part that a path may have: part 1000, the default of
638
+ * `Limits.fieldPathParts`.
639
+ */
640
+ type PathWalk<
641
+ O,
642
+ F extends string,
643
+ Done extends string,
644
+ R extends PathRules,
645
+ Count extends ReadonlyArray<0>,
646
+ > = F extends `${infer A}.${infer B}.${infer Rest}`
647
+ ? PathStep<O, A, R> extends infer O1
648
+ ? [O1] extends [never]
649
+ ? NextNames<O, Done>
650
+ : PathStep<O1, B, R> extends infer O2
651
+ ? [O2] extends [never]
652
+ ? NextNames<O1, `${Done}${A}.`>
653
+ : PathWalk<O2, Rest, `${Done}${A}.${B}.`, R, [...Count, 0, 0]>
654
+ : never
655
+ : never
656
+ : F extends `${infer A}.${infer B}`
657
+ ? PathStep<O, A, R> extends infer O1
658
+ ? [O1] extends [never]
659
+ ? NextNames<O, Done>
660
+ : PathEnd<O1, B, `${Done}${A}.`, R, [...Count, 0]>
661
+ : never
662
+ : PathEnd<O, F, Done, R, Count>
663
+
664
+ type PathEnd<
665
+ O,
666
+ Name extends string,
667
+ Done extends string,
668
+ R extends PathRules,
669
+ Count extends ReadonlyArray<0>,
670
+ > =
671
+ HasPart<O, Name> extends true
672
+ ? EndsAt<
673
+ NonNullable<ChildOf<O, Name>>,
674
+ R,
675
+ Count["length"] extends 999 ? true : false
676
+ > extends true
677
+ ? true
678
+ : // The name is a field, but a path may not end at it, as at a struct
679
+ // for a condition: the paths below it may come next. The names of
680
+ // this place would hold the name itself.
681
+ NextNames<
682
+ ObjectsBelow<NonNullable<ChildOf<O, Name>>, R["arrays"]>,
683
+ `${Done}${Name}.`
684
+ >
685
+ : NextNames<O, Done>
686
+
687
+ /**
688
+ * Checks one field path `F` of `T`, of any length up to about 1000 parts.
689
+ * It gives `F` for a path that the rules `R` take. For another path, it gives
690
+ * the paths that may come next after its last good part, so a type error
691
+ * names them. For a union of types, a part must be in each of them.
692
+ */
693
+ type PathCheck<T, F extends string, R extends PathRules> = [T] extends [object]
694
+ ? PathWalk<T, F, "", R, []> extends true
695
+ ? F
696
+ : // The names come from parts of `F`. Inference must not find `F` in
697
+ // them, so a call gets its `F` from the path that it gives.
698
+ NoInfer<PathWalk<T, F, "", R, []>>
699
+ : never
700
+
701
+ /**
702
+ * A path of `T` that a condition may read, as one of {@link FieldPath}, of
703
+ * any length up to about 1000 parts. It is `F` when `F` is such a path, and
704
+ * the names that may come next when it is not.
705
+ *
706
+ * @stability stable
707
+ * @category utility types
708
+ * @since 2.1.0
709
+ */
710
+ export type ReadPath<T, F extends string> = PathCheck<T, F, ReadRules>
711
+
712
+ /**
713
+ * A path of `T` that a request may name, as one of {@link FieldSelector}, of
714
+ * any length up to about 1000 parts. See {@link ReadPath}.
715
+ *
716
+ * @stability stable
717
+ * @category utility types
718
+ * @since 2.1.0
719
+ */
720
+ export type SelectPath<T, F extends string> = PathCheck<T, F, SelectRules>
721
+
722
+ /**
723
+ * A path of `T` that a field of a rule may name, as one of
724
+ * {@link FieldName}, of any length up to about 1000 parts. See
725
+ * {@link ReadPath}.
726
+ *
727
+ * @stability stable
728
+ * @category utility types
729
+ * @since 2.1.0
730
+ */
731
+ export type NamePath<T, F extends string> = PathCheck<T, F, NameRules>
732
+
733
+ /** A path that a condition may read, with an ordered value. */
734
+ type OrderedReadPath<T, F extends string> =
735
+ ReadPath<T, F> extends F
736
+ ? Exclude<PathValue<T, F>, null> extends number | string
737
+ ? F
738
+ : never
739
+ : ReadPath<T, F>
740
+
741
+ /** A path that a condition may read, with a scalar value. */
742
+ type ScalarReadPath<T, F extends string> =
743
+ ReadPath<T, F> extends F
744
+ ? PathValue<T, F> extends Scalar
745
+ ? F
746
+ : never
747
+ : ReadPath<T, F>
748
+
531
749
  /**
532
750
  * A value for a field of type `A`: a fixed value, or a field of the principal
533
751
  * with the same type.
@@ -538,16 +756,6 @@ type ChildOf<T, Name extends string> = Name extends keyof T
538
756
  */
539
757
  export type OperandOf<A, P = never> = Extract<A, Scalar> | Ref<A, P>
540
758
 
541
- type ScalarPath<T> = {
542
- [F in FieldPath<T>]: PathValue<T, F> extends Scalar ? F : never
543
- }[FieldPath<T>]
544
-
545
- type OrderedPath<T> = {
546
- [F in FieldPath<T>]: Exclude<PathValue<T, F>, null> extends number | string
547
- ? F
548
- : never
549
- }[FieldPath<T>]
550
-
551
759
  /**
552
760
  * A test made by a {@link Builder}. It runs no code, but it keeps the value
553
761
  * type of its resource, so a test on the fields of one resource can not go
@@ -584,58 +792,60 @@ type PrincipalOf<V, _P> = [Extract<V, PrincipalRef>] extends [never]
584
792
  export interface Builder<Data, Value, P> {
585
793
  /** The field is equal to the value. */
586
794
  readonly eq: <
587
- const F extends FieldPath<Data>,
795
+ const F extends string,
588
796
  const V extends OperandOf<FieldValue<Data, F>, any>,
589
797
  >(
590
- field: F,
798
+ field: ReadPath<Data, F>,
591
799
  value: V,
592
800
  ) => Test<Value, PrincipalOf<V, P>>
593
801
  /** The field is not equal to the value. */
594
802
  readonly ne: <
595
- const F extends FieldPath<Data>,
803
+ const F extends string,
596
804
  const V extends OperandOf<FieldValue<Data, F>, any>,
597
805
  >(
598
- field: F,
806
+ field: ReadPath<Data, F>,
599
807
  value: V,
600
808
  ) => Test<Value, PrincipalOf<V, P>>
601
809
  readonly lt: <
602
- const F extends OrderedPath<Data>,
810
+ const F extends string,
603
811
  const V extends OperandOf<Exclude<FieldValue<Data, F>, null>, any>,
604
812
  >(
605
- field: F,
813
+ field: OrderedReadPath<Data, F>,
606
814
  value: V,
607
815
  ) => Test<Value, PrincipalOf<V, P>>
608
816
  readonly lte: <
609
- const F extends OrderedPath<Data>,
817
+ const F extends string,
610
818
  const V extends OperandOf<Exclude<FieldValue<Data, F>, null>, any>,
611
819
  >(
612
- field: F,
820
+ field: OrderedReadPath<Data, F>,
613
821
  value: V,
614
822
  ) => Test<Value, PrincipalOf<V, P>>
615
823
  readonly gt: <
616
- const F extends OrderedPath<Data>,
824
+ const F extends string,
617
825
  const V extends OperandOf<Exclude<FieldValue<Data, F>, null>, any>,
618
826
  >(
619
- field: F,
827
+ field: OrderedReadPath<Data, F>,
620
828
  value: V,
621
829
  ) => Test<Value, PrincipalOf<V, P>>
622
830
  readonly gte: <
623
- const F extends OrderedPath<Data>,
831
+ const F extends string,
624
832
  const V extends OperandOf<Exclude<FieldValue<Data, F>, null>, any>,
625
833
  >(
626
- field: F,
834
+ field: OrderedReadPath<Data, F>,
627
835
  value: V,
628
836
  ) => Test<Value, PrincipalOf<V, P>>
629
837
  /** The field is equal to one of the values. */
630
838
  readonly in: <
631
- const F extends FieldPath<Data>,
839
+ const F extends string,
632
840
  const Vs extends ReadonlyArray<OperandOf<FieldValue<Data, F>, any>>,
633
841
  >(
634
- field: F,
842
+ field: ReadPath<Data, F>,
635
843
  values: Vs,
636
844
  ) => Test<Value, PrincipalOf<Vs[number], P>>
637
845
  /** The field has a value that is not `null`. */
638
- readonly exists: <const F extends FieldPath<Data>>(field: F) => Test<Value>
846
+ readonly exists: <const F extends string>(
847
+ field: ReadPath<Data, F>,
848
+ ) => Test<Value>
639
849
  /** The path of the resource starts with these parts. */
640
850
  readonly under: <
641
851
  const Ps extends ReadonlyArray<string | null | Ref<string | null, any>>,
@@ -646,8 +856,8 @@ export interface Builder<Data, Value, P> {
646
856
  * A field of the principal, to use as a value. The field must have a
647
857
  * {@link Scalar} type.
648
858
  */
649
- readonly principal: <const F extends ScalarPath<P>>(
650
- field: F,
859
+ readonly principal: <const F extends string>(
860
+ field: ScalarReadPath<P, F>,
651
861
  ) => Ref<PathValue<P, F>, P>
652
862
  readonly and: <const Cs extends ReadonlyArray<Any>>(
653
863
  ...conditions: Cs
@@ -992,50 +1202,65 @@ const literalValue = (operand: Operand, field: string): Scalar => {
992
1202
  return operand.value
993
1203
  }
994
1204
 
995
- /** Folds a condition. A shared child is folded again for each place. */
996
- const foldNode = <A>(node: Nodes.Node, interpreter: Interpreter<A>): A => {
997
- switch (node._tag) {
998
- case "True":
999
- return interpreter.true()
1000
- case "False":
1001
- return interpreter.false()
1002
- case "Compare":
1003
- return interpreter.compare(
1004
- node.op,
1005
- node.field,
1006
- literalValue(node.value, node.field),
1007
- )
1008
- case "In":
1009
- return interpreter.in(
1010
- node.field,
1011
- Arr.map(node.values, (operand) => literalValue(operand, node.field)),
1012
- )
1013
- case "Exists":
1014
- return interpreter.exists(node.field)
1015
- case "Under":
1016
- throw Untranslatable.make({
1017
- reason:
1018
- "An Under node needs the resource path. Call Condition.partial first.",
1019
- })
1020
- case "And":
1021
- return interpreter.and(
1022
- Arr.map(node.conditions, (child) => foldNode(child, interpreter)),
1023
- )
1024
- case "Or":
1025
- return interpreter.or(
1026
- Arr.map(node.conditions, (child) => foldNode(child, interpreter)),
1027
- )
1028
- case "Not":
1029
- return interpreter.not(foldNode(node.condition, interpreter))
1030
- case "Predicate":
1031
- if (interpreter.predicate === undefined) {
1032
- throw Untranslatable.make({
1033
- reason: `The predicate "${node.name}" can not become a query`,
1034
- })
1205
+ /**
1206
+ * Folds a condition. A shared child is folded again for each place. The walk
1207
+ * takes the steps of a trampoline, so a deep condition does not fill the
1208
+ * stack.
1209
+ */
1210
+ const foldNode = <A>(root: Nodes.Node, interpreter: Interpreter<A>): A =>
1211
+ Trampoline.run(root.depth, (R) => {
1212
+ const go = (node: Nodes.Node): Trampoline.Step<A> => {
1213
+ const children = (nodes: ReadonlyArray<Nodes.Node>) =>
1214
+ R.forEach(nodes, (child) => R.suspend(() => go(child)))
1215
+ switch (node._tag) {
1216
+ case "True":
1217
+ return R.succeed(interpreter.true())
1218
+ case "False":
1219
+ return R.succeed(interpreter.false())
1220
+ case "Compare":
1221
+ return R.succeed(
1222
+ interpreter.compare(
1223
+ node.op,
1224
+ node.field,
1225
+ literalValue(node.value, node.field),
1226
+ ),
1227
+ )
1228
+ case "In":
1229
+ return R.succeed(
1230
+ interpreter.in(
1231
+ node.field,
1232
+ Arr.map(node.values, (operand) =>
1233
+ literalValue(operand, node.field),
1234
+ ),
1235
+ ),
1236
+ )
1237
+ case "Exists":
1238
+ return R.succeed(interpreter.exists(node.field))
1239
+ case "Under":
1240
+ throw Untranslatable.make({
1241
+ reason:
1242
+ "An Under node needs the resource path. Call Condition.partial first.",
1243
+ })
1244
+ case "And":
1245
+ return R.map(children(node.conditions), interpreter.and)
1246
+ case "Or":
1247
+ return R.map(children(node.conditions), interpreter.or)
1248
+ case "Not":
1249
+ return R.map(
1250
+ R.suspend(() => go(node.condition)),
1251
+ interpreter.not,
1252
+ )
1253
+ case "Predicate":
1254
+ if (interpreter.predicate === undefined) {
1255
+ throw Untranslatable.make({
1256
+ reason: `The predicate "${node.name}" can not become a query`,
1257
+ })
1258
+ }
1259
+ return R.succeed(interpreter.predicate(node.name))
1035
1260
  }
1036
- return interpreter.predicate(node.name)
1037
- }
1038
- }
1261
+ }
1262
+ return go(root)
1263
+ })
1039
1264
 
1040
1265
  /**
1041
1266
  * Changes a condition into another form with an interpreter. Call
package/src/Domain.ts CHANGED
@@ -18,6 +18,7 @@ import type * as HashMap from "effect/HashMap"
18
18
  import type * as Schema from "effect/Schema"
19
19
  import type * as Catalog from "./internal/catalog.ts"
20
20
  import * as Internal from "./internal/domain.ts"
21
+ import type * as Limits from "./Limits.ts"
21
22
  import type * as Resource from "./Resource.ts"
22
23
 
23
24
  /** The Schema of a principal: a Schema of objects, such as a `Schema.Class`. */
@@ -42,6 +43,8 @@ export interface Domain<
42
43
  /** The descriptor of each resource, by its kind name. */
43
44
  readonly resources: HashMap.HashMap<string, Resource.Descriptor>
44
45
  readonly meta: Schema.Top | undefined
46
+ /** The limits of the domain: see `Limits`. */
47
+ readonly limits: Limits.Limits
45
48
  readonly "~Domain"?: {
46
49
  readonly Principal: P
47
50
  readonly Resources: Resources
@@ -174,6 +177,11 @@ export type AnyValue<D> = Resource.Value<Resources<D>>
174
177
  * may not need services, because `Policy.schema` gives a Schema that needs
175
178
  * none.
176
179
  *
180
+ * Give `limits` to set the limits of the domain, as
181
+ * `{ limits: { fieldPathParts: 2000 } }`. Each one is a whole number from 1
182
+ * up to its ceiling in `Limits.ceilings`, and a limit that you leave out has
183
+ * its default. A wrong value is a defect.
184
+ *
177
185
  * @stability stable
178
186
  * @category constructors
179
187
  * @since 0.3.0
@@ -186,4 +194,5 @@ export const make: <
186
194
  readonly principal: P
187
195
  readonly resources: Resources
188
196
  readonly meta?: M
197
+ readonly limits?: Partial<Limits.Limits>
189
198
  }) => Domain<P["Type"], Resources[number], M["Type"]> = Internal.make as never