@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
@@ -0,0 +1,393 @@
1
+ import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Equal from "effect/Equal";
4
+ import * as Schema from "effect/Schema";
5
+ import * as Predicate from "effect/Predicate";
6
+ import { dual } from "effect/Function";
7
+ // src/internal/condition.ts
8
+ var condition_exports = /* @__PURE__ */ __exportAll({
9
+ Untranslatable: () => Untranslatable,
10
+ always: () => always,
11
+ and: () => and,
12
+ builder: () => builder,
13
+ evaluate: () => evaluate,
14
+ evaluateOf: () => evaluateOf,
15
+ evaluateSync: () => evaluateSync,
16
+ evaluateSyncOf: () => evaluateSyncOf,
17
+ fields: () => fields,
18
+ fold: () => fold,
19
+ getField: () => getField,
20
+ hasPredicate: () => hasPredicate,
21
+ never: () => never,
22
+ not: () => not,
23
+ or: () => or,
24
+ partial: () => partial,
25
+ partialOf: () => partialOf,
26
+ schema: () => schema,
27
+ simplify: () => simplify
28
+ });
29
+ /** @internal */
30
+ const always = Object.freeze({ _tag: "True" });
31
+ /** @internal */
32
+ const never = Object.freeze({ _tag: "False" });
33
+ const literal = (value) => Object.freeze({
34
+ _tag: "Literal",
35
+ value
36
+ });
37
+ const isOperand = (u) => Predicate.hasProperty(u, "_tag") && (u._tag === "Literal" || u._tag === "Principal");
38
+ const toOperand = (value) => isOperand(value) ? value : literal(value);
39
+ const compare = (op) => (field, value) => Object.freeze({
40
+ _tag: "Compare",
41
+ op,
42
+ field,
43
+ value: toOperand(value)
44
+ });
45
+ /** @internal */
46
+ const and = (...conditions) => Object.freeze({
47
+ _tag: "And",
48
+ conditions: Object.freeze([...conditions])
49
+ });
50
+ /** @internal */
51
+ const or = (...conditions) => Object.freeze({
52
+ _tag: "Or",
53
+ conditions: Object.freeze([...conditions])
54
+ });
55
+ /** @internal */
56
+ const not = (condition) => Object.freeze({
57
+ _tag: "Not",
58
+ condition
59
+ });
60
+ /** @internal */
61
+ const builder = () => Object.freeze({
62
+ eq: compare("eq"),
63
+ ne: compare("ne"),
64
+ lt: compare("lt"),
65
+ lte: compare("lte"),
66
+ gt: compare("gt"),
67
+ gte: compare("gte"),
68
+ in: (field, values) => Object.freeze({
69
+ _tag: "In",
70
+ field,
71
+ values: Object.freeze(values.map(toOperand))
72
+ }),
73
+ exists: (field) => Object.freeze({
74
+ _tag: "Exists",
75
+ field
76
+ }),
77
+ under: (...prefix) => Object.freeze({
78
+ _tag: "Under",
79
+ prefix: Object.freeze(prefix.map(toOperand))
80
+ }),
81
+ principal: (path) => Object.freeze({
82
+ _tag: "Principal",
83
+ path
84
+ }),
85
+ and,
86
+ or,
87
+ not,
88
+ predicate: (name, test) => Object.freeze({
89
+ _tag: "Predicate",
90
+ name,
91
+ run: (value, principal) => Effect.suspend(() => {
92
+ const result = test(value, principal);
93
+ return Effect.isEffect(result) ? result : Effect.succeed(result);
94
+ })
95
+ })
96
+ });
97
+ /**
98
+ * Gets a field of an object by a path with dots. A missing field, or a field
99
+ * under a value that is not an object, gives `null`.
100
+ *
101
+ * @internal
102
+ */
103
+ const getField = (value, path) => {
104
+ let cursor = value;
105
+ for (const key of path.split(".")) {
106
+ if (!Predicate.isObject(cursor) || !Object.hasOwn(cursor, key)) return null;
107
+ cursor = cursor[key];
108
+ }
109
+ return cursor === void 0 ? null : cursor;
110
+ };
111
+ /**
112
+ * Gives the value of an operand. A principal field that is `null` or missing
113
+ * gives `undefined`. No field of a resource is `undefined`, so a test with it
114
+ * is never true. This keeps the check closed: a principal with no id never
115
+ * matches a resource with no owner.
116
+ */
117
+ const resolve = (operand, principal) => operand._tag === "Literal" ? operand.value : getField(principal, operand.path) ?? void 0;
118
+ const testCompare = (op, left, right) => {
119
+ if (right === void 0) return false;
120
+ switch (op) {
121
+ case "eq": return left === right;
122
+ case "ne": return left !== right;
123
+ default: {
124
+ if (!(typeof left === "number" && typeof right === "number" || typeof left === "string" && typeof right === "string")) return false;
125
+ const a = left;
126
+ const b = right;
127
+ switch (op) {
128
+ case "lt": return a < b;
129
+ case "lte": return a <= b;
130
+ case "gt": return a > b;
131
+ case "gte": return a >= b;
132
+ }
133
+ }
134
+ }
135
+ };
136
+ /**
137
+ * Gives the values of a resource path. It gives `undefined` when the resource
138
+ * has no path.
139
+ */
140
+ const pathValues = (value, path) => path?.map((segment) => typeof segment === "string" ? segment : getField(value, segment.field));
141
+ const testUnder = (prefix, input) => {
142
+ const values = pathValues(input.value, input.path);
143
+ if (values === void 0 || prefix.length > values.length) return false;
144
+ return prefix.every((operand, index) => resolve(operand, input.principal) === values[index]);
145
+ };
146
+ /** @internal */
147
+ const hasPredicate = (ast) => {
148
+ switch (ast._tag) {
149
+ case "Predicate": return true;
150
+ case "And":
151
+ case "Or": return ast.conditions.some(hasPredicate);
152
+ case "Not": return hasPredicate(ast.condition);
153
+ default: return false;
154
+ }
155
+ };
156
+ /** @internal */
157
+ const evaluateSyncOf = (ast, input) => {
158
+ switch (ast._tag) {
159
+ case "True": return true;
160
+ case "False": return false;
161
+ case "Compare": return testCompare(ast.op, getField(input.value, ast.field), resolve(ast.value, input.principal));
162
+ case "In": {
163
+ const field = getField(input.value, ast.field);
164
+ return ast.values.some((operand) => resolve(operand, input.principal) === field);
165
+ }
166
+ case "Exists": return getField(input.value, ast.field) !== null;
167
+ case "Under": return testUnder(ast.prefix, input);
168
+ case "And": return ast.conditions.every((child) => evaluateSyncOf(child, input));
169
+ case "Or": return ast.conditions.some((child) => evaluateSyncOf(child, input));
170
+ case "Not": return !evaluateSyncOf(ast.condition, input);
171
+ case "Predicate": throw new Error(`The predicate "${ast.name}" needs an Effect. Use Condition.evaluate.`);
172
+ }
173
+ };
174
+ /** @internal */
175
+ const evaluateOf = (ast, input) => {
176
+ if (!hasPredicate(ast)) return Effect.sync(() => evaluateSyncOf(ast, input));
177
+ switch (ast._tag) {
178
+ case "Predicate": return ast.run(input.value, input.principal);
179
+ case "Not": return Effect.map(evaluateOf(ast.condition, input), (value) => !value);
180
+ case "And": return Effect.gen(function* () {
181
+ for (const child of ast.conditions) if (!(yield* evaluateOf(child, input))) return false;
182
+ return true;
183
+ });
184
+ case "Or": return Effect.gen(function* () {
185
+ for (const child of ast.conditions) if (yield* evaluateOf(child, input)) return true;
186
+ return false;
187
+ });
188
+ default: return Effect.sync(() => evaluateSyncOf(ast, input));
189
+ }
190
+ };
191
+ const dedupe = (conditions) => {
192
+ const output = [];
193
+ for (const condition of conditions) if (!output.some((other) => Equal.equals(other, condition))) output.push(condition);
194
+ return output;
195
+ };
196
+ /**
197
+ * Removes the children that the other children make useless. In an `Or`,
198
+ * `a OR (a AND b)` is `a`. In an `And`, `a AND (a OR b)` is `a`.
199
+ */
200
+ const absorb = (inner, conditions) => conditions.filter((condition) => condition._tag !== inner || !conditions.some((other) => other !== condition && condition.conditions.some((part) => Equal.equals(part, other))));
201
+ const flatten = (tag, conditions) => conditions.flatMap((child) => {
202
+ const simple = simplify(child);
203
+ return simple._tag === tag ? simple.conditions : [simple];
204
+ });
205
+ /** @internal */
206
+ const simplify = (ast) => {
207
+ switch (ast._tag) {
208
+ case "And": {
209
+ const children = flatten("And", ast.conditions).filter((child) => child._tag !== "True");
210
+ if (children.some((child) => child._tag === "False")) return never;
211
+ const unique = absorb("Or", dedupe(children));
212
+ if (unique.length === 0) return always;
213
+ return unique.length === 1 ? unique[0] : and(...unique);
214
+ }
215
+ case "Or": {
216
+ const children = flatten("Or", ast.conditions).filter((child) => child._tag !== "False");
217
+ if (children.some((child) => child._tag === "True")) return always;
218
+ const unique = absorb("And", dedupe(children));
219
+ if (unique.length === 0) return never;
220
+ return unique.length === 1 ? unique[0] : or(...unique);
221
+ }
222
+ case "Not": {
223
+ const child = simplify(ast.condition);
224
+ switch (child._tag) {
225
+ case "True": return never;
226
+ case "False": return always;
227
+ case "Not": return child.condition;
228
+ case "Compare":
229
+ if (child.value._tag === "Literal" && (child.op === "eq" || child.op === "ne")) return Object.freeze({
230
+ ...child,
231
+ op: child.op === "eq" ? "ne" : "eq"
232
+ });
233
+ return not(child);
234
+ default: return not(child);
235
+ }
236
+ }
237
+ case "In": return ast.values.length === 0 ? never : ast;
238
+ default: return ast;
239
+ }
240
+ };
241
+ /**
242
+ * Puts the value of the principal into an operand. It gives `undefined` for a
243
+ * principal field with no value. See {@link resolve}.
244
+ */
245
+ const bindOperand = (operand, principal) => {
246
+ if (operand._tag === "Literal") return operand;
247
+ const value = resolve(operand, principal);
248
+ return value === void 0 ? void 0 : literal(value);
249
+ };
250
+ const expandUnder = (prefix, principal, path) => {
251
+ if (path === void 0 || prefix.length > path.length) return never;
252
+ const parts = [];
253
+ prefix.forEach((operand, index) => {
254
+ const value = resolve(operand, principal);
255
+ const segment = path[index];
256
+ if (value === void 0) parts.push(never);
257
+ else if (typeof segment === "string") parts.push(segment === value ? always : never);
258
+ else parts.push(Object.freeze({
259
+ _tag: "Compare",
260
+ op: "eq",
261
+ field: segment.field,
262
+ value: literal(value)
263
+ }));
264
+ });
265
+ return and(...parts);
266
+ };
267
+ const bind = (ast, principal, path) => {
268
+ switch (ast._tag) {
269
+ case "Compare": {
270
+ const value = bindOperand(ast.value, principal);
271
+ return value === void 0 ? never : Object.freeze({
272
+ ...ast,
273
+ value
274
+ });
275
+ }
276
+ case "In": return Object.freeze({
277
+ ...ast,
278
+ values: Object.freeze(ast.values.flatMap((operand) => {
279
+ const value = bindOperand(operand, principal);
280
+ return value === void 0 ? [] : [value];
281
+ }))
282
+ });
283
+ case "Under": return expandUnder(ast.prefix, principal, path);
284
+ case "And": return and(...ast.conditions.map((child) => bind(child, principal, path)));
285
+ case "Or": return or(...ast.conditions.map((child) => bind(child, principal, path)));
286
+ case "Not": return not(bind(ast.condition, principal, path));
287
+ case "Predicate": return Object.freeze({
288
+ _tag: "Predicate",
289
+ name: ast.name,
290
+ run: (value) => ast.run(value, principal)
291
+ });
292
+ default: return ast;
293
+ }
294
+ };
295
+ /** @internal */
296
+ const partialOf = (ast, input) => simplify(bind(ast, input.principal, input.path));
297
+ /** @internal */
298
+ const evaluate = dual(2, evaluateOf);
299
+ /** @internal */
300
+ const evaluateSync = dual(2, evaluateSyncOf);
301
+ /** @internal */
302
+ const partial = dual(2, partialOf);
303
+ /** @internal */
304
+ var Untranslatable = class extends Schema.TaggedError("@nmnmcc/ability/Condition/Untranslatable")("Untranslatable", { reason: Schema.String }) {};
305
+ const foldNode = (ast, interpreter) => {
306
+ switch (ast._tag) {
307
+ case "True": return interpreter.true();
308
+ case "False": return interpreter.false();
309
+ case "Compare":
310
+ if (ast.value._tag !== "Literal") throw Untranslatable.make({ reason: `The field "${ast.field}" is compared with a principal field. Call Condition.partial first.` });
311
+ return interpreter.compare(ast.op, ast.field, ast.value.value);
312
+ case "In": return interpreter.in(ast.field, ast.values.map((operand) => {
313
+ if (operand._tag !== "Literal") throw Untranslatable.make({ reason: `The field "${ast.field}" uses a principal field. Call Condition.partial first.` });
314
+ return operand.value;
315
+ }));
316
+ case "Exists": return interpreter.exists(ast.field);
317
+ case "Under": throw Untranslatable.make({ reason: "An Under node needs the resource path. Call Condition.partial first." });
318
+ case "And": return interpreter.and(ast.conditions.map((child) => foldNode(child, interpreter)));
319
+ case "Or": return interpreter.or(ast.conditions.map((child) => foldNode(child, interpreter)));
320
+ case "Not": return interpreter.not(foldNode(ast.condition, interpreter));
321
+ case "Predicate":
322
+ if (interpreter.predicate === void 0) throw Untranslatable.make({ reason: `The predicate "${ast.name}" can not become a query` });
323
+ return interpreter.predicate(ast.name);
324
+ }
325
+ };
326
+ /** @internal */
327
+ const fold = dual(2, (ast, interpreter) => Effect.try({
328
+ try: () => foldNode(ast, interpreter),
329
+ catch: (cause) => {
330
+ if (cause instanceof Untranslatable) return cause;
331
+ throw cause;
332
+ }
333
+ }));
334
+ /** @internal */
335
+ const fields = (ast) => {
336
+ const output = /* @__PURE__ */ new Set();
337
+ const visit = (node) => {
338
+ switch (node._tag) {
339
+ case "Compare":
340
+ case "In":
341
+ case "Exists":
342
+ output.add(node.field);
343
+ return;
344
+ case "And":
345
+ case "Or":
346
+ node.conditions.forEach(visit);
347
+ return;
348
+ case "Not":
349
+ visit(node.condition);
350
+ return;
351
+ default: return;
352
+ }
353
+ };
354
+ visit(ast);
355
+ return Object.freeze(Array.from(output));
356
+ };
357
+ const ScalarSchema = Schema.Union([
358
+ Schema.String,
359
+ Schema.Finite,
360
+ Schema.Boolean,
361
+ Schema.Null
362
+ ]);
363
+ const OperandSchema = Schema.Union([Schema.TaggedStruct("Literal", { value: ScalarSchema }), Schema.TaggedStruct("Principal", { path: Schema.String })]);
364
+ const Recursive = Schema.suspend(() => schema);
365
+ /** @internal */
366
+ const schema = Schema.Union([
367
+ Schema.TaggedStruct("True", {}),
368
+ Schema.TaggedStruct("False", {}),
369
+ Schema.TaggedStruct("Compare", {
370
+ op: Schema.Literals([
371
+ "eq",
372
+ "ne",
373
+ "lt",
374
+ "lte",
375
+ "gt",
376
+ "gte"
377
+ ]),
378
+ field: Schema.String,
379
+ value: OperandSchema
380
+ }),
381
+ Schema.TaggedStruct("In", {
382
+ field: Schema.String,
383
+ values: Schema.Array(OperandSchema)
384
+ }),
385
+ Schema.TaggedStruct("Exists", { field: Schema.String }),
386
+ Schema.TaggedStruct("Under", { prefix: Schema.Array(OperandSchema) }),
387
+ Schema.TaggedStruct("And", { conditions: Schema.Array(Recursive) }),
388
+ Schema.TaggedStruct("Or", { conditions: Schema.Array(Recursive) }),
389
+ Schema.TaggedStruct("Not", { condition: Recursive })
390
+ ]);
391
+ export { Untranslatable, always, and, builder, condition_exports, evaluate, evaluateOf, evaluateSync, evaluateSyncOf, fields, fold, getField, hasPredicate, never, not, or, partial, partialOf, schema, simplify };
392
+
393
+ //# sourceMappingURL=condition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"condition.js","names":[],"sources":["../../src/internal/condition.ts"],"sourcesContent":["// A predicate keeps its error type and service type only in the public types.\n// Inside this file they are erased to `unknown`, so the language service check\n// for `unknown` in an Effect is off here.\n// @effect-diagnostics anyUnknownInErrorContext:off\nimport * as Effect from \"effect/Effect\"\nimport * as Equal from \"effect/Equal\"\nimport { dual } from \"effect/Function\"\nimport * as Predicate from \"effect/Predicate\"\nimport * as Schema from \"effect/Schema\"\nimport type * as Condition from \"../Condition.ts\"\nimport type * as Resource from \"../Resource.ts\"\n\ntype Ast = Condition.Ast\ntype Scalar = Condition.Scalar\n\n/** @internal */\nexport const always: Condition.True = Object.freeze({ _tag: \"True\" })\n\n/** @internal */\nexport const never: Condition.False = Object.freeze({ _tag: \"False\" })\n\nconst literal = (value: Scalar): Condition.Literal =>\n\tObject.freeze({ _tag: \"Literal\", value })\n\nconst isOperand = (u: unknown): u is Condition.Operand =>\n\tPredicate.hasProperty(u, \"_tag\") &&\n\t(u._tag === \"Literal\" || u._tag === \"Principal\")\n\nconst toOperand = (value: unknown): Condition.Operand =>\n\tisOperand(value) ? value : literal(value as Scalar)\n\nconst compare =\n\t(op: Condition.CompareOperator) =>\n\t(field: string, value: unknown): Condition.Compare =>\n\t\tObject.freeze({ _tag: \"Compare\", op, field, value: toOperand(value) })\n\n/** @internal */\nexport const and = (...conditions: ReadonlyArray<Ast>): Condition.And =>\n\tObject.freeze({ _tag: \"And\", conditions: Object.freeze([...conditions]) })\n\n/** @internal */\nexport const or = (...conditions: ReadonlyArray<Ast>): Condition.Or =>\n\tObject.freeze({ _tag: \"Or\", conditions: Object.freeze([...conditions]) })\n\n/** @internal */\nexport const not = (condition: Ast): Condition.Not =>\n\tObject.freeze({ _tag: \"Not\", condition })\n\n/** @internal */\nexport const builder = (): any =>\n\tObject.freeze({\n\t\teq: compare(\"eq\"),\n\t\tne: compare(\"ne\"),\n\t\tlt: compare(\"lt\"),\n\t\tlte: compare(\"lte\"),\n\t\tgt: compare(\"gt\"),\n\t\tgte: compare(\"gte\"),\n\t\tin: (field: string, values: ReadonlyArray<unknown>): Condition.In =>\n\t\t\tObject.freeze({\n\t\t\t\t_tag: \"In\",\n\t\t\t\tfield,\n\t\t\t\tvalues: Object.freeze(values.map(toOperand)),\n\t\t\t}),\n\t\texists: (field: string): Condition.Exists =>\n\t\t\tObject.freeze({ _tag: \"Exists\", field }),\n\t\tunder: (...prefix: ReadonlyArray<unknown>): Condition.Under =>\n\t\t\tObject.freeze({\n\t\t\t\t_tag: \"Under\",\n\t\t\t\tprefix: Object.freeze(prefix.map(toOperand)),\n\t\t\t}),\n\t\tprincipal: (path: string): Condition.PrincipalRef =>\n\t\t\tObject.freeze({ _tag: \"Principal\", path }),\n\t\tand,\n\t\tor,\n\t\tnot,\n\t\tpredicate: (\n\t\t\tname: string,\n\t\t\ttest: (\n\t\t\t\tvalue: unknown,\n\t\t\t\tprincipal: unknown,\n\t\t\t) => boolean | Effect.Effect<boolean, unknown, unknown>,\n\t\t): Condition.Predicate =>\n\t\t\tObject.freeze({\n\t\t\t\t_tag: \"Predicate\",\n\t\t\t\tname,\n\t\t\t\trun: (value: unknown, principal: unknown) =>\n\t\t\t\t\tEffect.suspend(() => {\n\t\t\t\t\t\tconst result = test(value, principal)\n\t\t\t\t\t\treturn Effect.isEffect(result) ? result : Effect.succeed(result)\n\t\t\t\t\t}),\n\t\t\t}),\n\t})\n\n/**\n * Gets a field of an object by a path with dots. A missing field, or a field\n * under a value that is not an object, gives `null`.\n *\n * @internal\n */\nexport const getField = (value: unknown, path: string): unknown => {\n\tlet cursor: unknown = value\n\tfor (const key of path.split(\".\")) {\n\t\tif (!Predicate.isObject(cursor) || !Object.hasOwn(cursor, key)) {\n\t\t\treturn null\n\t\t}\n\t\tcursor = (cursor as Record<string, unknown>)[key]\n\t}\n\treturn cursor === undefined ? null : cursor\n}\n\n/**\n * Gives the value of an operand. A principal field that is `null` or missing\n * gives `undefined`. No field of a resource is `undefined`, so a test with it\n * is never true. This keeps the check closed: a principal with no id never\n * matches a resource with no owner.\n */\nconst resolve = (operand: Condition.Operand, principal: unknown): unknown =>\n\toperand._tag === \"Literal\"\n\t\t? operand.value\n\t\t: (getField(principal, operand.path) ?? undefined)\n\nconst testCompare = (\n\top: Condition.CompareOperator,\n\tleft: unknown,\n\tright: unknown,\n): boolean => {\n\tif (right === undefined) {\n\t\treturn false\n\t}\n\tswitch (op) {\n\t\tcase \"eq\":\n\t\t\treturn left === right\n\t\tcase \"ne\":\n\t\t\treturn left !== right\n\t\tdefault: {\n\t\t\tconst ordered =\n\t\t\t\t(typeof left === \"number\" && typeof right === \"number\") ||\n\t\t\t\t(typeof left === \"string\" && typeof right === \"string\")\n\t\t\tif (!ordered) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tconst a = left as number | string\n\t\t\tconst b = right as number | string\n\t\t\tswitch (op) {\n\t\t\t\tcase \"lt\":\n\t\t\t\t\treturn a < b\n\t\t\t\tcase \"lte\":\n\t\t\t\t\treturn a <= b\n\t\t\t\tcase \"gt\":\n\t\t\t\t\treturn a > b\n\t\t\t\tcase \"gte\":\n\t\t\t\t\treturn a >= b\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Gives the values of a resource path. It gives `undefined` when the resource\n * has no path.\n */\nconst pathValues = (\n\tvalue: unknown,\n\tpath: ReadonlyArray<Resource.PathSegment> | undefined,\n): ReadonlyArray<unknown> | undefined =>\n\tpath?.map((segment) =>\n\t\ttypeof segment === \"string\" ? segment : getField(value, segment.field),\n\t)\n\nconst testUnder = (\n\tprefix: ReadonlyArray<Condition.Operand>,\n\tinput: Condition.Input,\n): boolean => {\n\tconst values = pathValues(input.value, input.path)\n\tif (values === undefined || prefix.length > values.length) {\n\t\treturn false\n\t}\n\treturn prefix.every(\n\t\t(operand, index) => resolve(operand, input.principal) === values[index],\n\t)\n}\n\n/** @internal */\nexport const hasPredicate = (ast: Ast): boolean => {\n\tswitch (ast._tag) {\n\t\tcase \"Predicate\":\n\t\t\treturn true\n\t\tcase \"And\":\n\t\tcase \"Or\":\n\t\t\treturn ast.conditions.some(hasPredicate)\n\t\tcase \"Not\":\n\t\t\treturn hasPredicate(ast.condition)\n\t\tdefault:\n\t\t\treturn false\n\t}\n}\n\n/** @internal */\nexport const evaluateSyncOf = (ast: Ast, input: Condition.Input): boolean => {\n\tswitch (ast._tag) {\n\t\tcase \"True\":\n\t\t\treturn true\n\t\tcase \"False\":\n\t\t\treturn false\n\t\tcase \"Compare\":\n\t\t\treturn testCompare(\n\t\t\t\tast.op,\n\t\t\t\tgetField(input.value, ast.field),\n\t\t\t\tresolve(ast.value, input.principal),\n\t\t\t)\n\t\tcase \"In\": {\n\t\t\tconst field = getField(input.value, ast.field)\n\t\t\treturn ast.values.some(\n\t\t\t\t(operand) => resolve(operand, input.principal) === field,\n\t\t\t)\n\t\t}\n\t\tcase \"Exists\":\n\t\t\treturn getField(input.value, ast.field) !== null\n\t\tcase \"Under\":\n\t\t\treturn testUnder(ast.prefix, input)\n\t\tcase \"And\":\n\t\t\treturn ast.conditions.every((child) => evaluateSyncOf(child, input))\n\t\tcase \"Or\":\n\t\t\treturn ast.conditions.some((child) => evaluateSyncOf(child, input))\n\t\tcase \"Not\":\n\t\t\treturn !evaluateSyncOf(ast.condition, input)\n\t\tcase \"Predicate\":\n\t\t\t// The types stop this. A predicate needs `evaluate`.\n\t\t\tthrow new Error(\n\t\t\t\t`The predicate \"${ast.name}\" needs an Effect. Use Condition.evaluate.`,\n\t\t\t)\n\t}\n}\n\n/** @internal */\nexport const evaluateOf = (\n\tast: Ast,\n\tinput: Condition.Input,\n): Effect.Effect<boolean, unknown, unknown> => {\n\tif (!hasPredicate(ast)) {\n\t\treturn Effect.sync(() => evaluateSyncOf(ast, input))\n\t}\n\tswitch (ast._tag) {\n\t\tcase \"Predicate\":\n\t\t\treturn ast.run(input.value, input.principal)\n\t\tcase \"Not\":\n\t\t\treturn Effect.map(evaluateOf(ast.condition, input), (value) => !value)\n\t\tcase \"And\":\n\t\t\treturn Effect.gen(function* () {\n\t\t\t\tfor (const child of ast.conditions) {\n\t\t\t\t\tif (!(yield* evaluateOf(child, input))) {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t})\n\t\tcase \"Or\":\n\t\t\treturn Effect.gen(function* () {\n\t\t\t\tfor (const child of ast.conditions) {\n\t\t\t\t\tif (yield* evaluateOf(child, input)) {\n\t\t\t\t\t\treturn true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false\n\t\t\t})\n\t\tdefault:\n\t\t\treturn Effect.sync(() => evaluateSyncOf(ast, input))\n\t}\n}\n\nconst dedupe = (conditions: ReadonlyArray<Ast>): ReadonlyArray<Ast> => {\n\tconst output: Array<Ast> = []\n\tfor (const condition of conditions) {\n\t\tif (!output.some((other) => Equal.equals(other, condition))) {\n\t\t\toutput.push(condition)\n\t\t}\n\t}\n\treturn output\n}\n\n/**\n * Removes the children that the other children make useless. In an `Or`,\n * `a OR (a AND b)` is `a`. In an `And`, `a AND (a OR b)` is `a`.\n */\nconst absorb = (\n\tinner: \"And\" | \"Or\",\n\tconditions: ReadonlyArray<Ast>,\n): ReadonlyArray<Ast> =>\n\tconditions.filter(\n\t\t(condition) =>\n\t\t\tcondition._tag !== inner ||\n\t\t\t!conditions.some(\n\t\t\t\t(other) =>\n\t\t\t\t\tother !== condition &&\n\t\t\t\t\tcondition.conditions.some((part) => Equal.equals(part, other)),\n\t\t\t),\n\t)\n\nconst flatten = (\n\ttag: \"And\" | \"Or\",\n\tconditions: ReadonlyArray<Ast>,\n): ReadonlyArray<Ast> =>\n\tconditions.flatMap((child) => {\n\t\tconst simple = simplify(child)\n\t\treturn simple._tag === tag ? simple.conditions : [simple]\n\t})\n\n/** @internal */\nexport const simplify = (ast: Ast): Ast => {\n\tswitch (ast._tag) {\n\t\tcase \"And\": {\n\t\t\tconst children = flatten(\"And\", ast.conditions).filter(\n\t\t\t\t(child) => child._tag !== \"True\",\n\t\t\t)\n\t\t\tif (children.some((child) => child._tag === \"False\")) {\n\t\t\t\treturn never\n\t\t\t}\n\t\t\tconst unique = absorb(\"Or\", dedupe(children))\n\t\t\tif (unique.length === 0) {\n\t\t\t\treturn always\n\t\t\t}\n\t\t\treturn unique.length === 1 ? unique[0]! : and(...unique)\n\t\t}\n\t\tcase \"Or\": {\n\t\t\tconst children = flatten(\"Or\", ast.conditions).filter(\n\t\t\t\t(child) => child._tag !== \"False\",\n\t\t\t)\n\t\t\tif (children.some((child) => child._tag === \"True\")) {\n\t\t\t\treturn always\n\t\t\t}\n\t\t\tconst unique = absorb(\"And\", dedupe(children))\n\t\t\tif (unique.length === 0) {\n\t\t\t\treturn never\n\t\t\t}\n\t\t\treturn unique.length === 1 ? unique[0]! : or(...unique)\n\t\t}\n\t\tcase \"Not\": {\n\t\t\tconst child = simplify(ast.condition)\n\t\t\tswitch (child._tag) {\n\t\t\t\tcase \"True\":\n\t\t\t\t\treturn never\n\t\t\t\tcase \"False\":\n\t\t\t\t\treturn always\n\t\t\t\tcase \"Not\":\n\t\t\t\t\treturn child.condition\n\t\t\t\tcase \"Compare\":\n\t\t\t\t\t// A principal field with no value makes `eq` and `ne` both false,\n\t\t\t\t\t// so only a fixed value lets `not eq` become `ne`.\n\t\t\t\t\tif (\n\t\t\t\t\t\tchild.value._tag === \"Literal\" &&\n\t\t\t\t\t\t(child.op === \"eq\" || child.op === \"ne\")\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn Object.freeze({\n\t\t\t\t\t\t\t...child,\n\t\t\t\t\t\t\top: child.op === \"eq\" ? \"ne\" : \"eq\",\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t\treturn not(child)\n\t\t\t\tdefault:\n\t\t\t\t\treturn not(child)\n\t\t\t}\n\t\t}\n\t\tcase \"In\":\n\t\t\treturn ast.values.length === 0 ? never : ast\n\t\tdefault:\n\t\t\treturn ast\n\t}\n}\n\n/**\n * Puts the value of the principal into an operand. It gives `undefined` for a\n * principal field with no value. See {@link resolve}.\n */\nconst bindOperand = (\n\toperand: Condition.Operand,\n\tprincipal: unknown,\n): Condition.Literal | undefined => {\n\tif (operand._tag === \"Literal\") {\n\t\treturn operand\n\t}\n\tconst value = resolve(operand, principal)\n\treturn value === undefined ? undefined : literal(value as Scalar)\n}\n\nconst expandUnder = (\n\tprefix: ReadonlyArray<Condition.Operand>,\n\tprincipal: unknown,\n\tpath: ReadonlyArray<Resource.PathSegment> | undefined,\n): Ast => {\n\tif (path === undefined || prefix.length > path.length) {\n\t\treturn never\n\t}\n\tconst parts: Array<Ast> = []\n\tprefix.forEach((operand, index) => {\n\t\tconst value = resolve(operand, principal)\n\t\tconst segment = path[index]!\n\t\tif (value === undefined) {\n\t\t\tparts.push(never)\n\t\t} else if (typeof segment === \"string\") {\n\t\t\tparts.push(segment === value ? always : never)\n\t\t} else {\n\t\t\tparts.push(\n\t\t\t\tObject.freeze({\n\t\t\t\t\t_tag: \"Compare\",\n\t\t\t\t\top: \"eq\",\n\t\t\t\t\tfield: segment.field,\n\t\t\t\t\tvalue: literal(value as Scalar),\n\t\t\t\t}),\n\t\t\t)\n\t\t}\n\t})\n\treturn and(...parts)\n}\n\nconst bind = (\n\tast: Ast,\n\tprincipal: unknown,\n\tpath: ReadonlyArray<Resource.PathSegment> | undefined,\n): Ast => {\n\tswitch (ast._tag) {\n\t\tcase \"Compare\": {\n\t\t\tconst value = bindOperand(ast.value, principal)\n\t\t\treturn value === undefined ? never : Object.freeze({ ...ast, value })\n\t\t}\n\t\tcase \"In\":\n\t\t\treturn Object.freeze({\n\t\t\t\t...ast,\n\t\t\t\tvalues: Object.freeze(\n\t\t\t\t\tast.values.flatMap((operand) => {\n\t\t\t\t\t\tconst value = bindOperand(operand, principal)\n\t\t\t\t\t\treturn value === undefined ? [] : [value]\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t})\n\t\tcase \"Under\":\n\t\t\treturn expandUnder(ast.prefix, principal, path)\n\t\tcase \"And\":\n\t\t\treturn and(...ast.conditions.map((child) => bind(child, principal, path)))\n\t\tcase \"Or\":\n\t\t\treturn or(...ast.conditions.map((child) => bind(child, principal, path)))\n\t\tcase \"Not\":\n\t\t\treturn not(bind(ast.condition, principal, path))\n\t\tcase \"Predicate\":\n\t\t\treturn Object.freeze({\n\t\t\t\t_tag: \"Predicate\",\n\t\t\t\tname: ast.name,\n\t\t\t\trun: (value: unknown) => ast.run(value, principal),\n\t\t\t})\n\t\tdefault:\n\t\t\treturn ast\n\t}\n}\n\n/** @internal */\nexport const partialOf = (\n\tast: Ast,\n\tinput: {\n\t\treadonly principal?: object | undefined\n\t\treadonly path?: ReadonlyArray<Resource.PathSegment> | undefined\n\t},\n): Ast => simplify(bind(ast, input.principal, input.path))\n\n/** @internal */\nexport const evaluate = dual(2, evaluateOf)\n\n/** @internal */\nexport const evaluateSync = dual(2, evaluateSyncOf)\n\n/** @internal */\nexport const partial = dual(2, partialOf)\n\n/** @internal */\nexport class Untranslatable extends Schema.TaggedError<Untranslatable>(\n\t\"@nmnmcc/ability/Condition/Untranslatable\",\n)(\"Untranslatable\", { reason: Schema.String }) {}\n\nconst foldNode = <A>(ast: Ast, interpreter: Condition.Interpreter<A>): A => {\n\tswitch (ast._tag) {\n\t\tcase \"True\":\n\t\t\treturn interpreter.true()\n\t\tcase \"False\":\n\t\t\treturn interpreter.false()\n\t\tcase \"Compare\":\n\t\t\tif (ast.value._tag !== \"Literal\") {\n\t\t\t\tthrow Untranslatable.make({\n\t\t\t\t\treason: `The field \"${ast.field}\" is compared with a principal field. Call Condition.partial first.`,\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn interpreter.compare(ast.op, ast.field, ast.value.value)\n\t\tcase \"In\":\n\t\t\treturn interpreter.in(\n\t\t\t\tast.field,\n\t\t\t\tast.values.map((operand) => {\n\t\t\t\t\tif (operand._tag !== \"Literal\") {\n\t\t\t\t\t\tthrow Untranslatable.make({\n\t\t\t\t\t\t\treason: `The field \"${ast.field}\" uses a principal field. Call Condition.partial first.`,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t\treturn operand.value\n\t\t\t\t}),\n\t\t\t)\n\t\tcase \"Exists\":\n\t\t\treturn interpreter.exists(ast.field)\n\t\tcase \"Under\":\n\t\t\tthrow Untranslatable.make({\n\t\t\t\treason:\n\t\t\t\t\t\"An Under node needs the resource path. Call Condition.partial first.\",\n\t\t\t})\n\t\tcase \"And\":\n\t\t\treturn interpreter.and(\n\t\t\t\tast.conditions.map((child) => foldNode(child, interpreter)),\n\t\t\t)\n\t\tcase \"Or\":\n\t\t\treturn interpreter.or(\n\t\t\t\tast.conditions.map((child) => foldNode(child, interpreter)),\n\t\t\t)\n\t\tcase \"Not\":\n\t\t\treturn interpreter.not(foldNode(ast.condition, interpreter))\n\t\tcase \"Predicate\":\n\t\t\tif (interpreter.predicate === undefined) {\n\t\t\t\tthrow Untranslatable.make({\n\t\t\t\t\treason: `The predicate \"${ast.name}\" can not become a query`,\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn interpreter.predicate(ast.name)\n\t}\n}\n\n/** @internal */\nexport const fold = dual(\n\t2,\n\t<A>(\n\t\tast: Ast,\n\t\tinterpreter: Condition.Interpreter<A>,\n\t): Effect.Effect<A, Untranslatable> =>\n\t\tEffect.try({\n\t\t\ttry: () => foldNode(ast, interpreter),\n\t\t\tcatch: (cause) => {\n\t\t\t\tif (cause instanceof Untranslatable) {\n\t\t\t\t\treturn cause\n\t\t\t\t}\n\t\t\t\tthrow cause\n\t\t\t},\n\t\t}),\n)\n\n/** @internal */\nexport const fields = (ast: Ast): ReadonlyArray<string> => {\n\tconst output = new Set<string>()\n\tconst visit = (node: Ast): void => {\n\t\tswitch (node._tag) {\n\t\t\tcase \"Compare\":\n\t\t\tcase \"In\":\n\t\t\tcase \"Exists\":\n\t\t\t\toutput.add(node.field)\n\t\t\t\treturn\n\t\t\tcase \"And\":\n\t\t\tcase \"Or\":\n\t\t\t\tnode.conditions.forEach(visit)\n\t\t\t\treturn\n\t\t\tcase \"Not\":\n\t\t\t\tvisit(node.condition)\n\t\t\t\treturn\n\t\t\tdefault:\n\t\t\t\treturn\n\t\t}\n\t}\n\tvisit(ast)\n\treturn Object.freeze(Array.from(output))\n}\n\nconst ScalarSchema = Schema.Union([\n\tSchema.String,\n\tSchema.Finite,\n\tSchema.Boolean,\n\tSchema.Null,\n])\n\nconst OperandSchema = Schema.Union([\n\tSchema.TaggedStruct(\"Literal\", { value: ScalarSchema }),\n\tSchema.TaggedStruct(\"Principal\", { path: Schema.String }),\n])\n\nconst Recursive = Schema.suspend(\n\t(): Schema.Codec<Condition.Condition, Condition.Encoded> => schema,\n)\n\n/** @internal */\nexport const schema: Schema.Codec<Condition.Condition, Condition.Encoded> =\n\tSchema.Union([\n\t\tSchema.TaggedStruct(\"True\", {}),\n\t\tSchema.TaggedStruct(\"False\", {}),\n\t\tSchema.TaggedStruct(\"Compare\", {\n\t\t\top: Schema.Literals([\"eq\", \"ne\", \"lt\", \"lte\", \"gt\", \"gte\"]),\n\t\t\tfield: Schema.String,\n\t\t\tvalue: OperandSchema,\n\t\t}),\n\t\tSchema.TaggedStruct(\"In\", {\n\t\t\tfield: Schema.String,\n\t\t\tvalues: Schema.Array(OperandSchema),\n\t\t}),\n\t\tSchema.TaggedStruct(\"Exists\", { field: Schema.String }),\n\t\tSchema.TaggedStruct(\"Under\", { prefix: Schema.Array(OperandSchema) }),\n\t\tSchema.TaggedStruct(\"And\", { conditions: Schema.Array(Recursive) }),\n\t\tSchema.TaggedStruct(\"Or\", { conditions: Schema.Array(Recursive) }),\n\t\tSchema.TaggedStruct(\"Not\", { condition: Recursive }),\n\t]) as never\n"],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import { descriptor } from "./resource.js";
2
+ import * as Predicate from "effect/Predicate";
3
+ // src/internal/domain.ts
4
+ /** @internal */
5
+ const TypeId = "~@nmnmcc/ability/Domain";
6
+ /** @internal */
7
+ const make = (options) => {
8
+ const resources = /* @__PURE__ */ new Map();
9
+ for (const resource of options.resources) {
10
+ const value = descriptor(resource);
11
+ if (resources.has(value.kind)) throw new Error(`Two resources have the kind name "${value.kind}"`);
12
+ if (value.kind === "*") throw new Error(`A resource may not have the kind name "*"`);
13
+ resources.set(value.kind, value);
14
+ }
15
+ return Object.freeze({
16
+ [TypeId]: TypeId,
17
+ principal: options.principal,
18
+ resources,
19
+ meta: options.meta
20
+ });
21
+ };
22
+ /** @internal */
23
+ const isDomain = (u) => Predicate.hasProperty(u, TypeId);
24
+ /** @internal */
25
+ const getDescriptor = (domain, kind) => domain.resources.get(kind);
26
+ /**
27
+ * Gives the kind name of a resource value, from its `_tag` field.
28
+ *
29
+ * @internal
30
+ */
31
+ const kindOf = (value) => Predicate.hasProperty(value, "_tag") && typeof value._tag === "string" ? value._tag : void 0;
32
+ export { TypeId, getDescriptor, isDomain, kindOf, make };
33
+
34
+ //# sourceMappingURL=domain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain.js","names":[],"sources":["../../src/internal/domain.ts"],"sourcesContent":["import * as Predicate from \"effect/Predicate\"\nimport type * as Schema from \"effect/Schema\"\nimport type * as Domain from \"../Domain.ts\"\nimport type * as Principal from \"../Principal.ts\"\nimport type * as Resource from \"../Resource.ts\"\nimport { descriptor } from \"./resource.ts\"\n\n/** @internal */\nexport const TypeId = \"~@nmnmcc/ability/Domain\" as const\n\n/** @internal */\nexport const make = (options: {\n\treadonly principal: Principal.Any\n\treadonly resources: ReadonlyArray<Resource.Any>\n\treadonly meta?: Schema.Top\n}): any => {\n\tconst resources = new Map<string, Resource.Descriptor>()\n\tfor (const resource of options.resources) {\n\t\tconst value = descriptor(resource)\n\t\tif (resources.has(value.kind)) {\n\t\t\t// Two resources with one kind name is a mistake in the code, not in the\n\t\t\t// data, so it is a defect.\n\t\t\tthrow new Error(`Two resources have the kind name \"${value.kind}\"`)\n\t\t}\n\t\tif (value.kind === \"*\") {\n\t\t\tthrow new Error(`A resource may not have the kind name \"*\"`)\n\t\t}\n\t\tresources.set(value.kind, value)\n\t}\n\treturn Object.freeze({\n\t\t[TypeId]: TypeId,\n\t\tprincipal: options.principal,\n\t\tresources,\n\t\tmeta: options.meta,\n\t})\n}\n\n/** @internal */\nexport const isDomain = (u: unknown): u is Domain.Any =>\n\tPredicate.hasProperty(u, TypeId)\n\n/** @internal */\nexport const getDescriptor = (\n\tdomain: Domain.Any,\n\tkind: string,\n): Resource.Descriptor | undefined => domain.resources.get(kind)\n\n/**\n * Gives the kind name of a resource value, from its `_tag` field.\n *\n * @internal\n */\nexport const kindOf = (value: unknown): string | undefined =>\n\tPredicate.hasProperty(value, \"_tag\") && typeof value._tag === \"string\"\n\t\t? value._tag\n\t\t: undefined\n"],"mappings":";;;;AAQA,MAAa,SAAS;;AAGtB,MAAa,QAAQ,YAIV;CACV,MAAM,4BAAY,IAAI,IAAiC;CACvD,KAAK,MAAM,YAAY,QAAQ,WAAW;EACzC,MAAM,QAAQ,WAAW,QAAQ;EACjC,IAAI,UAAU,IAAI,MAAM,IAAI,GAG3B,MAAM,IAAI,MAAM,qCAAqC,MAAM,KAAK,EAAE;EAEnE,IAAI,MAAM,SAAS,KAClB,MAAM,IAAI,MAAM,2CAA2C;EAE5D,UAAU,IAAI,MAAM,MAAM,KAAK;CAChC;CACA,OAAO,OAAO,OAAO;GACnB,SAAS;EACV,WAAW,QAAQ;EACnB;EACA,MAAM,QAAQ;CACf,CAAC;AACF;;AAGA,MAAa,YAAY,MACxB,UAAU,YAAY,GAAG,MAAM;;AAGhC,MAAa,iBACZ,QACA,SACqC,OAAO,UAAU,IAAI,IAAI;;;;;;AAO/D,MAAa,UAAU,UACtB,UAAU,YAAY,OAAO,MAAM,KAAK,OAAO,MAAM,SAAS,WAC3D,MAAM,OACN,KAAA"}
@@ -0,0 +1,41 @@
1
+ import { GroupRequired, Required } from "../HttpApi.js";
2
+ import * as Context from "effect/Context";
3
+ import * as Effect from "effect/Effect";
4
+ import * as Layer from "effect/Layer";
5
+ import * as Option from "effect/Option";
6
+ import { HttpRouter } from "effect/http";
7
+ // src/internal/httpApi.ts
8
+ /** @internal */
9
+ const requires = (_authorizer, action, kind, load) => Object.freeze(load === void 0 ? {
10
+ action,
11
+ kind
12
+ } : {
13
+ action,
14
+ kind,
15
+ load
16
+ });
17
+ /** @internal */
18
+ const layer = (middleware, authorizer) => Layer.effect(middleware, Effect.gen(function* () {
19
+ const service = yield* authorizer;
20
+ const services = yield* Effect.context();
21
+ return Effect.fnUntraced(function* (httpEffect, options) {
22
+ const requirements = Option.orElse(Context.getOption(options.endpoint.annotations, Required), () => Option.map(Context.getOption(options.group.annotations, GroupRequired), (rules) => options.endpoint.method === "GET" ? rules.read : rules.write));
23
+ if (Option.isNone(requirements)) return yield* Effect.die(/* @__PURE__ */ new Error(`The endpoint ${options.group.identifier}.${options.endpoint.name} does not say what it needs. Give it the HttpApi.Required annotation.`));
24
+ for (const requirement of requirements.value) if (requirement.load === void 0) yield* service.check({
25
+ action: requirement.action,
26
+ kind: requirement.kind
27
+ });
28
+ else {
29
+ const params = yield* HttpRouter.params;
30
+ const value = yield* Effect.provideContext(requirement.load(params), services);
31
+ yield* service.check({
32
+ action: requirement.action,
33
+ resource: value
34
+ });
35
+ }
36
+ return yield* httpEffect;
37
+ });
38
+ }));
39
+ export { layer, requires };
40
+
41
+ //# sourceMappingURL=httpApi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"httpApi.js","names":[],"sources":["../../src/internal/httpApi.ts"],"sourcesContent":["// A `load` function of a requirement is kept in an annotation, so its error\n// type and its service type are erased to `unknown`. The language service\n// check for `unknown` in an Effect is off here.\n// @effect-diagnostics anyUnknownInErrorContext:off\nimport * as Context from \"effect/Context\"\nimport * as Effect from \"effect/Effect\"\nimport * as Layer from \"effect/Layer\"\nimport * as Option from \"effect/Option\"\nimport { HttpRouter } from \"effect/http\"\nimport type * as Authorizer from \"../Authorizer.ts\"\nimport type * as HttpApi from \"../HttpApi.ts\"\nimport { GroupRequired, Required } from \"../HttpApi.ts\"\n\n/** @internal */\nexport const requires = (\n\t_authorizer: unknown,\n\taction: string,\n\tkind: string,\n\tload?: HttpApi.Requirement[\"load\"],\n): HttpApi.Requirement =>\n\tObject.freeze(load === undefined ? { action, kind } : { action, kind, load })\n\n/** @internal */\nexport const layer = (\n\tmiddleware: Context.ServiceClass<any, string, any>,\n\tauthorizer: Authorizer.AnyServiceClass,\n) =>\n\tLayer.effect(\n\t\tmiddleware,\n\t\tEffect.gen(function* () {\n\t\t\tconst service = yield* authorizer\n\t\t\tconst services = yield* Effect.context<never>()\n\t\t\treturn Effect.fnUntraced(function* (\n\t\t\t\thttpEffect: Effect.Effect<unknown, unknown, unknown>,\n\t\t\t\toptions: {\n\t\t\t\t\treadonly endpoint: {\n\t\t\t\t\t\treadonly name: string\n\t\t\t\t\t\treadonly method: string\n\t\t\t\t\t\treadonly annotations: Context.Context<never>\n\t\t\t\t\t}\n\t\t\t\t\treadonly group: {\n\t\t\t\t\t\treadonly identifier: string\n\t\t\t\t\t\treadonly annotations: Context.Context<never>\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t) {\n\t\t\t\tconst requirements = Option.orElse(\n\t\t\t\t\tContext.getOption(options.endpoint.annotations, Required),\n\t\t\t\t\t() =>\n\t\t\t\t\t\tOption.map(\n\t\t\t\t\t\t\tContext.getOption(options.group.annotations, GroupRequired),\n\t\t\t\t\t\t\t(rules) =>\n\t\t\t\t\t\t\t\toptions.endpoint.method === \"GET\" ? rules.read : rules.write,\n\t\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t\tif (Option.isNone(requirements)) {\n\t\t\t\t\treturn yield* Effect.die(\n\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t`The endpoint ${options.group.identifier}.${options.endpoint.name} does not say what it needs. Give it the HttpApi.Required annotation.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tfor (const requirement of requirements.value) {\n\t\t\t\t\tif (requirement.load === undefined) {\n\t\t\t\t\t\tyield* service.check({\n\t\t\t\t\t\t\taction: requirement.action,\n\t\t\t\t\t\t\tkind: requirement.kind,\n\t\t\t\t\t\t} as never)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst params = yield* HttpRouter.params\n\t\t\t\t\t\tconst value = yield* Effect.provideContext(\n\t\t\t\t\t\t\trequirement.load(params),\n\t\t\t\t\t\t\tservices,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tyield* service.check({\n\t\t\t\t\t\t\taction: requirement.action,\n\t\t\t\t\t\t\tresource: value,\n\t\t\t\t\t\t} as never)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn yield* httpEffect\n\t\t\t})\n\t\t}),\n\t)\n"],"mappings":";;;;;;;;AAcA,MAAa,YACZ,aACA,QACA,MACA,SAEA,OAAO,OAAO,SAAS,KAAA,IAAY;CAAE;CAAQ;AAAK,IAAI;CAAE;CAAQ;CAAM;AAAK,CAAC;;AAG7E,MAAa,SACZ,YACA,eAEA,MAAM,OACL,YACA,OAAO,IAAI,aAAa;CACvB,MAAM,UAAU,OAAO;CACvB,MAAM,WAAW,OAAO,OAAO,QAAe;CAC9C,OAAO,OAAO,WAAW,WACxB,YACA,SAWC;EACD,MAAM,eAAe,OAAO,OAC3B,QAAQ,UAAU,QAAQ,SAAS,aAAa,QAAQ,SAEvD,OAAO,IACN,QAAQ,UAAU,QAAQ,MAAM,aAAa,aAAa,IACzD,UACA,QAAQ,SAAS,WAAW,QAAQ,MAAM,OAAO,MAAM,KACzD,CACF;EACA,IAAI,OAAO,OAAO,YAAY,GAC7B,OAAO,OAAO,OAAO,oBACpB,IAAI,MACH,gBAAgB,QAAQ,MAAM,WAAW,GAAG,QAAQ,SAAS,KAAK,sEACnE,CACD;EAED,KAAK,MAAM,eAAe,aAAa,OACtC,IAAI,YAAY,SAAS,KAAA,GACxB,OAAO,QAAQ,MAAM;GACpB,QAAQ,YAAY;GACpB,MAAM,YAAY;EACnB,CAAU;OACJ;GACN,MAAM,SAAS,OAAO,WAAW;GACjC,MAAM,QAAQ,OAAO,OAAO,eAC3B,YAAY,KAAK,MAAM,GACvB,QACD;GACA,OAAO,QAAQ,MAAM;IACpB,QAAQ,YAAY;IACpB,UAAU;GACX,CAAU;EACX;EAED,OAAO,OAAO;CACf,CAAC;AACF,CAAC,CACF"}