@nmnmcc/ability 0.2.0 → 0.3.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 (83) hide show
  1. package/README.md +322 -469
  2. package/dist/Authorizer.d.ts +216 -0
  3. package/dist/Authorizer.d.ts.map +1 -0
  4. package/dist/Authorizer.js +55 -0
  5. package/dist/Authorizer.js.map +1 -0
  6. package/dist/Condition.d.ts +536 -0
  7. package/dist/Condition.d.ts.map +1 -0
  8. package/dist/Condition.js +141 -0
  9. package/dist/Condition.js.map +1 -0
  10. package/dist/Decision.d.ts +131 -0
  11. package/dist/Decision.d.ts.map +1 -0
  12. package/dist/Decision.js +83 -0
  13. package/dist/Decision.js.map +1 -0
  14. package/dist/Domain.d.ts +148 -0
  15. package/dist/Domain.d.ts.map +1 -0
  16. package/dist/Domain.js +34 -0
  17. package/dist/Domain.js.map +1 -0
  18. package/dist/HttpApi.d.ts +129 -0
  19. package/dist/HttpApi.d.ts.map +1 -0
  20. package/dist/HttpApi.js +95 -0
  21. package/dist/HttpApi.js.map +1 -0
  22. package/dist/Policy.d.ts +429 -0
  23. package/dist/Policy.d.ts.map +1 -0
  24. package/dist/Policy.js +162 -0
  25. package/dist/Policy.js.map +1 -0
  26. package/dist/Principal.d.ts +35 -0
  27. package/dist/Principal.d.ts.map +1 -0
  28. package/dist/Principal.js +37 -0
  29. package/dist/Principal.js.map +1 -0
  30. package/dist/Resource.d.ts +213 -0
  31. package/dist/Resource.d.ts.map +1 -0
  32. package/dist/Resource.js +71 -0
  33. package/dist/Resource.js.map +1 -0
  34. package/dist/Rule.d.ts +189 -0
  35. package/dist/Rule.d.ts.map +1 -0
  36. package/dist/Rule.js +50 -0
  37. package/dist/Rule.js.map +1 -0
  38. package/dist/_virtual/_rolldown/runtime.js +1 -2
  39. package/dist/index.d.ts +9 -3
  40. package/dist/index.js +9 -3
  41. package/dist/internal/authorizer.d.ts +28 -0
  42. package/dist/internal/authorizer.d.ts.map +1 -0
  43. package/dist/internal/authorizer.js +153 -0
  44. package/dist/internal/authorizer.js.map +1 -0
  45. package/dist/internal/condition.d.ts +11 -0
  46. package/dist/internal/condition.d.ts.map +1 -0
  47. package/dist/internal/condition.js +393 -0
  48. package/dist/internal/condition.js.map +1 -0
  49. package/dist/internal/domain.js +34 -0
  50. package/dist/internal/domain.js.map +1 -0
  51. package/dist/internal/httpApi.js +41 -0
  52. package/dist/internal/httpApi.js.map +1 -0
  53. package/dist/internal/policy.js +524 -0
  54. package/dist/internal/policy.js.map +1 -0
  55. package/dist/internal/resource.js +66 -0
  56. package/dist/internal/resource.js.map +1 -0
  57. package/dist/internal/rule.js +131 -0
  58. package/dist/internal/rule.js.map +1 -0
  59. package/package.json +61 -72
  60. package/src/Authorizer.ts +330 -0
  61. package/src/Condition.ts +706 -0
  62. package/src/Decision.ts +117 -0
  63. package/src/Domain.ts +189 -0
  64. package/src/HttpApi.ts +148 -0
  65. package/src/Policy.ts +575 -0
  66. package/src/Principal.ts +41 -0
  67. package/src/Resource.ts +290 -0
  68. package/src/Rule.ts +265 -0
  69. package/src/index.ts +57 -0
  70. package/src/internal/authorizer.ts +271 -0
  71. package/src/internal/condition.ts +607 -0
  72. package/src/internal/domain.ts +56 -0
  73. package/src/internal/httpApi.ts +84 -0
  74. package/src/internal/policy.ts +815 -0
  75. package/src/internal/resource.ts +98 -0
  76. package/src/internal/rule.ts +203 -0
  77. package/dist/Ability.d.ts +0 -491
  78. package/dist/Ability.js +0 -207
  79. package/dist/AbilityExtra.d.ts +0 -79
  80. package/dist/AbilityExtra.js +0 -187
  81. package/dist/internal/ability.d.ts +0 -90
  82. package/dist/internal/ability.js +0 -550
  83. package/dist/internal/serializable.js +0 -22
