@nmnmcc/ability 2.0.7 → 2.1.2
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 +52 -29
- 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 +121 -19
- package/dist/Condition.d.ts.map +1 -1
- package/dist/Condition.js +32 -21
- 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 +102 -18
- package/dist/Policy.d.ts.map +1 -1
- package/dist/Policy.js +7 -6
- 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 +170 -77
- package/dist/internal/catalog.js.map +1 -1
- package/dist/internal/decide.js +27 -31
- 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 +317 -86
- package/src/Domain.ts +9 -0
- package/src/Limits.ts +69 -29
- package/src/Policy.ts +143 -21
- 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 +320 -118
- package/src/internal/decide.ts +61 -50
- 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 +79 -25
- 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,215 @@ 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
|
+
? // Each path of a union of paths, as of a field typed `FieldSelector`,
|
|
695
|
+
// is checked by itself.
|
|
696
|
+
F extends unknown
|
|
697
|
+
? PathWalk<T, F, "", R, []> extends true
|
|
698
|
+
? F
|
|
699
|
+
: // The names come from parts of `F`. Inference must not find `F`
|
|
700
|
+
// in them, so a call gets its `F` from the path that it gives.
|
|
701
|
+
NoInfer<PathWalk<T, F, "", R, []>>
|
|
702
|
+
: never
|
|
703
|
+
: never
|
|
704
|
+
|
|
705
|
+
/**
|
|
706
|
+
* A path of `T` that a condition may read, as one of {@link FieldPath}, of
|
|
707
|
+
* any length up to about 1000 parts. It is `F` when `F` is such a path, and
|
|
708
|
+
* the names that may come next when it is not.
|
|
709
|
+
*
|
|
710
|
+
* @stability stable
|
|
711
|
+
* @category utility types
|
|
712
|
+
* @since 2.1.0
|
|
713
|
+
*/
|
|
714
|
+
export type ReadPath<T, F extends string> = PathCheck<T, F, ReadRules>
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
* A path of `T` that a request may name, as one of {@link FieldSelector}, of
|
|
718
|
+
* any length up to about 1000 parts. See {@link ReadPath}.
|
|
719
|
+
*
|
|
720
|
+
* @stability stable
|
|
721
|
+
* @category utility types
|
|
722
|
+
* @since 2.1.0
|
|
723
|
+
*/
|
|
724
|
+
export type SelectPath<T, F extends string> = PathCheck<T, F, SelectRules>
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* A path of `T` that a field of a rule may name, as one of
|
|
728
|
+
* {@link FieldName}, of any length up to about 1000 parts. See
|
|
729
|
+
* {@link ReadPath}.
|
|
730
|
+
*
|
|
731
|
+
* @stability stable
|
|
732
|
+
* @category utility types
|
|
733
|
+
* @since 2.1.0
|
|
734
|
+
*/
|
|
735
|
+
export type NamePath<T, F extends string> = PathCheck<T, F, NameRules>
|
|
736
|
+
|
|
737
|
+
/** A path that a condition may read, with an ordered value. */
|
|
738
|
+
type OrderedReadPath<T, F extends string> =
|
|
739
|
+
ReadPath<T, F> extends F
|
|
740
|
+
? Exclude<PathValue<T, F>, null> extends number | string
|
|
741
|
+
? F
|
|
742
|
+
: never
|
|
743
|
+
: ReadPath<T, F>
|
|
744
|
+
|
|
745
|
+
/** A path that a condition may read, with a scalar value. */
|
|
746
|
+
type ScalarReadPath<T, F extends string> =
|
|
747
|
+
ReadPath<T, F> extends F
|
|
748
|
+
? PathValue<T, F> extends Scalar
|
|
749
|
+
? F
|
|
750
|
+
: never
|
|
751
|
+
: ReadPath<T, F>
|
|
752
|
+
|
|
531
753
|
/**
|
|
532
754
|
* A value for a field of type `A`: a fixed value, or a field of the principal
|
|
533
755
|
* with the same type.
|
|
@@ -538,16 +760,6 @@ type ChildOf<T, Name extends string> = Name extends keyof T
|
|
|
538
760
|
*/
|
|
539
761
|
export type OperandOf<A, P = never> = Extract<A, Scalar> | Ref<A, P>
|
|
540
762
|
|
|
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
763
|
/**
|
|
552
764
|
* A test made by a {@link Builder}. It runs no code, but it keeps the value
|
|
553
765
|
* type of its resource, so a test on the fields of one resource can not go
|
|
@@ -584,58 +796,60 @@ type PrincipalOf<V, _P> = [Extract<V, PrincipalRef>] extends [never]
|
|
|
584
796
|
export interface Builder<Data, Value, P> {
|
|
585
797
|
/** The field is equal to the value. */
|
|
586
798
|
readonly eq: <
|
|
587
|
-
const F extends
|
|
799
|
+
const F extends string,
|
|
588
800
|
const V extends OperandOf<FieldValue<Data, F>, any>,
|
|
589
801
|
>(
|
|
590
|
-
field: F
|
|
802
|
+
field: ReadPath<Data, F>,
|
|
591
803
|
value: V,
|
|
592
804
|
) => Test<Value, PrincipalOf<V, P>>
|
|
593
805
|
/** The field is not equal to the value. */
|
|
594
806
|
readonly ne: <
|
|
595
|
-
const F extends
|
|
807
|
+
const F extends string,
|
|
596
808
|
const V extends OperandOf<FieldValue<Data, F>, any>,
|
|
597
809
|
>(
|
|
598
|
-
field: F
|
|
810
|
+
field: ReadPath<Data, F>,
|
|
599
811
|
value: V,
|
|
600
812
|
) => Test<Value, PrincipalOf<V, P>>
|
|
601
813
|
readonly lt: <
|
|
602
|
-
const F extends
|
|
814
|
+
const F extends string,
|
|
603
815
|
const V extends OperandOf<Exclude<FieldValue<Data, F>, null>, any>,
|
|
604
816
|
>(
|
|
605
|
-
field: F
|
|
817
|
+
field: OrderedReadPath<Data, F>,
|
|
606
818
|
value: V,
|
|
607
819
|
) => Test<Value, PrincipalOf<V, P>>
|
|
608
820
|
readonly lte: <
|
|
609
|
-
const F extends
|
|
821
|
+
const F extends string,
|
|
610
822
|
const V extends OperandOf<Exclude<FieldValue<Data, F>, null>, any>,
|
|
611
823
|
>(
|
|
612
|
-
field: F
|
|
824
|
+
field: OrderedReadPath<Data, F>,
|
|
613
825
|
value: V,
|
|
614
826
|
) => Test<Value, PrincipalOf<V, P>>
|
|
615
827
|
readonly gt: <
|
|
616
|
-
const F extends
|
|
828
|
+
const F extends string,
|
|
617
829
|
const V extends OperandOf<Exclude<FieldValue<Data, F>, null>, any>,
|
|
618
830
|
>(
|
|
619
|
-
field: F
|
|
831
|
+
field: OrderedReadPath<Data, F>,
|
|
620
832
|
value: V,
|
|
621
833
|
) => Test<Value, PrincipalOf<V, P>>
|
|
622
834
|
readonly gte: <
|
|
623
|
-
const F extends
|
|
835
|
+
const F extends string,
|
|
624
836
|
const V extends OperandOf<Exclude<FieldValue<Data, F>, null>, any>,
|
|
625
837
|
>(
|
|
626
|
-
field: F
|
|
838
|
+
field: OrderedReadPath<Data, F>,
|
|
627
839
|
value: V,
|
|
628
840
|
) => Test<Value, PrincipalOf<V, P>>
|
|
629
841
|
/** The field is equal to one of the values. */
|
|
630
842
|
readonly in: <
|
|
631
|
-
const F extends
|
|
843
|
+
const F extends string,
|
|
632
844
|
const Vs extends ReadonlyArray<OperandOf<FieldValue<Data, F>, any>>,
|
|
633
845
|
>(
|
|
634
|
-
field: F
|
|
846
|
+
field: ReadPath<Data, F>,
|
|
635
847
|
values: Vs,
|
|
636
848
|
) => Test<Value, PrincipalOf<Vs[number], P>>
|
|
637
849
|
/** The field has a value that is not `null`. */
|
|
638
|
-
readonly exists: <const F extends
|
|
850
|
+
readonly exists: <const F extends string>(
|
|
851
|
+
field: ReadPath<Data, F>,
|
|
852
|
+
) => Test<Value>
|
|
639
853
|
/** The path of the resource starts with these parts. */
|
|
640
854
|
readonly under: <
|
|
641
855
|
const Ps extends ReadonlyArray<string | null | Ref<string | null, any>>,
|
|
@@ -646,8 +860,8 @@ export interface Builder<Data, Value, P> {
|
|
|
646
860
|
* A field of the principal, to use as a value. The field must have a
|
|
647
861
|
* {@link Scalar} type.
|
|
648
862
|
*/
|
|
649
|
-
readonly principal: <const F extends
|
|
650
|
-
field: F
|
|
863
|
+
readonly principal: <const F extends string>(
|
|
864
|
+
field: ScalarReadPath<P, F>,
|
|
651
865
|
) => Ref<PathValue<P, F>, P>
|
|
652
866
|
readonly and: <const Cs extends ReadonlyArray<Any>>(
|
|
653
867
|
...conditions: Cs
|
|
@@ -992,50 +1206,65 @@ const literalValue = (operand: Operand, field: string): Scalar => {
|
|
|
992
1206
|
return operand.value
|
|
993
1207
|
}
|
|
994
1208
|
|
|
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
|
-
|
|
1209
|
+
/**
|
|
1210
|
+
* Folds a condition. A shared child is folded again for each place. The walk
|
|
1211
|
+
* takes the steps of a trampoline, so a deep condition does not fill the
|
|
1212
|
+
* stack.
|
|
1213
|
+
*/
|
|
1214
|
+
const foldNode = <A>(root: Nodes.Node, interpreter: Interpreter<A>): A =>
|
|
1215
|
+
Trampoline.run(root.depth, (R) => {
|
|
1216
|
+
const go = (node: Nodes.Node): Trampoline.Step<A> => {
|
|
1217
|
+
const children = (nodes: ReadonlyArray<Nodes.Node>) =>
|
|
1218
|
+
R.forEach(nodes, (child) => R.suspend(() => go(child)))
|
|
1219
|
+
switch (node._tag) {
|
|
1220
|
+
case "True":
|
|
1221
|
+
return R.succeed(interpreter.true())
|
|
1222
|
+
case "False":
|
|
1223
|
+
return R.succeed(interpreter.false())
|
|
1224
|
+
case "Compare":
|
|
1225
|
+
return R.succeed(
|
|
1226
|
+
interpreter.compare(
|
|
1227
|
+
node.op,
|
|
1228
|
+
node.field,
|
|
1229
|
+
literalValue(node.value, node.field),
|
|
1230
|
+
),
|
|
1231
|
+
)
|
|
1232
|
+
case "In":
|
|
1233
|
+
return R.succeed(
|
|
1234
|
+
interpreter.in(
|
|
1235
|
+
node.field,
|
|
1236
|
+
Arr.map(node.values, (operand) =>
|
|
1237
|
+
literalValue(operand, node.field),
|
|
1238
|
+
),
|
|
1239
|
+
),
|
|
1240
|
+
)
|
|
1241
|
+
case "Exists":
|
|
1242
|
+
return R.succeed(interpreter.exists(node.field))
|
|
1243
|
+
case "Under":
|
|
1244
|
+
throw Untranslatable.make({
|
|
1245
|
+
reason:
|
|
1246
|
+
"An Under node needs the resource path. Call Condition.partial first.",
|
|
1247
|
+
})
|
|
1248
|
+
case "And":
|
|
1249
|
+
return R.map(children(node.conditions), interpreter.and)
|
|
1250
|
+
case "Or":
|
|
1251
|
+
return R.map(children(node.conditions), interpreter.or)
|
|
1252
|
+
case "Not":
|
|
1253
|
+
return R.map(
|
|
1254
|
+
R.suspend(() => go(node.condition)),
|
|
1255
|
+
interpreter.not,
|
|
1256
|
+
)
|
|
1257
|
+
case "Predicate":
|
|
1258
|
+
if (interpreter.predicate === undefined) {
|
|
1259
|
+
throw Untranslatable.make({
|
|
1260
|
+
reason: `The predicate "${node.name}" can not become a query`,
|
|
1261
|
+
})
|
|
1262
|
+
}
|
|
1263
|
+
return R.succeed(interpreter.predicate(node.name))
|
|
1035
1264
|
}
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
}
|
|
1265
|
+
}
|
|
1266
|
+
return go(root)
|
|
1267
|
+
})
|
|
1039
1268
|
|
|
1040
1269
|
/**
|
|
1041
1270
|
* Changes a condition into another form with an interpreter. Call
|
|
@@ -1220,9 +1449,11 @@ export type PlainCondition = Condition<any>
|
|
|
1220
1449
|
* The Schema of a condition with no predicate. It checks the shape only. Use
|
|
1221
1450
|
* `Policy.schema` to check the field names against a domain too.
|
|
1222
1451
|
*
|
|
1223
|
-
* The decoder takes
|
|
1224
|
-
* objects and array items, with a shared
|
|
1225
|
-
*
|
|
1452
|
+
* The decoder takes the default limits: at most `conditionNodes` nodes,
|
|
1453
|
+
* 1000000, and `jsonNodes` objects and array items, 10000000, with a shared
|
|
1454
|
+
* object counted for each place. It stops at the first one past a limit. It
|
|
1455
|
+
* takes any number of levels, and it reads only the own data fields of the
|
|
1456
|
+
* input. Use `Policy.schema` for the limits of a domain.
|
|
1226
1457
|
*
|
|
1227
1458
|
* @stability stable
|
|
1228
1459
|
* @category schemas
|
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
|