@nmnmcc/ability 2.0.7 → 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 +50 -27
- 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 +116 -16
- 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 +2 -2
- 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 +11 -7
- package/dist/internal/authorizer.js.map +1 -1
- package/dist/internal/bind.js +86 -64
- 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 +147 -72
- 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.map +1 -1
- package/dist/internal/nodes.js +53 -44
- 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 +16 -13
- 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 +19 -5
- package/dist/internal/trampoline.js.map +1 -1
- 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/analysis.ts +154 -124
- package/src/internal/authorizer.ts +29 -14
- package/src/internal/bind.ts +193 -136
- package/src/internal/catalog.ts +295 -112
- 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 +65 -47
- package/src/internal/patterns.ts +72 -26
- package/src/internal/policy-json.ts +266 -197
- package/src/internal/policy-nodes.ts +31 -23
- 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 +51 -4
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.
|
|
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
|
-
:
|
|
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
|
|
507
|
-
|
|
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
|
-
/**
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
/**
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
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
|
-
|
|
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
|