package/src/Policy.ts ADDED
@@ -0,0 +1,575 @@
1
+ /**
2
+ * A policy is a tree that gives a {@link Decision.Decision} for a request.
3
+ *
4
+ * The leaves of the tree are lists of rules. A combining algorithm decides
5
+ * which rule gives the answer when more than one rule applies:
6
+ * - `denyOverrides` (the default): a deny rule wins over every allow rule.
7
+ * - `permitOverrides`: an allow rule wins over every deny rule.
8
+ * - `firstApplicable`: the first rule that applies wins.
9
+ * - `lastApplicable`: the last rule that applies wins.
10
+ *
11
+ * The branches put policies together:
12
+ * - {@link all}: every policy must allow, and one deny is enough to deny. Use
13
+ * it when a user token may never do more than its user.
14
+ * - {@link any}: one allow is enough.
15
+ * - {@link firstOf}: the first policy that gives an answer wins. Use it for
16
+ * grants first, then rules.
17
+ * - {@link ceiling}: the deny rules of a second policy are a limit for
18
+ * everyone. Its allow rules do nothing.
19
+ *
20
+ * A policy gives three kinds of answers:
21
+ * - {@link decide}: the decision for one resource value.
22
+ * - {@link residual}: a condition on resource values. A value passes when the
23
+ * policy allows the request for that value. Use it to make a database
24
+ * query, or to ask "may this principal do this act on some resource of
25
+ * this kind?"
26
+ * - {@link permittedFields}: the fields that the policy lets a request use.
27
+ *
28
+ * A policy without predicates can become JSON with {@link schema}.
29
+ *
30
+ * @stability stable
31
+ * @since 0.3.0
32
+ */
33
+ import type * as Effect from "effect/Effect"
34
+ import type * as Equal from "effect/Equal"
35
+ import type * as Inspectable from "effect/Inspectable"
36
+ import type * as Pipeable from "effect/Pipeable"
37
+ import type * as Schema from "effect/Schema"
38
+ import type * as Condition from "./Condition.ts"
39
+ import type * as Decision from "./Decision.ts"
40
+ import type * as Domain from "./Domain.ts"
41
+ import * as internal from "./internal/policy.ts"
42
+ import type * as Rule from "./Rule.ts"
43
+
44
+ /**
45
+ * @stability stable
46
+ * @category type IDs
47
+ * @since 0.3.0
48
+ */
49
+ export const TypeId: "~@nmnmcc/ability/Policy" = internal.TypeId
50
+
51
+ /**
52
+ * @stability stable
53
+ * @category type IDs
54
+ * @since 0.3.0
55
+ */
56
+ export type TypeId = typeof TypeId
57
+
58
+ /**
59
+ * @stability stable
60
+ * @category models
61
+ * @since 0.3.0
62
+ */
63
+ export type Algorithm =
64
+ "denyOverrides" | "permitOverrides" | "firstApplicable" | "lastApplicable"
65
+
66
+ /**
67
+ * @stability stable
68
+ * @category models
69
+ * @since 0.3.0
70
+ */
71
+ export interface RulesNode {
72
+ readonly _tag: "Rules"
73
+ readonly algorithm: Algorithm
74
+ readonly rules: ReadonlyArray<Rule.Any>
75
+ }
76
+
77
+ /**
78
+ * @stability stable
79
+ * @category models
80
+ * @since 0.3.0
81
+ */
82
+ export interface AllNode {
83
+ readonly _tag: "All"
84
+ readonly policies: ReadonlyArray<Node>
85
+ }
86
+
87
+ /**
88
+ * @stability stable
89
+ * @category models
90
+ * @since 0.3.0
91
+ */
92
+ export interface AnyNode {
93
+ readonly _tag: "Any"
94
+ readonly policies: ReadonlyArray<Node>
95
+ }
96
+
97
+ /**
98
+ * @stability stable
99
+ * @category models
100
+ * @since 0.3.0
101
+ */
102
+ export interface FirstOfNode {
103
+ readonly _tag: "FirstOf"
104
+ readonly policies: ReadonlyArray<Node>
105
+ }
106
+
107
+ /**
108
+ * @stability stable
109
+ * @category models
110
+ * @since 0.3.0
111
+ */
112
+ export interface CeilingNode {
113
+ readonly _tag: "Ceiling"
114
+ readonly cap: Node
115
+ readonly policy: Node
116
+ }
117
+
118
+ /**
119
+ * The nodes of a policy tree.
120
+ *
121
+ * @stability stable
122
+ * @category models
123
+ * @since 0.3.0
124
+ */
125
+ export type Node = RulesNode | AllNode | AnyNode | FirstOfNode | CeilingNode
126
+
127
+ /**
128
+ * A policy for the domain `D`. `E`, `R` and `O` come from the conditions of
129
+ * its rules. See `Condition.Condition`.
130
+ *
131
+ * @stability stable
132
+ * @category models
133
+ * @since 0.3.0
134
+ */
135
+ export interface Policy<D extends Domain.Any, E = never, R = never, O = never>
136
+ extends Equal.Equal, Inspectable.Inspectable, Pipeable.Pipeable {
137
+ readonly [TypeId]: TypeId
138
+ readonly domain: D
139
+ readonly node: Node
140
+ readonly "~Policy"?: Condition.Variance<E, R, O>
141
+ }
142
+
143
+ /**
144
+ * Any policy.
145
+ *
146
+ * @stability stable
147
+ * @category models
148
+ * @since 0.3.0
149
+ */
150
+ export type Any = Policy<any, any, any, any>
151
+
152
+ /**
153
+ * The domain of a policy.
154
+ *
155
+ * @stability stable
156
+ * @category utility types
157
+ * @since 0.3.0
158
+ */
159
+ export type DomainOf<P> = P extends Policy<infer D, any, any, any> ? D : never
160
+
161
+ /**
162
+ * The error type of a policy.
163
+ *
164
+ * @stability stable
165
+ * @category utility types
166
+ * @since 0.3.0
167
+ */
168
+ export type Error<P> = P extends {
169
+ readonly "~Policy"?: Condition.Variance<infer E, infer _R, infer _O>
170
+ }
171
+ ? E
172
+ : never
173
+
174
+ /**
175
+ * The service type of a policy.
176
+ *
177
+ * @stability stable
178
+ * @category utility types
179
+ * @since 0.3.0
180
+ */
181
+ export type Services<P> = P extends {
182
+ readonly "~Policy"?: Condition.Variance<infer _E, infer R, infer _O>
183
+ }
184
+ ? R
185
+ : never
186
+
187
+ /**
188
+ * `Condition.Opaque` when a policy has a predicate.
189
+ *
190
+ * @stability stable
191
+ * @category utility types
192
+ * @since 0.3.0
193
+ */
194
+ export type OpaqueOf<P> = P extends {
195
+ readonly "~Policy"?: Condition.Variance<infer _E, infer _R, infer O>
196
+ }
197
+ ? O
198
+ : never
199
+
200
+ /**
201
+ * One act on one resource value, for each kind of the domain. The action must
202
+ * be an action of the kind, and the field must be a field of the kind.
203
+ *
204
+ * @stability stable
205
+ * @category models
206
+ * @since 0.3.0
207
+ */
208
+ export type Target<D> = {
209
+ [K in Domain.Kind<D>]: {
210
+ readonly action: Domain.ActionOf<D, K>
211
+ readonly resource: Domain.ValueOf<D, K>
212
+ readonly field?: Condition.FieldPath<Domain.DataOf<D, K>>
213
+ }
214
+ }[Domain.Kind<D>]
215
+
216
+ /**
217
+ * One act on one kind of resource, with no value.
218
+ *
219
+ * @stability stable
220
+ * @category models
221
+ * @since 0.3.0
222
+ */
223
+ export type KindTarget<D> = {
224
+ [K in Domain.Kind<D>]: {
225
+ readonly action: Domain.ActionOf<D, K>
226
+ readonly kind: K
227
+ readonly field?: Condition.FieldPath<Domain.DataOf<D, K>>
228
+ }
229
+ }[Domain.Kind<D>]
230
+
231
+ /**
232
+ * A request: a principal, an action, and a resource value.
233
+ *
234
+ * @stability stable
235
+ * @category models
236
+ * @since 0.3.0
237
+ */
238
+ export type Request<D> = Target<D> & { readonly principal: Domain.Principal<D> }
239
+
240
+ /**
241
+ * A request about a kind of resource, with no value.
242
+ *
243
+ * @stability stable
244
+ * @category models
245
+ * @since 0.3.0
246
+ */
247
+ export type KindRequest<D> = KindTarget<D> & {
248
+ readonly principal: Domain.Principal<D>
249
+ }
250
+
251
+ /**
252
+ * A request with no types.
253
+ *
254
+ * @stability stable
255
+ * @category models
256
+ * @since 0.3.0
257
+ */
258
+ export interface AnyRequest {
259
+ readonly principal: object
260
+ readonly action: string
261
+ readonly resource: object
262
+ readonly field?: string | undefined
263
+ }
264
+
265
+ /**
266
+ * One rule that a decision tested. `path` gives the place of the rule in the
267
+ * policy tree: the index of each child, then the index of the rule.
268
+ *
269
+ * @stability stable
270
+ * @category models
271
+ * @since 0.3.0
272
+ */
273
+ export interface Step {
274
+ readonly path: ReadonlyArray<number>
275
+ readonly rule: Rule.Any
276
+ readonly applies: boolean
277
+ }
278
+
279
+ /**
280
+ * A decision, and the rules that were tested to make it, in order. Keep it in
281
+ * an audit log.
282
+ *
283
+ * @stability stable
284
+ * @category models
285
+ * @since 0.3.0
286
+ */
287
+ export interface Explanation {
288
+ readonly decision: Decision.Decision
289
+ readonly steps: ReadonlyArray<Step>
290
+ }
291
+
292
+ /**
293
+ * The options of a list of rules.
294
+ *
295
+ * @stability stable
296
+ * @category models
297
+ * @since 0.3.0
298
+ */
299
+ export interface Options {
300
+ /** The default is `denyOverrides`. */
301
+ readonly algorithm?: Algorithm
302
+ }
303
+
304
+ /**
305
+ * Makes a policy from a generator function that gives rules. It is pure and it
306
+ * gives its result at once.
307
+ *
308
+ * @example
309
+ * ```ts
310
+ * const policy = Policy.define(App)(function* (_) {
311
+ * yield* _.allow("read", Bot)
312
+ * yield* _.allow(["update", "delete"], Bot, {
313
+ * when: ($) => $.eq("ownerUserId", $.principal("userId")),
314
+ * })
315
+ * })
316
+ * ```
317
+ *
318
+ * @stability stable
319
+ * @category constructors
320
+ * @since 0.3.0
321
+ */
322
+ export const define: <D extends Domain.Any>(
323
+ domain: D,
324
+ options?: Options,
325
+ ) => <Rules extends Rule.Any, A>(
326
+ body: (builder: Rule.Builder<D>) => Generator<Rules, A, unknown>,
327
+ ) => Policy<D, Rule.Error<Rules>, Rule.Services<Rules>, Rule.OpaqueOf<Rules>> =
328
+ internal.define as never
329
+
330
+ /**
331
+ * Makes a policy from a list of rules.
332
+ *
333
+ * @stability stable
334
+ * @category constructors
335
+ * @since 0.3.0
336
+ */
337
+ export const rules: <D extends Domain.Any, Rules extends Rule.Any>(
338
+ domain: D,
339
+ rules: Iterable<Rules>,
340
+ options?: Options,
341
+ ) => Policy<D, Rule.Error<Rules>, Rule.Services<Rules>, Rule.OpaqueOf<Rules>> =
342
+ internal.rules
343
+
344
+ /**
345
+ * A policy with no rules. It is not applicable to any request.
346
+ *
347
+ * @stability stable
348
+ * @category constructors
349
+ * @since 0.3.0
350
+ */
351
+ export const empty: <D extends Domain.Any>(domain: D) => Policy<D> =
352
+ internal.empty
353
+
354
+ type Combined<D extends Domain.Any, Ps extends ReadonlyArray<Any>> = Policy<
355
+ D,
356
+ Error<Ps[number]>,
357
+ Services<Ps[number]>,
358
+ OpaqueOf<Ps[number]>
359
+ >
360
+
361
+ /**
362
+ * Every policy must allow, and one deny is enough to deny. With some policies
363
+ * not applicable and none that deny, the result is not applicable.
364
+ *
365
+ * @stability stable
366
+ * @category combinators
367
+ * @since 0.3.0
368
+ */
369
+ export const all: <
370
+ const Ps extends readonly [Policy<any, any, any, any>, ...Array<Any>],
371
+ >(
372
+ policies: Ps,
373
+ ) => Combined<DomainOf<Ps[0]>, Ps> = internal.all
374
+
375
+ /**
376
+ * One allow is enough. Without an allow, one deny gives a deny.
377
+ *
378
+ * @stability stable
379
+ * @category combinators
380
+ * @since 0.3.0
381
+ */
382
+ export const any: <
383
+ const Ps extends readonly [Policy<any, any, any, any>, ...Array<Any>],
384
+ >(
385
+ policies: Ps,
386
+ ) => Combined<DomainOf<Ps[0]>, Ps> = internal.any
387
+
388
+ /**
389
+ * The first policy that allows or denies gives the answer.
390
+ *
391
+ * @stability stable
392
+ * @category combinators
393
+ * @since 0.3.0
394
+ */
395
+ export const firstOf: <
396
+ const Ps extends readonly [Policy<any, any, any, any>, ...Array<Any>],
397
+ >(
398
+ policies: Ps,
399
+ ) => Combined<DomainOf<Ps[0]>, Ps> = internal.firstOf
400
+
401
+ /**
402
+ * Puts a limit on a policy. A deny from `cap` always wins. An allow from `cap`
403
+ * does nothing.
404
+ *
405
+ * @stability stable
406
+ * @category combinators
407
+ * @since 0.3.0
408
+ */
409
+ export const ceiling: {
410
+ <D extends Domain.Any, E2, R2, O2>(
411
+ cap: Policy<D, E2, R2, O2>,
412
+ ): <E, R, O>(policy: Policy<D, E, R, O>) => Policy<D, E | E2, R | R2, O | O2>
413
+ <D extends Domain.Any, E, R, O, E2, R2, O2>(
414
+ policy: Policy<D, E, R, O>,
415
+ cap: Policy<D, E2, R2, O2>,
416
+ ): Policy<D, E | E2, R | R2, O | O2>
417
+ } = internal.ceiling
418
+
419
+ /**
420
+ * Gives the decision of a policy for a request.
421
+ *
422
+ * @stability stable
423
+ * @category evaluation
424
+ * @since 0.3.0
425
+ */
426
+ export const decide: {
427
+ <D extends Domain.Any>(
428
+ request: Request<D>,
429
+ ): <E, R, O>(
430
+ policy: Policy<D, E, R, O>,
431
+ ) => Effect.Effect<Decision.Decision, E, R>
432
+ <D extends Domain.Any, E, R, O>(
433
+ policy: Policy<D, E, R, O>,
434
+ request: Request<NoInfer<D>>,
435
+ ): Effect.Effect<Decision.Decision, E, R>
436
+ } = internal.decide as never
437
+
438
+ /**
439
+ * Gives the decision of a policy with no predicates, at once.
440
+ *
441
+ * @stability stable
442
+ * @category evaluation
443
+ * @since 0.3.0
444
+ */
445
+ export const decideSync: {
446
+ <D extends Domain.Any>(
447
+ request: Request<D>,
448
+ ): (policy: Policy<D>) => Decision.Decision
449
+ <D extends Domain.Any>(
450
+ policy: Policy<D>,
451
+ request: Request<NoInfer<D>>,
452
+ ): Decision.Decision
453
+ } = internal.decideSync
454
+
455
+ /**
456
+ * Gives the decision of a policy and the rules that were tested to make it.
457
+ *
458
+ * @stability stable
459
+ * @category evaluation
460
+ * @since 0.3.0
461
+ */
462
+ export const explain: {
463
+ <D extends Domain.Any>(
464
+ request: Request<D>,
465
+ ): <E, R, O>(policy: Policy<D, E, R, O>) => Effect.Effect<Explanation, E, R>
466
+ <D extends Domain.Any, E, R, O>(
467
+ policy: Policy<D, E, R, O>,
468
+ request: Request<NoInfer<D>>,
469
+ ): Effect.Effect<Explanation, E, R>
470
+ } = internal.explain as never
471
+
472
+ /**
473
+ * Gives the condition on resource values for which the policy allows a
474
+ * request. It has no principal fields and no `Under` nodes, so you can give it
475
+ * to `Condition.fold`. It is `True` when the policy allows every value of the
476
+ * kind, and `False` when it allows none.
477
+ *
478
+ * Predicates stay in the condition. They take the principal with them.
479
+ *
480
+ * @stability stable
481
+ * @category evaluation
482
+ * @since 0.3.0
483
+ */
484
+ export const residual: {
485
+ <D extends Domain.Any>(
486
+ request: KindRequest<D>,
487
+ ): <E, R, O>(policy: Policy<D, E, R, O>) => Condition.Condition<E, R, O>
488
+ <D extends Domain.Any, E, R, O>(
489
+ policy: Policy<D, E, R, O>,
490
+ request: KindRequest<NoInfer<D>>,
491
+ ): Condition.Condition<E, R, O>
492
+ } = internal.residual as never
493
+
494
+ /**
495
+ * Gives the fields of a resource value that the policy lets a request use. It
496
+ * tests each field of the resource Schema, with dots for nested fields.
497
+ *
498
+ * @stability stable
499
+ * @category evaluation
500
+ * @since 0.3.0
501
+ */
502
+ export const permittedFields: {
503
+ <D extends Domain.Any>(
504
+ request: Omit<Request<D>, "field">,
505
+ ): <E, R, O>(
506
+ policy: Policy<D, E, R, O>,
507
+ ) => Effect.Effect<ReadonlyArray<string>, E, R>
508
+ <D extends Domain.Any, E, R, O>(
509
+ policy: Policy<D, E, R, O>,
510
+ request: Omit<Request<NoInfer<D>>, "field">,
511
+ ): Effect.Effect<ReadonlyArray<string>, E, R>
512
+ } = internal.permittedFields as never
513
+
514
+ /**
515
+ * The JSON form of a rule.
516
+ *
517
+ * @stability stable
518
+ * @category models
519
+ * @since 0.3.0
520
+ */
521
+ export interface EncodedRule {
522
+ readonly _tag: "Allow" | "Deny"
523
+ readonly actions: ReadonlyArray<string>
524
+ readonly resources: ReadonlyArray<string>
525
+ readonly when?: Condition.Encoded
526
+ readonly fields?: ReadonlyArray<string>
527
+ readonly reason?: string
528
+ readonly id?: string
529
+ readonly meta?: unknown
530
+ }
531
+
532
+ /**
533
+ * The JSON form of a policy.
534
+ *
535
+ * @stability stable
536
+ * @category models
537
+ * @since 0.3.0
538
+ */
539
+ export type EncodedNode =
540
+ | {
541
+ readonly _tag: "Rules"
542
+ readonly algorithm: Algorithm
543
+ readonly rules: ReadonlyArray<EncodedRule>
544
+ }
545
+ | {
546
+ readonly _tag: "All" | "Any" | "FirstOf"
547
+ readonly policies: ReadonlyArray<EncodedNode>
548
+ }
549
+ | {
550
+ readonly _tag: "Ceiling"
551
+ readonly cap: EncodedNode
552
+ readonly policy: EncodedNode
553
+ }
554
+
555
+ /**
556
+ * The Schema of the policies of a domain with no predicates. Decoding checks
557
+ * every kind, action, field and principal field against the domain, and the
558
+ * `meta` of each rule against the `meta` Schema of the domain.
559
+ *
560
+ * @stability stable
561
+ * @category schemas
562
+ * @since 0.3.0
563
+ */
564
+ export const schema: <D extends Domain.Any>(
565
+ domain: D,
566
+ ) => Schema.Codec<Policy<D>, EncodedNode> = internal.schema
567
+
568
+ /**
569
+ * Tests if a value is a policy.
570
+ *
571
+ * @stability stable
572
+ * @category guards
573
+ * @since 0.3.0
574
+ */
575
+ export const isPolicy: (u: unknown) => u is Any = internal.isPolicy
@@ -0,0 +1,41 @@
1
+ /**
2
+ * A principal is the one who asks to do an act. It may be a person, a user
3
+ * token, or a Bot.
4
+ *
5
+ * A principal is a Schema. Make it with {@link Class}, in the same way as
6
+ * `Schema.Class`, or use any `Schema.Struct`. Conditions can use the fields of
7
+ * the principal. See `Condition.Builder.principal`.
8
+ *
9
+ * @stability stable
10
+ * @since 0.3.0
11
+ */
12
+ import * as Schema from "effect/Schema"
13
+
14
+ /**
15
+ * Any Schema that can be a principal. Its type must be an object.
16
+ *
17
+ * @stability stable
18
+ * @category models
19
+ * @since 0.3.0
20
+ */
21
+ export type Any = Schema.Top & { readonly Type: object }
22
+
23
+ /**
24
+ * Makes a principal as a Schema class. It is the same as `Schema.Class`.
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * import { Schema } from "effect"
29
+ * import { Principal } from "@nmnmcc/ability"
30
+ *
31
+ * class Caller extends Principal.Class<Caller>("Caller")({
32
+ * userId: Schema.String,
33
+ * organizationId: Schema.String,
34
+ * }) {}
35
+ * ```
36
+ *
37
+ * @stability stable
38
+ * @category constructors
39
+ * @since 0.3.0
40
+ */
41
+ export const Class: typeof Schema.Class = Schema.Class