@nmnmcc/ability 2.0.6 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -32
- package/dist/Authorizer.d.ts +21 -12
- package/dist/Authorizer.d.ts.map +1 -1
- package/dist/Authorizer.js.map +1 -1
- package/dist/Condition.d.ts +118 -18
- package/dist/Condition.d.ts.map +1 -1
- package/dist/Condition.js +27 -18
- package/dist/Condition.js.map +1 -1
- package/dist/Domain.d.ts +9 -0
- package/dist/Domain.d.ts.map +1 -1
- package/dist/Domain.js +5 -0
- package/dist/Domain.js.map +1 -1
- package/dist/Limits.d.ts +44 -13
- package/dist/Limits.d.ts.map +1 -1
- package/dist/Limits.js +52 -22
- package/dist/Limits.js.map +1 -1
- package/dist/Policy.d.ts +95 -12
- package/dist/Policy.d.ts.map +1 -1
- package/dist/Policy.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/internal/algebra.js +101 -74
- package/dist/internal/algebra.js.map +1 -1
- package/dist/internal/analysis.js +81 -75
- package/dist/internal/analysis.js.map +1 -1
- package/dist/internal/authorizer.d.ts.map +1 -1
- package/dist/internal/authorizer.js +16 -11
- package/dist/internal/authorizer.js.map +1 -1
- package/dist/internal/bind.js +119 -80
- package/dist/internal/bind.js.map +1 -1
- package/dist/internal/catalog.d.ts +33 -10
- package/dist/internal/catalog.d.ts.map +1 -1
- package/dist/internal/catalog.js +153 -78
- package/dist/internal/catalog.js.map +1 -1
- package/dist/internal/decide.js +25 -29
- package/dist/internal/decide.js.map +1 -1
- package/dist/internal/domain.js +19 -5
- package/dist/internal/domain.js.map +1 -1
- package/dist/internal/json.js +120 -76
- package/dist/internal/json.js.map +1 -1
- package/dist/internal/limits.d.ts +28 -0
- package/dist/internal/limits.d.ts.map +1 -1
- package/dist/internal/limits.js +75 -16
- package/dist/internal/limits.js.map +1 -1
- package/dist/internal/nodes.d.ts +7 -0
- package/dist/internal/nodes.d.ts.map +1 -1
- package/dist/internal/nodes.js +86 -47
- package/dist/internal/nodes.js.map +1 -1
- package/dist/internal/patterns.js +50 -15
- package/dist/internal/patterns.js.map +1 -1
- package/dist/internal/policy-json.js +169 -127
- package/dist/internal/policy-json.js.map +1 -1
- package/dist/internal/policy-nodes.d.ts.map +1 -1
- package/dist/internal/policy-nodes.js +17 -14
- package/dist/internal/policy-nodes.js.map +1 -1
- package/dist/internal/policy.d.ts.map +1 -1
- package/dist/internal/policy.js +38 -22
- package/dist/internal/policy.js.map +1 -1
- package/dist/internal/resource.js +1 -1
- package/dist/internal/rule.d.ts.map +1 -1
- package/dist/internal/rule.js +6 -5
- package/dist/internal/rule.js.map +1 -1
- package/dist/internal/search.d.ts.map +1 -1
- package/dist/internal/search.js +106 -92
- package/dist/internal/search.js.map +1 -1
- package/dist/internal/trampoline.js +89 -0
- package/dist/internal/trampoline.js.map +1 -0
- package/package.json +1 -1
- package/src/Authorizer.ts +30 -20
- package/src/Condition.ts +308 -83
- package/src/Domain.ts +9 -0
- package/src/Limits.ts +69 -29
- package/src/Policy.ts +131 -15
- package/src/internal/algebra.ts +218 -135
- package/src/internal/analysis.ts +154 -122
- package/src/internal/authorizer.ts +34 -16
- package/src/internal/bind.ts +279 -148
- package/src/internal/catalog.ts +307 -133
- package/src/internal/decide.ts +58 -49
- package/src/internal/domain.ts +39 -3
- package/src/internal/json.ts +212 -117
- package/src/internal/limits.ts +101 -31
- package/src/internal/nodes.ts +101 -59
- package/src/internal/patterns.ts +72 -26
- package/src/internal/policy-json.ts +266 -197
- package/src/internal/policy-nodes.ts +33 -24
- package/src/internal/policy.ts +63 -23
- package/src/internal/rule.ts +16 -3
- package/src/internal/search.ts +186 -136
- package/src/internal/trampoline.ts +194 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walks that do not fill the stack.
|
|
3
|
+
*
|
|
4
|
+
* A walk is written one time, with the steps of a {@link Runner}, and a
|
|
5
|
+
* runner runs it:
|
|
6
|
+
* - {@link direct} runs each step at once, as a plain call does. It is fast,
|
|
7
|
+
* and it is for an input with few levels.
|
|
8
|
+
* - {@link loop} puts each step into the run loop of an Effect. A step gives
|
|
9
|
+
* the next step in place of calling it, and the loop runs one step after
|
|
10
|
+
* the other, so the stack does not grow with the levels of the input. This
|
|
11
|
+
* is a trampoline.
|
|
12
|
+
*
|
|
13
|
+
* {@link run} takes `direct` for an input with at most `directDepth` levels,
|
|
14
|
+
* and `loop` for a deeper one. A walk makes each call for a child through
|
|
15
|
+
* `suspend`, so the loop makes the step of the child only when it runs it.
|
|
16
|
+
*/
|
|
17
|
+
import * as Arr from "effect/Array"
|
|
18
|
+
import * as Cause from "effect/Cause"
|
|
19
|
+
import * as Effect from "effect/Effect"
|
|
20
|
+
import * as Exit from "effect/Exit"
|
|
21
|
+
import * as Option from "effect/Option"
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A step of a walk that gives an `A`. A runner of steps knows what a step
|
|
25
|
+
* is: the value itself for `direct`, and an Effect for `loop`. The type is
|
|
26
|
+
* only in the types.
|
|
27
|
+
*/
|
|
28
|
+
export interface Step<A> {
|
|
29
|
+
readonly "~Step": (_: never) => A
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** The steps that a walk may take. */
|
|
33
|
+
export interface Runner {
|
|
34
|
+
readonly succeed: <A>(value: A) => Step<A>
|
|
35
|
+
/** The step that `step` makes, when the runner runs it. */
|
|
36
|
+
readonly suspend: <A>(step: () => Step<A>) => Step<A>
|
|
37
|
+
readonly map: <A, B>(step: Step<A>, f: (value: A) => B) => Step<B>
|
|
38
|
+
readonly flatMap: <A, B>(step: Step<A>, f: (value: A) => Step<B>) => Step<B>
|
|
39
|
+
/** Runs a step for each item, in order, and gives their values. */
|
|
40
|
+
readonly forEach: <A, B>(
|
|
41
|
+
items: ReadonlyArray<A>,
|
|
42
|
+
f: (item: A, index: number) => Step<B>,
|
|
43
|
+
) => Step<ReadonlyArray<B>>
|
|
44
|
+
/**
|
|
45
|
+
* Runs a step for each item, in order, with the value of the step before.
|
|
46
|
+
* It does not grow the stack with the number of items.
|
|
47
|
+
*/
|
|
48
|
+
readonly reduce: <A, B>(
|
|
49
|
+
items: ReadonlyArray<A>,
|
|
50
|
+
initial: B,
|
|
51
|
+
f: (before: B, item: A) => Step<B>,
|
|
52
|
+
) => Step<B>
|
|
53
|
+
/** Runs a step for each item, in order, up to the first `true`. */
|
|
54
|
+
readonly some: <A>(
|
|
55
|
+
items: ReadonlyArray<A>,
|
|
56
|
+
f: (item: A) => Step<boolean>,
|
|
57
|
+
) => Step<boolean>
|
|
58
|
+
/** Runs a step for each item, in order, up to the first `false`. */
|
|
59
|
+
readonly every: <A>(
|
|
60
|
+
items: ReadonlyArray<A>,
|
|
61
|
+
f: (item: A) => Step<boolean>,
|
|
62
|
+
) => Step<boolean>
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// A step of `direct` is its value. The casts below only change the type.
|
|
66
|
+
const value = <A>(step: Step<A>): A => step as unknown as A
|
|
67
|
+
const step = <A>(value: A): Step<A> => value as unknown as Step<A>
|
|
68
|
+
|
|
69
|
+
/** Runs each step at once, on the stack. */
|
|
70
|
+
// A step of `direct` is its value, so a function that gives a step gives a
|
|
71
|
+
// value too. The runner passes such a function on with no wrap: a wrap for
|
|
72
|
+
// each item would be a call more for each node of a walk.
|
|
73
|
+
export const direct: Runner = {
|
|
74
|
+
succeed: step,
|
|
75
|
+
suspend: (make) => make(),
|
|
76
|
+
map: (from, f) => step(f(value(from))),
|
|
77
|
+
flatMap: (from, f) => f(value(from)),
|
|
78
|
+
forEach: (items, f) => step(Arr.map(items, f as never)),
|
|
79
|
+
reduce: (items, initial, f) => step(Arr.reduce(items, initial, f as never)),
|
|
80
|
+
some: (items, f) => step(Arr.some(items, f as never)),
|
|
81
|
+
every: (items, f) => step(Arr.every(items, f as never)),
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// A step of `loop` is an Effect with no error and no services. A failure of a
|
|
85
|
+
// walk is a thrown error, which `run` gives back as it was.
|
|
86
|
+
type Loop<A> = Effect.Effect<A>
|
|
87
|
+
const effect = <A>(step: Step<A>): Loop<A> => step as unknown as Loop<A>
|
|
88
|
+
const fromEffect = <A>(effect: Loop<A>): Step<A> => effect as unknown as Step<A>
|
|
89
|
+
|
|
90
|
+
/** Runs each step in the run loop of an Effect, so a deep walk does not fill the stack. */
|
|
91
|
+
export const loop: Runner = {
|
|
92
|
+
succeed: (value) => fromEffect(Effect.succeed(value)),
|
|
93
|
+
suspend: (make) => fromEffect(Effect.suspend(() => effect(make()))),
|
|
94
|
+
map: (from, f) => fromEffect(Effect.map(effect(from), f)),
|
|
95
|
+
flatMap: (from, f) =>
|
|
96
|
+
fromEffect(Effect.flatMap(effect(from), (value) => effect(f(value)))),
|
|
97
|
+
forEach: (items, f) =>
|
|
98
|
+
fromEffect(Effect.forEach(items, (item, index) => effect(f(item, index)))),
|
|
99
|
+
reduce: (items, initial, f) =>
|
|
100
|
+
fromEffect(
|
|
101
|
+
Effect.reduce(
|
|
102
|
+
items,
|
|
103
|
+
() => initial,
|
|
104
|
+
(before, item) => effect(f(before, item)),
|
|
105
|
+
),
|
|
106
|
+
),
|
|
107
|
+
some: (items, f) =>
|
|
108
|
+
fromEffect(
|
|
109
|
+
Effect.map(
|
|
110
|
+
Effect.findFirst(items, (item) => effect(f(item))),
|
|
111
|
+
Option.isSome,
|
|
112
|
+
),
|
|
113
|
+
),
|
|
114
|
+
every: (items, f) =>
|
|
115
|
+
fromEffect(
|
|
116
|
+
Effect.map(
|
|
117
|
+
Effect.findFirst(items, (item) =>
|
|
118
|
+
Effect.map(effect(f(item)), (value) => !value),
|
|
119
|
+
),
|
|
120
|
+
Option.isNone,
|
|
121
|
+
),
|
|
122
|
+
),
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* The most levels of an input that `run` walks with `direct`. A level takes
|
|
127
|
+
* a few calls of the walk and of the runner on the stack, so this keeps the
|
|
128
|
+
* stack far from full, and most inputs take the fast way.
|
|
129
|
+
*/
|
|
130
|
+
export const directDepth = 200
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Gives the runner for an input with `depth` levels. The walks of a condition
|
|
134
|
+
* or a policy tree know the depth of the input from its node. A walk of an
|
|
135
|
+
* input with an unknown depth, as a decoder, takes `loop`.
|
|
136
|
+
*/
|
|
137
|
+
export const runnerFor = (depth: number): Runner =>
|
|
138
|
+
depth <= directDepth ? direct : loop
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Runs a walk at once, with the runner for `depth` levels, and gives its
|
|
142
|
+
* value. An error that a step throws comes out as it was, also from `loop`.
|
|
143
|
+
*/
|
|
144
|
+
export const run = <A>(depth: number, walk: (runner: Runner) => Step<A>): A =>
|
|
145
|
+
runWith(runnerFor(depth), walk)
|
|
146
|
+
|
|
147
|
+
/** Runs a walk at once with a runner, as {@link run} does. */
|
|
148
|
+
export const runWith = <A>(
|
|
149
|
+
runner: Runner,
|
|
150
|
+
walk: (runner: Runner) => Step<A>,
|
|
151
|
+
): A => {
|
|
152
|
+
if (runner === direct) {
|
|
153
|
+
return value(walk(direct))
|
|
154
|
+
}
|
|
155
|
+
return Exit.match(Effect.runSyncExit(effect(walk(loop))), {
|
|
156
|
+
onSuccess: (result) => result,
|
|
157
|
+
onFailure: (cause) => {
|
|
158
|
+
throw Cause.squash(cause)
|
|
159
|
+
},
|
|
160
|
+
})
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Makes a walk of an input with an unknown depth, as the input of a decoder.
|
|
165
|
+
* It runs with `direct` while the input is low. A part more than
|
|
166
|
+
* `directDepth` levels down runs with `loop`, and the walk stays in the loop
|
|
167
|
+
* below it, so it goes into the loop one time on each path. `walk` gets the
|
|
168
|
+
* runner, and the call for a child at the next level: `child(item, depth)`.
|
|
169
|
+
*/
|
|
170
|
+
export const adaptive = <I, A>(
|
|
171
|
+
walk: (
|
|
172
|
+
R: Runner,
|
|
173
|
+
child: (item: I, depth: number) => Step<A>,
|
|
174
|
+
) => (item: I, depth: number) => Step<A>,
|
|
175
|
+
): ((item: I) => A) => {
|
|
176
|
+
const inLoop: (item: I, depth: number) => Step<A> = walk(
|
|
177
|
+
loop,
|
|
178
|
+
(item, depth) => loop.suspend(() => inLoop(item, depth)),
|
|
179
|
+
)
|
|
180
|
+
const onStack: (item: I, depth: number) => Step<A> = walk(
|
|
181
|
+
direct,
|
|
182
|
+
(item, depth) =>
|
|
183
|
+
depth > directDepth
|
|
184
|
+
? step(runWith(loop, () => inLoop(item, depth)))
|
|
185
|
+
: onStack(item, depth),
|
|
186
|
+
)
|
|
187
|
+
return (item) => value(onStack(item, 1))
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Gives the Effect of a step of `loop`, so a walk can go on in an Effect
|
|
192
|
+
* that runs a predicate.
|
|
193
|
+
*/
|
|
194
|
+
export const toEffect = <A>(step: Step<A>): Effect.Effect<A> => effect(step)
|