@nmnmcc/ability 1.0.1 → 2.0.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.
Files changed (127) hide show
  1. package/README.md +112 -69
  2. package/dist/Authorizer.d.ts +43 -47
  3. package/dist/Authorizer.d.ts.map +1 -1
  4. package/dist/Authorizer.js +5 -290
  5. package/dist/Authorizer.js.map +1 -1
  6. package/dist/Condition.d.ts +164 -332
  7. package/dist/Condition.d.ts.map +1 -1
  8. package/dist/Condition.js +75 -890
  9. package/dist/Condition.js.map +1 -1
  10. package/dist/Decision.d.ts +13 -13
  11. package/dist/Decision.d.ts.map +1 -1
  12. package/dist/Decision.js.map +1 -1
  13. package/dist/Domain.d.ts +10 -21
  14. package/dist/Domain.d.ts.map +1 -1
  15. package/dist/Domain.js +4 -62
  16. package/dist/Domain.js.map +1 -1
  17. package/dist/HttpApi.d.ts +31 -7
  18. package/dist/HttpApi.d.ts.map +1 -1
  19. package/dist/HttpApi.js +25 -8
  20. package/dist/HttpApi.js.map +1 -1
  21. package/dist/Limits.d.ts +114 -0
  22. package/dist/Limits.d.ts.map +1 -0
  23. package/dist/Limits.js +132 -0
  24. package/dist/Limits.js.map +1 -0
  25. package/dist/Policy.d.ts +276 -269
  26. package/dist/Policy.d.ts.map +1 -1
  27. package/dist/Policy.js +73 -1177
  28. package/dist/Policy.js.map +1 -1
  29. package/dist/Resource.d.ts +4 -177
  30. package/dist/Resource.d.ts.map +1 -1
  31. package/dist/Resource.js +4 -803
  32. package/dist/Resource.js.map +1 -1
  33. package/dist/index.d.ts +3 -4
  34. package/dist/index.js +4 -5
  35. package/dist/internal/algebra.js +267 -0
  36. package/dist/internal/algebra.js.map +1 -0
  37. package/dist/internal/analysis.js +245 -0
  38. package/dist/internal/analysis.js.map +1 -0
  39. package/dist/internal/authorizer.d.ts +30 -0
  40. package/dist/internal/authorizer.d.ts.map +1 -0
  41. package/dist/internal/authorizer.js +221 -0
  42. package/dist/internal/authorizer.js.map +1 -0
  43. package/dist/internal/bind.js +311 -0
  44. package/dist/internal/bind.js.map +1 -0
  45. package/dist/internal/catalog.d.ts +56 -0
  46. package/dist/internal/catalog.d.ts.map +1 -0
  47. package/dist/internal/catalog.js +292 -0
  48. package/dist/internal/catalog.js.map +1 -0
  49. package/dist/internal/decide.js +166 -0
  50. package/dist/internal/decide.js.map +1 -0
  51. package/dist/internal/domain.js +32 -0
  52. package/dist/internal/domain.js.map +1 -0
  53. package/dist/internal/json.js +134 -0
  54. package/dist/internal/json.js.map +1 -0
  55. package/dist/internal/limits.d.ts +14 -0
  56. package/dist/internal/limits.d.ts.map +1 -0
  57. package/dist/internal/limits.js +43 -0
  58. package/dist/internal/limits.js.map +1 -0
  59. package/dist/internal/nodes.d.ts +121 -0
  60. package/dist/internal/nodes.d.ts.map +1 -0
  61. package/dist/internal/nodes.js +277 -0
  62. package/dist/internal/nodes.js.map +1 -0
  63. package/dist/internal/patterns.js +110 -0
  64. package/dist/internal/patterns.js.map +1 -0
  65. package/dist/internal/policy-json.js +265 -0
  66. package/dist/internal/policy-json.js.map +1 -0
  67. package/dist/internal/policy-nodes.d.ts +61 -0
  68. package/dist/internal/policy-nodes.d.ts.map +1 -0
  69. package/dist/internal/policy-nodes.js +146 -0
  70. package/dist/internal/policy-nodes.js.map +1 -0
  71. package/dist/internal/policy.d.ts +42 -0
  72. package/dist/internal/policy.d.ts.map +1 -0
  73. package/dist/internal/policy.js +124 -0
  74. package/dist/internal/policy.js.map +1 -0
  75. package/dist/internal/read.js +39 -0
  76. package/dist/internal/read.js.map +1 -0
  77. package/dist/internal/resource.js +115 -0
  78. package/dist/internal/resource.js.map +1 -0
  79. package/dist/internal/rule.d.ts +26 -0
  80. package/dist/internal/rule.d.ts.map +1 -0
  81. package/dist/internal/rule.js +103 -0
  82. package/dist/internal/rule.js.map +1 -0
  83. package/dist/internal/search.d.ts +22 -0
  84. package/dist/internal/search.d.ts.map +1 -0
  85. package/dist/internal/search.js +274 -0
  86. package/dist/internal/search.js.map +1 -0
  87. package/dist/internal/suggest.js +46 -0
  88. package/dist/internal/suggest.js.map +1 -0
  89. package/package.json +3 -4
  90. package/src/Authorizer.ts +67 -583
  91. package/src/Condition.ts +339 -2095
  92. package/src/Decision.ts +6 -5
  93. package/src/Domain.ts +12 -69
  94. package/src/HttpApi.ts +72 -10
  95. package/src/Limits.ts +132 -0
  96. package/src/Policy.ts +391 -2772
  97. package/src/Resource.ts +7 -1548
  98. package/src/index.ts +3 -9
  99. package/src/internal/algebra.ts +482 -0
  100. package/src/internal/analysis.ts +478 -0
  101. package/src/internal/authorizer.ts +418 -0
  102. package/src/internal/bind.ts +648 -0
  103. package/src/internal/catalog.ts +534 -0
  104. package/src/internal/decide.ts +402 -0
  105. package/src/internal/domain.ts +66 -0
  106. package/src/internal/json.ts +260 -0
  107. package/src/internal/limits.ts +78 -0
  108. package/src/internal/nodes.ts +404 -0
  109. package/src/internal/patterns.ts +211 -0
  110. package/src/internal/policy-json.ts +487 -0
  111. package/src/internal/policy-nodes.ts +207 -0
  112. package/src/internal/policy.ts +264 -0
  113. package/src/internal/read.ts +55 -0
  114. package/src/internal/resource.ts +180 -0
  115. package/src/internal/rule.ts +196 -0
  116. package/src/internal/search.ts +541 -0
  117. package/src/internal/suggest.ts +104 -0
  118. package/dist/Principal.d.ts +0 -35
  119. package/dist/Principal.d.ts.map +0 -1
  120. package/dist/Principal.js +0 -37
  121. package/dist/Principal.js.map +0 -1
  122. package/dist/Rule.d.ts +0 -275
  123. package/dist/Rule.d.ts.map +0 -1
  124. package/dist/Rule.js +0 -257
  125. package/dist/Rule.js.map +0 -1
  126. package/src/Principal.ts +0 -41
  127. package/src/Rule.ts +0 -683
@@ -1 +1 @@
1
- {"version":3,"file":"Resource.js","names":["DataClass"],"sources":["../src/Resource.ts"],"sourcesContent":["/**\n * A resource is a kind of thing that a person may act on, such as a document\n * or an invoice. Each resource has a kind name, a list of actions, a Schema for its\n * data, and an optional path.\n *\n * Make a resource in one of two ways:\n * - {@link Class} makes a Schema class, in the same way as\n * `Schema.TaggedClass`. The class is a Schema, a constructor, and a resource\n * at the same time.\n * - {@link make} makes a resource from plain fields. Its values are plain\n * objects with a `_tag` field.\n *\n * Every value of a resource has a `_tag` field with the kind name. The library\n * uses this field to find the resource of a value. It does not guess from the\n * constructor name.\n *\n * A path puts a resource inside a tree, such as\n * `[\"org\", organizationId, \"team\", teamId, \"doc\", id]`. A condition can\n * then ask if a value is under a part of the tree. See `Condition.under`.\n *\n * @stability stable\n * @since 0.3.0\n */\nimport * as Arr from \"effect/Array\"\nimport { Class as DataClass } from \"effect/Data\"\nimport * as HashMap from \"effect/HashMap\"\nimport * as HashSet from \"effect/HashSet\"\nimport * as Option from \"effect/Option\"\nimport { hasProperty, isObject } from \"effect/Predicate\"\nimport * as Schema from \"effect/Schema\"\nimport * as SchemaAST from \"effect/SchemaAST\"\n\n/**\n * One part of a resource path. A string is a fixed part. A field reference\n * takes the part from a field of the value.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport type PathSegment = string | FieldRef<string>\n\n/**\n * A reference to a top-level field of a resource, used in a path.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport interface FieldRef<Name extends string> {\n\treadonly _tag: \"Field\"\n\treadonly field: Name\n}\n\n/**\n * The runtime data of a resource.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport interface Descriptor {\n\treadonly kind: string\n\treadonly actions: ReadonlyArray<string>\n\treadonly path: ReadonlyArray<PathSegment> | undefined\n\t/** The paths of the data fields, with dots for nested fields. */\n\treadonly fieldPaths: ReadonlyArray<string>\n\t/**\n\t * The paths in {@link fieldPaths} of fields that hold more than one value,\n\t * such as a record, a map or an array. The parts of such a field are not\n\t * in `fieldPaths`, but a rule may name them.\n\t */\n\treadonly openPaths: ReadonlyArray<string>\n\t/**\n\t * A struct Schema of the data of the values, with the `_tag` field. It is a\n\t * struct also for a `Resource.Class`. The class Schema must not be read\n\t * before the class is made, because Effect then binds the class Schema to\n\t * the base class, and the values lose the getters of the class.\n\t */\n\treadonly schema: Schema.Top\n}\n\n/**\n * A resource. `Kind` is its name, `Action` is the union of its actions, `Data`\n * is the type of its Schema fields, and `Value` is the type of its values.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport interface Resource<\n\tKind extends string,\n\tAction extends string,\n\tData extends object,\n\tValue extends { readonly _tag: Kind },\n> {\n\treadonly descriptor: Descriptor\n\treadonly \"~Resource\"?: {\n\t\treadonly Kind: Kind\n\t\treadonly Action: Action\n\t\treadonly Data: Data\n\t\treadonly Value: Value\n\t}\n}\n\n/**\n * Any resource.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport type Any = Resource<string, string, object, { readonly _tag: string }>\n\n/**\n * The kind name of a resource.\n *\n * @stability stable\n * @category utility types\n * @since 0.3.0\n */\nexport type Kind<R> = R extends Resource<infer K, any, any, any> ? K : never\n\n/**\n * The actions of a resource.\n *\n * @stability stable\n * @category utility types\n * @since 0.3.0\n */\nexport type Action<R> = R extends Resource<any, infer A, any, any> ? A : never\n\n/**\n * The type of the Schema fields of a resource, without `_tag`.\n *\n * @stability stable\n * @category utility types\n * @since 0.3.0\n */\nexport type Data<R> = R extends Resource<any, any, infer D, any> ? D : never\n\n/**\n * The type of the values of a resource.\n *\n * @stability stable\n * @category utility types\n * @since 0.3.0\n */\nexport type Value<R> = R extends Resource<any, any, any, infer V> ? V : never\n\n/**\n * The options of a resource.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport interface Options<\n\tActions extends ReadonlyArray<string>,\n\tFields extends Schema.Struct.Fields,\n> {\n\treadonly actions: Actions\n\treadonly fields: Fields\n\t/**\n\t * Gives the path of the resource. The function gets one reference for each\n\t * top-level field.\n\t */\n\treadonly path?: (fields: {\n\t\treadonly [K in keyof Fields & string]: FieldRef<K>\n\t}) => ReadonlyArray<string | FieldRef<keyof Fields & string>>\n}\n\n/**\n * The class of the runtime data of a resource. {@link isResource} uses it to\n * know a resource.\n */\nclass ResourceDescriptor extends DataClass<Descriptor> {}\n\n/** The prototypes from `prototype` up, below `Object.prototype`. */\nconst prototypesFrom = (prototype: unknown): ReadonlyArray<object> =>\n\tArr.unfold(prototype, (current) =>\n\t\ttypeof current === \"object\" &&\n\t\tcurrent !== null &&\n\t\tcurrent !== Object.prototype\n\t\t\t? Option.some([current, Object.getPrototypeOf(current)] as const)\n\t\t\t: Option.none(),\n\t)\n\n/**\n * Gives the prototype of the class of a class node, or `undefined`. The node\n * does not keep the class: a class Schema with an annotation or a check, or\n * one inside `Schema.suspend`, is a new Schema with the same node. So the\n * walk asks the node to make a value with no check, and reads its prototype.\n *\n * This uses the `\"~constructor\"` annotation of Effect, which is not a public\n * API: it gives a link whose decode makes a value of the class from its\n * fields without a check. When that is not so, the walk gives `undefined`,\n * and the check of a policy says no to the getter.\n */\nconst classPrototype = (ast: SchemaAST.Declaration): object | undefined => {\n\tconst make: unknown = ast.annotations?.[\"~constructor\"]\n\tif (typeof make !== \"function\") {\n\t\treturn undefined\n\t}\n\ttry {\n\t\tconst made: unknown = make(ast.typeParameters)\n\t\tconst decode: unknown =\n\t\t\thasProperty(made, \"link\") &&\n\t\t\thasProperty(made.link, \"transformation\") &&\n\t\t\thasProperty(made.link.transformation, \"decode\")\n\t\t\t\t? made.link.transformation.decode\n\t\t\t\t: undefined\n\t\tconst value: unknown =\n\t\t\thasProperty(decode, \"transform\") && typeof decode.transform === \"function\"\n\t\t\t\t? decode.transform({})\n\t\t\t\t: undefined\n\t\treturn isObject(value) ? Object.getPrototypeOf(value) : undefined\n\t} catch {\n\t\treturn undefined\n\t}\n}\n\n/**\n * Tests if a path names a getter of a class Schema, such as a getter of a\n * `Schema.Class` or a `Principal.Class`, at its root or in a nested field. A\n * condition reads such a field, and the types of a condition take it, so the\n * check of a policy takes it too. It goes into the fields of a struct, the\n * values of a record, the members of a union, `Schema.suspend`, and a class\n * with an annotation or a check.\n *\n * @stability stable\n * @category predicates\n * @since 1.0.0\n */\nexport const hasGetter = (schema: unknown, path: string): boolean =>\n\t!isTooLong(path) &&\n\tSchema.isSchema(schema) &&\n\tgetterAt(\n\t\tschema.ast,\n\t\tpath.split(\".\"),\n\t\t0,\n\t\t(part, name) => part === name,\n\t\tnew Map(),\n\t)\n\n/**\n * The most parts that a field path may have. The walks below call themselves\n * for each part, and a path comes from the input of a policy. So a very long\n * path, as in a recursive Schema, could fill the stack.\n */\nconst maxPathParts = 256\n\n/** Tests if a field path has more than {@link maxPathParts} parts. */\nconst isTooLong = (path: string): boolean =>\n\tpath.split(\".\", maxPathParts + 1).length > maxPathParts\n\n/**\n * Tests if a Schema has a getter of a class at a path whose parts fit\n * `parts`, as `hasGetter` does for one path. A part fits a name when `fits`\n * says so, as a part with `*` fits many names. A part `**` stands for any\n * number of parts, also none.\n *\n * @stability stable\n * @category predicates\n * @since 1.0.0\n */\nexport const hasMatchingGetter = (\n\tschema: unknown,\n\tparts: ReadonlyArray<string>,\n\tfits: (part: string, name: string) => boolean,\n): boolean =>\n\tparts.length <= maxPathParts &&\n\tSchema.isSchema(schema) &&\n\tgetterAt(schema.ast, parts, 0, fits, new Map())\n\n/** The names of the getters of a prototype and the prototypes above it. */\nconst getterNames = (prototype: object | undefined): ReadonlyArray<string> =>\n\tArr.flatMap(prototypesFrom(prototype), (current) =>\n\t\tArr.filter(\n\t\t\tObject.getOwnPropertyNames(current),\n\t\t\t(name) =>\n\t\t\t\tObject.getOwnPropertyDescriptor(current, name)?.get !== undefined,\n\t\t),\n\t)\n\nconst getterAt = (\n\tast: SchemaAST.AST,\n\tnames: ReadonlyArray<string>,\n\tindex: number,\n\tfits: (part: string, name: string) => boolean,\n\tmemo: PathMemo<boolean>,\n): boolean =>\n\trememberAt(memo, ast, index, false, () => {\n\t\tconst name = names[index]\n\t\tif (name === undefined) {\n\t\t\treturn false\n\t\t}\n\t\tconst last = index === names.length - 1\n\t\tconst next = (type: SchemaAST.AST, at: number) =>\n\t\t\tgetterAt(type, names, at, fits, memo)\n\t\t// A `**` may stand for no parts.\n\t\tif (name === \"**\" && !last && next(ast, index + 1)) {\n\t\t\treturn true\n\t\t}\n\t\tswitch (ast._tag) {\n\t\t\tcase \"Union\":\n\t\t\t\treturn Arr.some(ast.types, (type) => next(type, index))\n\t\t\tcase \"Suspend\":\n\t\t\t\treturn next(ast.thunk(), index)\n\t\t\tcase \"Declaration\": {\n\t\t\t\tconst inner = classStruct(ast)\n\t\t\t\tif (inner === undefined) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\t// A path ends at a getter. The library can not see the type of\n\t\t\t\t// the value of a getter, so it can not check a path that goes\n\t\t\t\t// past it.\n\t\t\t\treturn last\n\t\t\t\t\t? Arr.some(getterNames(classPrototype(ast)), (getter) =>\n\t\t\t\t\t\t\tfits(name, getter),\n\t\t\t\t\t\t)\n\t\t\t\t\t: next(inner, index)\n\t\t\t}\n\t\t\tcase \"Objects\":\n\t\t\t\treturn (\n\t\t\t\t\t!last &&\n\t\t\t\t\t(Arr.some(\n\t\t\t\t\t\tast.propertySignatures,\n\t\t\t\t\t\t(property) =>\n\t\t\t\t\t\t\ttypeof property.name === \"string\" &&\n\t\t\t\t\t\t\t// A `**` may stand for this part and more.\n\t\t\t\t\t\t\t((name === \"**\" && next(property.type, index)) ||\n\t\t\t\t\t\t\t\t(fits(name, property.name) && next(property.type, index + 1))),\n\t\t\t\t\t) ||\n\t\t\t\t\t\t// A record keeps the Schema of its keys and of its values.\n\t\t\t\t\t\tArr.some(ast.indexSignatures, (signature) =>\n\t\t\t\t\t\t\tname === \"**\"\n\t\t\t\t\t\t\t\t? hasSomeKey(signature.parameter) &&\n\t\t\t\t\t\t\t\t\t(next(signature.type, index) ||\n\t\t\t\t\t\t\t\t\t\tnext(signature.type, index + 1))\n\t\t\t\t\t\t\t\t: Arr.some(\n\t\t\t\t\t\t\t\t\t\t[name.replaceAll(\"*\", \"\"), name.replaceAll(\"*\", \"a\")],\n\t\t\t\t\t\t\t\t\t\t(key) =>\n\t\t\t\t\t\t\t\t\t\t\tfits(name, key) && keyFits(signature.parameter, key),\n\t\t\t\t\t\t\t\t\t) && next(signature.type, index + 1),\n\t\t\t\t\t\t))\n\t\t\t\t)\n\t\t\tdefault:\n\t\t\t\treturn false\n\t\t}\n\t})\n\n/**\n * Tests if a record takes a key. A key of an object is a string, also a key\n * that a number Schema takes: `{ 1: \"a\" }` has the key `\"1\"`. So a key that\n * is the text of a number is tried as that number too.\n */\nconst keyFits = (parameter: SchemaAST.AST, key: string): boolean => {\n\tconst is = Schema.is(Schema.make(parameter))\n\treturn (\n\t\tis(key) || (key !== \"\" && String(Number(key)) === key && is(Number(key)))\n\t)\n}\n\n/**\n * Gives the struct of a `Schema.Class`. A class is a declaration with one\n * struct as its type parameter, and Effect marks it with a `\"~constructor\"`\n * annotation, also through more codec steps, as in\n * `Schema.fromJsonString(User)`. Other declarations, such as\n * `Schema.OptionFromNullOr` or `Schema.ReadonlyMap`, have no such mark, and\n * the fields of their type parameter are not fields of the value.\n */\nconst classStruct = (\n\tast: SchemaAST.Declaration,\n): SchemaAST.Objects | undefined => {\n\tconst [inner] = ast.typeParameters\n\treturn ast.annotations?.[\"~constructor\"] !== undefined &&\n\t\tast.typeParameters.length === 1 &&\n\t\tinner?._tag === \"Objects\"\n\t\t? inner\n\t\t: undefined\n}\n\n/**\n * Gives the structs inside a Schema, with the `Schema.suspend` nodes that are\n * open on the way to each one. The open nodes are in a native `Set`, because\n * it must find a node by the node itself: `Equal` compares Schema nodes by\n * structure, and a recursive Schema has no end. It looks through optional keys, unions such as\n * `Schema.NullOr`, `Schema.suspend`, and `Schema.Class`. A suspend node that\n * is already open is not opened again, so a recursive Schema has an end.\n */\nconst structsOf = (\n\tast: SchemaAST.AST,\n\topen: ReadonlySet<SchemaAST.AST>,\n): ReadonlyArray<readonly [SchemaAST.Objects, ReadonlySet<SchemaAST.AST>]> => {\n\tswitch (ast._tag) {\n\t\tcase \"Objects\":\n\t\t\treturn ast.propertySignatures.length === 0 ? [] : [[ast, open]]\n\t\tcase \"Union\":\n\t\t\treturn ast.types.flatMap((type) => structsOf(type, open))\n\t\tcase \"Suspend\":\n\t\t\treturn open.has(ast)\n\t\t\t\t? []\n\t\t\t\t: structsOf(ast.thunk(), new Set([...open, ast]))\n\t\tcase \"Declaration\": {\n\t\t\tconst inner = classStruct(ast)\n\t\t\treturn inner === undefined ? [] : structsOf(inner, open)\n\t\t}\n\t\tdefault:\n\t\t\treturn []\n\t}\n}\n\n/** Tests if a Schema holds one plain value, with no parts. */\n/**\n * The kind of value that a field holds: one plain value, a record with keys\n * that the Schema does not name, or another value with parts, such as an\n * array or a map.\n */\ntype FieldShape = \"scalar\" | \"record\" | \"other\"\n\n/** Gives the kind of value that a field holds. See {@link FieldShape}. */\nconst shapeOf = (\n\tast: SchemaAST.AST,\n\topen: ReadonlySet<SchemaAST.AST> = new Set(),\n): FieldShape => {\n\tswitch (ast._tag) {\n\t\tcase \"Objects\":\n\t\t\treturn ast.indexSignatures.length > 0 ? \"record\" : \"other\"\n\t\tcase \"Union\": {\n\t\t\tconst shapes = ast.types.map((type) => shapeOf(type, open))\n\t\t\treturn shapes.every((shape) => shape === \"scalar\")\n\t\t\t\t? \"scalar\"\n\t\t\t\t: shapes.includes(\"record\")\n\t\t\t\t\t? \"record\"\n\t\t\t\t\t: \"other\"\n\t\t}\n\t\tcase \"Suspend\":\n\t\t\treturn open.has(ast)\n\t\t\t\t? \"other\"\n\t\t\t\t: shapeOf(ast.thunk(), new Set([...open, ast]))\n\t\tdefault:\n\t\t\treturn isScalar(ast) ? \"scalar\" : \"other\"\n\t}\n}\n\nconst isScalar = (ast: SchemaAST.AST): boolean => {\n\tswitch (ast._tag) {\n\t\tcase \"String\":\n\t\tcase \"Number\":\n\t\tcase \"Boolean\":\n\t\tcase \"BigInt\":\n\t\tcase \"Symbol\":\n\t\tcase \"UniqueSymbol\":\n\t\tcase \"Literal\":\n\t\tcase \"Enum\":\n\t\tcase \"TemplateLiteral\":\n\t\tcase \"Null\":\n\t\tcase \"Undefined\":\n\t\t\treturn true\n\t\tdefault:\n\t\t\treturn false\n\t}\n}\n\n/**\n * Tests if a Schema holds, in some branch, a value that is not a struct: a\n * scalar, or a value such as a record or an array.\n */\nconst holdsValue = (\n\tast: SchemaAST.AST,\n\topen: ReadonlySet<SchemaAST.AST>,\n): boolean => {\n\tswitch (ast._tag) {\n\t\tcase \"Objects\":\n\t\t\t// A struct with a record part, as from `Schema.StructWithRest`, holds\n\t\t\t// keys that are not named, so it holds more than one value.\n\t\t\treturn (\n\t\t\t\tast.propertySignatures.length === 0 || ast.indexSignatures.length > 0\n\t\t\t)\n\t\tcase \"Union\":\n\t\t\treturn ast.types.some((type) => holdsValue(type, open))\n\t\tcase \"Suspend\":\n\t\t\treturn !open.has(ast) && holdsValue(ast.thunk(), new Set([...open, ast]))\n\t\tcase \"Declaration\":\n\t\t\treturn classStruct(ast) === undefined\n\t\tdefault:\n\t\t\treturn true\n\t}\n}\n\n/** One field that {@link walkFields} finds. */\ninterface FieldVisit {\n\treadonly path: string\n\t/**\n\t * `true` for a field that holds a value that is not a struct, and `false`\n\t * for a field that holds a struct.\n\t */\n\treadonly leaf: boolean\n\treadonly type: SchemaAST.AST\n}\n\n/**\n * Gives the path of every field of a Schema, with a dot between the names of\n * nested fields. A field of a union may come two times: one time as a field\n * that holds a value, and one time as a field that holds a struct.\n */\nconst walkFields = (\n\tast: SchemaAST.AST,\n\tprefix = \"\",\n\topen: ReadonlySet<SchemaAST.AST> = new Set(),\n): ReadonlyArray<FieldVisit> =>\n\tArr.flatMap(structsOf(ast, open), ([struct, inner]) =>\n\t\tArr.flatMap(struct.propertySignatures, (property): Array<FieldVisit> => {\n\t\t\tconst name = property.name\n\t\t\tif (typeof name !== \"string\") {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\t// A dot in a path is the step into a nested field. A field name with a\n\t\t\t// dot would make two fields have one path, so it is a defect.\n\t\t\tif (name.includes(\".\")) {\n\t\t\t\tthrow new Error(`A field name may not have a dot: \"${name}\"`)\n\t\t\t}\n\t\t\t// An empty name would make an empty part in a path, such as `.secret`.\n\t\t\tif (name === \"\") {\n\t\t\t\tthrow new Error(\"A field name may not be empty\")\n\t\t\t}\n\t\t\tconst path = prefix === \"\" ? name : `${prefix}.${name}`\n\t\t\tconst type = property.type\n\t\t\treturn [\n\t\t\t\t...(holdsValue(type, inner) ? [{ path, leaf: true, type }] : []),\n\t\t\t\t...(structsOf(type, inner).length > 0\n\t\t\t\t\t? [{ path, leaf: false, type }, ...walkFields(type, path, inner)]\n\t\t\t\t\t: []),\n\t\t\t]\n\t\t}),\n\t)\n\n/**\n * Gives the paths of all the fields of a Schema, with dots for nested fields.\n * A nested struct gives its own path and the paths of its fields. Arrays are\n * left out. It throws when a field name has a dot or is empty, because such a\n * name would give two fields one path, or a path with an empty part.\n *\n * @stability stable\n * @category getters\n * @since 1.0.0\n */\nexport const fieldPaths = (schema: Schema.Top): ReadonlyArray<string> =>\n\tArr.dedupe(Arr.map(walkFields(schema.ast), (visit) => visit.path))\n\n/** Tests if a Schema holds only plain scalars: see {@link isPlainField}. */\n/**\n * The ids of the checks that the search knows. `domainOf` reads them, so a\n * field with only these checks has an exact domain.\n */\nconst knownChecks = HashSet.make(\n\t\"effect/schema/isInt\",\n\t\"effect/schema/isFinite\",\n)\n\n/**\n * Tests if each check of a Schema node is a check that the search knows. A\n * check such as `isGreaterThan(0)` stops some values, and the search does not\n * see it, so it could find a value that the Schema does not take.\n */\nconst hasOnlyKnownChecks = (\n\tchecks: ReadonlyArray<SchemaAST.Check<never>> | undefined,\n): boolean =>\n\tArr.every(checks ?? [], (check) =>\n\t\tcheck._tag === \"FilterGroup\"\n\t\t\t? hasOnlyKnownChecks(check.checks)\n\t\t\t: HashSet.has(knownChecks, check.annotations?.representation?.id),\n\t)\n\nconst isPlainScalar = (ast: SchemaAST.AST): boolean => {\n\t// `domainOf` reads the known checks only on a number node. A check on\n\t// another node, such as on a union of literals, is a check it can not see.\n\tif (\n\t\tast._tag === \"Number\"\n\t\t\t? !hasOnlyKnownChecks(ast.checks)\n\t\t\t: (ast.checks ?? []).length > 0\n\t) {\n\t\treturn false\n\t}\n\tswitch (ast._tag) {\n\t\tcase \"String\":\n\t\tcase \"Number\":\n\t\tcase \"Boolean\":\n\t\tcase \"Literal\":\n\t\tcase \"Null\":\n\t\tcase \"Undefined\":\n\t\t\treturn true\n\t\tcase \"Union\":\n\t\t\t// A union in the mode \"oneOf\" stops a value that fits two members.\n\t\t\t// The search does not see that, so such a field is not plain.\n\t\t\treturn (\n\t\t\t\tast.options?.mode !== \"oneOf\" && Arr.every(ast.types, isPlainScalar)\n\t\t\t)\n\t\tdefault:\n\t\t\treturn false\n\t}\n}\n\n/**\n * Tests if a path names a plain scalar field of a Schema: a string, a number,\n * a boolean, a literal, `null`, or an optional field or a union of these. Its\n * only checks may be integer and finite checks: another check, such as\n * `isGreaterThan(0)`, stops values that the search does not know about. On\n * the way, each part must be a required field of a plain struct with no\n * checks, with a name that is not a name of `Object.prototype`.\n *\n * `Policy.coverage` and `Condition.satisfiable` answer `All`, `None` or\n * `Some` only when each field of the condition is such a field. Their model of\n * the values of a field is exact for these Schemas. For other Schemas, such as\n * classes, records, unions of structs or declarations, a value may have data\n * that the Schema does not show, and the answer is `Unknown`.\n *\n * @stability stable\n * @category predicates\n * @since 1.0.0\n */\nexport const isPlainField = (schema: Schema.Top, path: string): boolean =>\n\t!isTooLong(path) && plainAt(schema.ast, path.split(\".\"))\n\nconst plainAt = (ast: SchemaAST.AST, names: ReadonlyArray<string>): boolean => {\n\tconst [name, ...rest] = names\n\tif (\n\t\tname === undefined ||\n\t\tast._tag !== \"Objects\" ||\n\t\tast.indexSignatures.length > 0 ||\n\t\t(ast.checks ?? []).length > 0 ||\n\t\tname in Object.prototype\n\t) {\n\t\treturn false\n\t}\n\tconst property = ast.propertySignatures.find(\n\t\t(signature) => signature.name === name,\n\t)\n\tif (property === undefined) {\n\t\treturn false\n\t}\n\treturn rest.length === 0\n\t\t? isPlainScalar(property.type)\n\t\t: !SchemaAST.isOptional(property.type) && plainAt(property.type, rest)\n}\n\n/**\n * Tests if a path names a field of a Schema that holds a value with no named\n * fields: a scalar, or a value such as a record or an array. It goes into\n * records by their keys, and into recursive Schemas as far as the path goes.\n * So it finds paths that {@link fieldPaths} does not list.\n *\n * @stability stable\n * @category predicates\n * @since 1.0.0\n */\nexport const hasPath = (schema: Schema.Top, path: string): boolean =>\n\t!isTooLong(path) && resolves(schema.ast, path.split(\".\"), 0, new Map())\n\n/**\n * The answers of a walk along a path, by Schema node and by place in the path.\n * Two branches of a union may come to one node at one place, as in a recursive\n * union, and the memo does that work one time. It is a native `Map`, because\n * it must find a Schema node by the node itself.\n */\ntype PathMemo<A> = Map<SchemaAST.AST, Map<number, A>>\n\n/**\n * Gives the answer for a node at a place from the memo, or works it out and\n * keeps it. While the work runs, the memo holds `pending`, so a walk that\n * comes back to the node at the same place, with no step on the path, gets\n * `pending` and stops.\n */\nconst rememberAt = <A>(\n\tmemo: PathMemo<A>,\n\tast: SchemaAST.AST,\n\tindex: number,\n\tpending: A,\n\twork: () => A,\n): A => {\n\tconst places = memo.get(ast) ?? new Map<number, A>()\n\tmemo.set(ast, places)\n\tif (places.has(index)) {\n\t\treturn places.get(index) as A\n\t}\n\tplaces.set(index, pending)\n\tconst result = work()\n\tplaces.set(index, result)\n\treturn result\n}\n\nconst resolves = (\n\tast: SchemaAST.AST,\n\tnames: ReadonlyArray<string>,\n\tindex: number,\n\tmemo: PathMemo<boolean>,\n): boolean =>\n\trememberAt(memo, ast, index, false, () => {\n\t\tif (index === names.length) {\n\t\t\treturn index > 0 && holdsValue(ast, new Set())\n\t\t}\n\t\tconst name = names[index]!\n\t\tswitch (ast._tag) {\n\t\t\tcase \"Objects\": {\n\t\t\t\tconst property = ast.propertySignatures.find(\n\t\t\t\t\t(signature) => signature.name === name,\n\t\t\t\t)\n\t\t\t\tif (property !== undefined) {\n\t\t\t\t\treturn resolves(property.type, names, index + 1, memo)\n\t\t\t\t}\n\t\t\t\t// A key of a record must fit the Schema of the keys.\n\t\t\t\treturn ast.indexSignatures.some(\n\t\t\t\t\t(signature) =>\n\t\t\t\t\t\tkeyFits(signature.parameter, name) &&\n\t\t\t\t\t\tresolves(signature.type, names, index + 1, memo),\n\t\t\t\t)\n\t\t\t}\n\t\t\tcase \"Union\":\n\t\t\t\treturn ast.types.some((type) => resolves(type, names, index, memo))\n\t\t\tcase \"Suspend\":\n\t\t\t\treturn resolves(ast.thunk(), names, index, memo)\n\t\t\tcase \"Declaration\": {\n\t\t\t\tconst inner = classStruct(ast)\n\t\t\t\treturn inner !== undefined && resolves(inner, names, index, memo)\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn false\n\t\t}\n\t})\n\n/**\n * Tests if a Schema has a field whose path fits a pattern. `parts` are the\n * parts of the pattern, split at the dots. A part `**` stands for any number\n * of parts, also none. Another part fits a name when `fits` says so, as a\n * part with `*` fits many names. For a record, the walk asks if the key\n * Schema takes a key that fits the part. For a template literal key Schema,\n * with parts that are literals and strings, the answer is exact. For another key Schema, the walk tries sample keys, so it may miss a\n * key, and then the answer is `false`.\n *\n * @stability stable\n * @category predicates\n * @since 1.0.0\n */\nexport const hasMatchingPath = (\n\tschema: Schema.Top,\n\tparts: ReadonlyArray<string>,\n\tfits: (part: string, name: string) => boolean,\n): boolean =>\n\tparts.length <= maxPathParts &&\n\tmatchesFrom(schema.ast, parts, 0, false, fits, new Map())\n\nconst matchesFrom = (\n\tast: SchemaAST.AST,\n\tparts: ReadonlyArray<string>,\n\tindex: number,\n\tstepped: boolean,\n\tfits: (part: string, name: string) => boolean,\n\tmemo: PathMemo<boolean>,\n): boolean =>\n\t// The memo keeps two answers for each place: before the first step, and\n\t// after it.\n\trememberAt(memo, ast, index * 2 + (stepped ? 1 : 0), false, () => {\n\t\tconst next = (type: SchemaAST.AST, at: number, step: boolean): boolean =>\n\t\t\tmatchesFrom(type, parts, at, step, fits, memo)\n\t\tswitch (ast._tag) {\n\t\t\tcase \"Union\":\n\t\t\t\treturn Arr.some(ast.types, (type) => next(type, index, stepped))\n\t\t\tcase \"Suspend\":\n\t\t\t\treturn next(ast.thunk(), index, stepped)\n\t\t\tcase \"Declaration\": {\n\t\t\t\tconst inner = classStruct(ast)\n\t\t\t\tif (inner !== undefined) {\n\t\t\t\t\treturn next(inner, index, stepped)\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tbreak\n\t\t}\n\t\t// The path ends at a field that holds a value, as a field that a rule\n\t\t// may name does.\n\t\tif (index === parts.length) {\n\t\t\treturn stepped && holdsValue(ast, new Set())\n\t\t}\n\t\tconst part = parts[index]!\n\t\tif (part === \"**\" && next(ast, index + 1, stepped)) {\n\t\t\treturn true\n\t\t}\n\t\tif (ast._tag !== \"Objects\") {\n\t\t\treturn false\n\t\t}\n\t\t// Keys made from the part, and keys made from the key Schema. A key\n\t\t// Schema such as `TemplateLiteral([\"x\", String])` takes neither \"\" nor\n\t\t// \"a\", but it takes \"x\" and \"xa\".\n\t\tconst fromPart = [part.replaceAll(\"*\", \"\"), part.replaceAll(\"*\", \"a\")]\n\t\treturn (\n\t\t\tArr.some(\n\t\t\t\tast.propertySignatures,\n\t\t\t\t(property) =>\n\t\t\t\t\ttypeof property.name === \"string\" &&\n\t\t\t\t\t(part === \"**\"\n\t\t\t\t\t\t? next(property.type, index, true)\n\t\t\t\t\t\t: fits(part, property.name) &&\n\t\t\t\t\t\t\tnext(property.type, index + 1, true)),\n\t\t\t) ||\n\t\t\tArr.some(ast.indexSignatures, (signature) =>\n\t\t\t\tpart === \"**\"\n\t\t\t\t\t? // A step into a record needs a key that its key Schema takes.\n\t\t\t\t\t\thasSomeKey(signature.parameter) && next(signature.type, index, true)\n\t\t\t\t\t: // A template literal key Schema gives an exact answer. Another\n\t\t\t\t\t\t// key Schema is tried with sample keys.\n\t\t\t\t\t\t(globMeetsKeys(part, signature.parameter) ??\n\t\t\t\t\t\t\tArr.some(\n\t\t\t\t\t\t\t\tArr.dedupe([...fromPart, ...sampleKeys(signature.parameter)]),\n\t\t\t\t\t\t\t\t(key) => keyFits(signature.parameter, key) && fits(part, key),\n\t\t\t\t\t\t\t)) &&\n\t\t\t\t\t\tnext(signature.type, index + 1, true),\n\t\t\t)\n\t\t)\n\t})\n\n/**\n * Tests if a key Schema takes some key: the exact search for a template\n * literal, or a sample key.\n */\nconst hasSomeKey = (parameter: SchemaAST.AST): boolean =>\n\tglobMeetsKeys(\"*\", parameter) ??\n\tArr.some(Arr.dedupe([\"\", \"a\", ...sampleKeys(parameter)]), (key) =>\n\t\tkeyFits(parameter, key),\n\t)\n\n/** The longest key pattern that the exact search of keys takes. */\nconst maxExactKeyLength = 256\n\n/** A part of a key pattern: one character, or `*` for any characters. */\ntype GlobToken =\n\t{ readonly _tag: \"Char\"; readonly char: string } | { readonly _tag: \"Star\" }\n\n/** A part of a template literal: one character, or any characters. */\ntype TemplateToken =\n\t{ readonly _tag: \"Char\"; readonly char: string } | { readonly _tag: \"Any\" }\n\nconst charsOf = (text: string): ReadonlyArray<TemplateToken> =>\n\tArr.map(Array.from(text), (char) => ({ _tag: \"Char\", char }) as const)\n\n/**\n * Gives the token lists of a template literal, one for each choice of its\n * unions of literals, or `undefined` when the lists can not be exact: a part\n * that this walk does not know, such as a number, a part with checks, or\n * more than 64 lists.\n */\nconst templateTokens = (\n\tast: SchemaAST.TemplateLiteral,\n): ReadonlyArray<ReadonlyArray<TemplateToken>> | undefined => {\n\tconst partTokens = (\n\t\tpart: SchemaAST.AST,\n\t): ReadonlyArray<ReadonlyArray<TemplateToken>> | undefined => {\n\t\tif ((part.checks ?? []).length > 0) {\n\t\t\treturn undefined\n\t\t}\n\t\tswitch (part._tag) {\n\t\t\tcase \"Literal\": {\n\t\t\t\tconst text = String(part.literal)\n\t\t\t\t// A half of a pair of UTF-16 code units may join a half in the\n\t\t\t\t// next part, and the tokens of each part can not show that.\n\t\t\t\treturn /[\\uD800-\\uDFFF]/.test(text) ? undefined : [charsOf(text)]\n\t\t\t}\n\t\t\tcase \"String\":\n\t\t\t\treturn [[{ _tag: \"Any\" }]]\n\t\t\tcase \"Number\":\n\t\t\t\t// The tokens can not hold all numbers, such as `-1.5`, so the\n\t\t\t\t// search is not exact.\n\t\t\t\treturn undefined\n\t\t\tcase \"Union\": {\n\t\t\t\t// A union in the mode \"oneOf\" stops a key that fits two members,\n\t\t\t\t// and token lists can not show that.\n\t\t\t\tif (part.options?.mode === \"oneOf\") {\n\t\t\t\t\treturn undefined\n\t\t\t\t}\n\t\t\t\tconst choices = Arr.map(part.types, partTokens)\n\t\t\t\treturn Arr.every(choices, (choice) => choice !== undefined)\n\t\t\t\t\t? Arr.flatten(\n\t\t\t\t\t\t\tchoices as ReadonlyArray<\n\t\t\t\t\t\t\t\tReadonlyArray<ReadonlyArray<TemplateToken>>\n\t\t\t\t\t\t\t>,\n\t\t\t\t\t\t)\n\t\t\t\t\t: undefined\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn undefined\n\t\t}\n\t}\n\treturn Arr.reduce(\n\t\tast.parts,\n\t\t[[]] as ReadonlyArray<ReadonlyArray<TemplateToken>> | undefined,\n\t\t(lists, part) => {\n\t\t\tconst choices = partTokens(part)\n\t\t\tif (lists === undefined || choices === undefined) {\n\t\t\t\treturn undefined\n\t\t\t}\n\t\t\t// Each list so far, with each choice of this part. Past 64 lists the\n\t\t\t// search would not be exact, so it gives no answer.\n\t\t\tconst all = Arr.flatMap(lists, (list) =>\n\t\t\t\tArr.map(choices, (choice) => [...list, ...choice]),\n\t\t\t)\n\t\t\t// The search calls itself for each character, so a long list of\n\t\t\t// tokens gives no answer too.\n\t\t\treturn all.length > 64 ||\n\t\t\t\tArr.some(all, (list) => list.length > maxExactKeyLength)\n\t\t\t\t? undefined\n\t\t\t\t: all\n\t\t},\n\t)\n}\n\n/**\n * Tests if a key pattern and a list of template tokens share a key. It walks\n * the pairs of places in the two lists, with a few characters that stand for\n * all others, so the answer is exact for these tokens.\n */\nconst tokensMeet = (\n\tglob: ReadonlyArray<GlobToken>,\n\ttemplate: ReadonlyArray<TemplateToken>,\n): boolean => {\n\tconst key = (t: number, g: number) => t * (glob.length + 1) + g\n\t// The places that a pair can reach with no character.\n\tconst closeOf = (\n\t\tt: number,\n\t\tg: number,\n\t): ReadonlyArray<readonly [number, number]> => [\n\t\t[t, g],\n\t\t...(template[t]?._tag === \"Any\" ? closeOf(t + 1, g) : []),\n\t\t...(glob[g]?._tag === \"Star\" ? closeOf(t, g + 1) : []),\n\t]\n\tconst alphabet = Arr.dedupe([\n\t\t\"a\",\n\t\t\"0\",\n\t\t...Arr.flatMap(glob, (token) =>\n\t\t\ttoken._tag === \"Char\" ? [token.char] : [],\n\t\t),\n\t\t...Arr.flatMap(template, (token) =>\n\t\t\ttoken._tag === \"Char\" ? [token.char] : [],\n\t\t),\n\t])\n\tconst stepTemplate = (t: number, char: string): ReadonlyArray<number> => {\n\t\tconst token = template[t]\n\t\treturn token === undefined\n\t\t\t? []\n\t\t\t: token._tag === \"Any\"\n\t\t\t\t? [t]\n\t\t\t\t: token.char === char\n\t\t\t\t\t? [t + 1]\n\t\t\t\t\t: []\n\t}\n\tconst stepGlob = (g: number, char: string): ReadonlyArray<number> => {\n\t\tconst token = glob[g]\n\t\treturn token === undefined\n\t\t\t? []\n\t\t\t: token._tag === \"Char\"\n\t\t\t\t? token.char === char\n\t\t\t\t\t? [g + 1]\n\t\t\t\t\t: []\n\t\t\t\t: char === \".\"\n\t\t\t\t\t? []\n\t\t\t\t\t: [g]\n\t}\n\t// A search over the pairs: each pair is seen one time.\n\tconst search = (\n\t\tfrontier: ReadonlyArray<readonly [number, number]>,\n\t\tseen: HashSet.HashSet<number>,\n\t): boolean => {\n\t\t// Each pair comes one time, also when many paths reach it, so the work\n\t\t// is at most the number of pairs.\n\t\tconst fresh = Array.from(\n\t\t\tHashMap.values(\n\t\t\t\tHashMap.fromIterable(\n\t\t\t\t\tArr.map(\n\t\t\t\t\t\tArr.filter(\n\t\t\t\t\t\t\tArr.flatMap(frontier, ([t, g]) => closeOf(t, g)),\n\t\t\t\t\t\t\t([t, g]) => !HashSet.has(seen, key(t, g)),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t(pair) => [key(pair[0], pair[1]), pair] as const,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\t)\n\t\tif (fresh.length === 0) {\n\t\t\treturn false\n\t\t}\n\t\tif (\n\t\t\tArr.some(fresh, ([t, g]) => t === template.length && g === glob.length)\n\t\t) {\n\t\t\treturn true\n\t\t}\n\t\tconst next = HashSet.union(\n\t\t\tseen,\n\t\t\tHashSet.fromIterable(Arr.map(fresh, ([t, g]) => key(t, g))),\n\t\t)\n\t\treturn search(\n\t\t\tArr.flatMap(fresh, ([t, g]) =>\n\t\t\t\tArr.flatMap(alphabet, (char) =>\n\t\t\t\t\tArr.flatMap(stepTemplate(t, char), (t2) =>\n\t\t\t\t\t\tArr.map(stepGlob(g, char), (g2) => [t2, g2] as const),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\t\tnext,\n\t\t)\n\t}\n\treturn search([[0, 0]], HashSet.empty())\n}\n\n/**\n * Tests if a key pattern fits a key of a template literal key Schema, or\n * `undefined` when the search is not exact for the Schema. The search calls\n * itself one time for each character of a key, so a very long part gives\n * `undefined` too.\n */\nconst globMeetsKeys = (\n\tpart: string,\n\tast: SchemaAST.AST,\n): boolean | undefined => {\n\tif (\n\t\tast._tag !== \"TemplateLiteral\" ||\n\t\t(ast.checks ?? []).length > 0 ||\n\t\tpart.length > maxExactKeyLength\n\t) {\n\t\treturn undefined\n\t}\n\tconst lists = templateTokens(ast)\n\tif (lists === undefined) {\n\t\treturn undefined\n\t}\n\tconst glob = Arr.map(\n\t\t(part.match(/\\*+|[^*]/gu) ?? []) as ReadonlyArray<string>,\n\t\t(token): GlobToken =>\n\t\t\ttoken.startsWith(\"*\") ? { _tag: \"Star\" } : { _tag: \"Char\", char: token },\n\t)\n\treturn Arr.some(lists, (list) => tokensMeet(glob, list))\n}\n\n/**\n * A few keys that a key Schema of a record takes: each part of a template\n * literal gives its literal, or a short text for a string or a number. These\n * are samples. A key that is not a sample may fit too, so a \"no\" from a test\n * with them is only \"not found\".\n */\nconst sampleKeys = (ast: SchemaAST.AST): ReadonlyArray<string> => {\n\tswitch (ast._tag) {\n\t\tcase \"String\":\n\t\t\treturn [\"\", \"a\"]\n\t\tcase \"Number\":\n\t\t\treturn [\"0\", \"1\"]\n\t\tcase \"Literal\":\n\t\t\treturn [String(ast.literal)]\n\t\tcase \"Union\":\n\t\t\treturn Arr.flatMap(ast.types, sampleKeys)\n\t\tcase \"TemplateLiteral\":\n\t\t\t// Each key of the parts before, with each key of this part. Two\n\t\t\t// samples for each part keep the list short.\n\t\t\treturn Arr.reduce(ast.parts, [\"\"], (keys: ReadonlyArray<string>, part) =>\n\t\t\t\tArr.take(\n\t\t\t\t\tArr.flatMap(keys, (key) =>\n\t\t\t\t\t\tArr.map(Arr.take(sampleKeys(part), 2), (end) => key + end),\n\t\t\t\t\t),\n\t\t\t\t\t64,\n\t\t\t\t),\n\t\t\t)\n\t\tdefault:\n\t\t\treturn []\n\t}\n}\n\n/**\n * Tests if a Schema surely has a value: each required field, at each depth,\n * has a type that has values, with no checks other than integer and finite\n * checks on numbers. A check such as a minimum length may stop every value,\n * and the library can not see that, so such a Schema gives `false`. So does a\n * required field that holds the struct itself again.\n *\n * @stability stable\n * @category predicates\n * @since 1.0.0\n */\nexport const hasValue = (schema: Schema.Top): boolean =>\n\tisSurelyInhabited(schema.ast, new Set())\n\nconst isSurelyInhabited = (\n\tast: SchemaAST.AST,\n\topen: ReadonlySet<SchemaAST.AST>,\n): boolean => {\n\tif (\n\t\tast._tag === \"Number\"\n\t\t\t? !hasOnlyKnownChecks(ast.checks)\n\t\t\t: (ast.checks ?? []).length > 0\n\t) {\n\t\treturn false\n\t}\n\tswitch (ast._tag) {\n\t\tcase \"Never\":\n\t\t\treturn false\n\t\tcase \"Objects\":\n\t\t\t// A named field must fit the record part too, as in\n\t\t\t// `Schema.StructWithRest`, and the two types may share no value. That\n\t\t\t// is not easy to know, so such a struct is not sure.\n\t\t\treturn (\n\t\t\t\t(ast.propertySignatures.length === 0 ||\n\t\t\t\t\tast.indexSignatures.length === 0) &&\n\t\t\t\tArr.every(\n\t\t\t\t\tast.propertySignatures,\n\t\t\t\t\t(property) =>\n\t\t\t\t\t\tSchemaAST.isOptional(property.type) ||\n\t\t\t\t\t\tisSurelyInhabited(property.type, open),\n\t\t\t\t)\n\t\t\t)\n\t\tcase \"Union\":\n\t\t\t// A union in the mode \"oneOf\" may stop every value of its members.\n\t\t\treturn (\n\t\t\t\tast.options?.mode !== \"oneOf\" &&\n\t\t\t\tArr.some(ast.types, (type) => isSurelyInhabited(type, open))\n\t\t\t)\n\t\tcase \"Suspend\":\n\t\t\treturn (\n\t\t\t\t!open.has(ast) &&\n\t\t\t\tisSurelyInhabited(ast.thunk(), new Set([...open, ast]))\n\t\t\t)\n\t\tcase \"Arrays\":\n\t\t\t// The elements that a tuple needs, and the elements after its rest.\n\t\t\t// The rest itself may be empty.\n\t\t\treturn Arr.every(\n\t\t\t\t[\n\t\t\t\t\t...Arr.filter(\n\t\t\t\t\t\tast.elements,\n\t\t\t\t\t\t(element) => !SchemaAST.isOptional(element),\n\t\t\t\t\t),\n\t\t\t\t\t...ast.rest.slice(1),\n\t\t\t\t],\n\t\t\t\t(element) => isSurelyInhabited(element, open),\n\t\t\t)\n\t\tcase \"Declaration\": {\n\t\t\tconst inner = classStruct(ast)\n\t\t\tif (inner !== undefined) {\n\t\t\t\treturn isSurelyInhabited(inner, open)\n\t\t\t}\n\t\t\tconst id = declarationId(ast)\n\t\t\t// A value of these holds a value of one of its type parameters.\n\t\t\tif (HashSet.has(wrapperDeclarations, id)) {\n\t\t\t\treturn Arr.some(ast.typeParameters, (type) =>\n\t\t\t\t\tisSurelyInhabited(type, open),\n\t\t\t\t)\n\t\t\t}\n\t\t\t// These have a value for any type parameters, such as an empty map\n\t\t\t// or `Option.none()`. Another declaration may take no value.\n\t\t\treturn HashSet.has(inhabitedDeclarations, id)\n\t\t}\n\t\tcase \"Enum\":\n\t\t\treturn ast.enums.length > 0\n\t\tcase \"TemplateLiteral\":\n\t\t\treturn Arr.every(ast.parts, (part) => isSurelyInhabited(part, open))\n\t\tcase \"String\":\n\t\tcase \"Number\":\n\t\tcase \"Boolean\":\n\t\tcase \"BigInt\":\n\t\tcase \"Symbol\":\n\t\tcase \"UniqueSymbol\":\n\t\tcase \"Literal\":\n\t\tcase \"Null\":\n\t\tcase \"Undefined\":\n\t\tcase \"Void\":\n\t\tcase \"Unknown\":\n\t\tcase \"Any\":\n\t\tcase \"ObjectKeyword\":\n\t\t\treturn true\n\t\tdefault:\n\t\t\t// A node that this walk does not know may take no value.\n\t\t\treturn false\n\t}\n}\n\n/** Declarations of Effect that hold a value of a type parameter. */\nconst wrapperDeclarations = HashSet.make(\n\t\"effect/schema/Redacted\",\n\t\"effect/schema/Result\",\n)\n\n/** Declarations of Effect that have a value for any type parameters. */\nconst inhabitedDeclarations = HashSet.make(\n\t\"effect/schema/Date\",\n\t\"effect/schema/URL\",\n\t\"effect/schema/Uint8Array\",\n\t\"effect/schema/Duration\",\n\t\"effect/schema/DateTimeUtc\",\n\t\"effect/schema/BigDecimal\",\n\t\"effect/schema/Cause\",\n\t\"effect/schema/Chunk\",\n\t\"effect/schema/HashMap\",\n\t\"effect/schema/HashSet\",\n\t\"effect/schema/ReadonlyMap\",\n\t\"effect/schema/ReadonlySet\",\n\t\"effect/schema/Option\",\n\t\"effect/schema/File\",\n\t\"effect/schema/FormData\",\n\t\"effect/schema/RegExp\",\n\t\"effect/schema/Json\",\n\t\"effect/schema/ByteSize\",\n\t\"effect/schema/DateTimeZoned\",\n\t\"effect/schema/Error\",\n\t\"effect/schema/Exit\",\n\t\"effect/schema/CauseReason\",\n\t\"effect/schema/Graph\",\n\t\"effect/schema/SemVer\",\n\t\"effect/schema/SemVerRange\",\n\t\"effect/schema/TimeZone\",\n\t\"effect/schema/TimeZoneNamed\",\n\t\"effect/schema/TimeZoneOffset\",\n\t\"effect/schema/URLSearchParams\",\n)\n\n/**\n * Tests if a Schema has no value at all: a required field of it, at some\n * depth, has no value, as `Schema.Never` has none. A required field that\n * holds the struct itself again, with no way to stop, has no finite value\n * either. Other checks, such as a minimum and a maximum that do not meet, are\n * not seen, so a \"no\" does not prove that the Schema has a value.\n *\n * @stability stable\n * @category predicates\n * @since 1.0.0\n */\nexport const hasNoValue = (schema: Schema.Top): boolean =>\n\tisEmptyType(schema.ast, new Set())\n\nconst isEmptyType = (\n\tast: SchemaAST.AST,\n\topen: ReadonlySet<SchemaAST.AST>,\n): boolean => {\n\tswitch (ast._tag) {\n\t\tcase \"Never\":\n\t\t\treturn true\n\t\tcase \"Objects\":\n\t\t\treturn Arr.some(\n\t\t\t\tast.propertySignatures,\n\t\t\t\t(property) =>\n\t\t\t\t\t!SchemaAST.isOptional(property.type) &&\n\t\t\t\t\tisEmptyType(property.type, open),\n\t\t\t)\n\t\tcase \"Union\":\n\t\t\treturn Arr.every(ast.types, (type) => isEmptyType(type, open))\n\t\tcase \"Suspend\":\n\t\t\t// A walk that comes back to a suspend node on required fields only\n\t\t\t// never stops, so such a value can not be made.\n\t\t\treturn open.has(ast) || isEmptyType(ast.thunk(), new Set([...open, ast]))\n\t\tcase \"Declaration\": {\n\t\t\tconst inner = classStruct(ast)\n\t\t\treturn inner !== undefined && isEmptyType(inner, open)\n\t\t}\n\t\tdefault:\n\t\t\treturn false\n\t}\n}\n\n/**\n * The values that one field of a resource may hold, as a condition sees them.\n * A missing field and `undefined` are `null`. The domain may be larger than\n * the real set of values: Schema checks other than finite and integer checks\n * are left out. A larger domain only makes a check say \"no\" more often.\n *\n * @stability stable\n * @category models\n * @since 1.0.0\n */\nexport interface FieldDomain {\n\t/** The field may be `null` or missing. */\n\treadonly null: boolean\n\t/** The field may hold a value with parts, or a value that is not a scalar. */\n\treadonly object: boolean\n\t/** The field may hold `true` and `false`. */\n\treadonly boolean: boolean\n\t/** The field may hold any string. */\n\treadonly string: boolean\n\t/** The numbers that the field may hold. */\n\treadonly number: \"none\" | \"integer\" | \"finite\" | \"any\"\n\t/** Single values that the field may hold, other than the ones above. */\n\treadonly literals: ReadonlyArray<string | number | boolean>\n}\n\nconst numberOrder = [\"none\", \"integer\", \"finite\", \"any\"] as const\n\nconst emptyDomain: FieldDomain = {\n\tnull: false,\n\tobject: false,\n\tboolean: false,\n\tstring: false,\n\tnumber: \"none\",\n\tliterals: [],\n}\n\nconst nullDomain: FieldDomain = { ...emptyDomain, null: true }\n\nconst objectDomain: FieldDomain = { ...emptyDomain, object: true }\n\n/**\n * The domain of a field with no Schema: any value.\n *\n * @stability stable\n * @category constants\n * @since 1.0.0\n */\nexport const anyDomain: FieldDomain = {\n\tnull: true,\n\tobject: true,\n\tboolean: true,\n\tstring: true,\n\tnumber: \"any\",\n\tliterals: [],\n}\n\nconst joinDomains = (domains: ReadonlyArray<FieldDomain>): FieldDomain =>\n\tdomains.reduce(\n\t\t(left, right) => ({\n\t\t\tnull: left.null || right.null,\n\t\t\tobject: left.object || right.object,\n\t\t\tboolean: left.boolean || right.boolean,\n\t\t\tstring: left.string || right.string,\n\t\t\tnumber:\n\t\t\t\tnumberOrder.indexOf(left.number) >= numberOrder.indexOf(right.number)\n\t\t\t\t\t? left.number\n\t\t\t\t\t: right.number,\n\t\t\tliterals: [...left.literals, ...right.literals],\n\t\t}),\n\t\temptyDomain,\n\t)\n\nconst hasCheck = (\n\tchecks: ReadonlyArray<SchemaAST.Check<never>>,\n\tid: string,\n): boolean =>\n\tchecks.some(\n\t\t(check) =>\n\t\t\tcheck.annotations?.representation?.id === id ||\n\t\t\t(check._tag === \"FilterGroup\" && hasCheck(check.checks, id)),\n\t)\n\n/**\n * The ids of the declarations of Effect that hold only values with parts.\n * Effect puts the id in the `representation` annotation. A declaration that\n * is not in this list may hold a scalar, as `Schema.Json` may.\n */\nconst objectDeclarations = HashSet.make(\n\t\"effect/schema/Date\",\n\t\"effect/schema/URL\",\n\t\"effect/schema/Uint8Array\",\n\t\"effect/schema/Duration\",\n\t\"effect/schema/DateTimeUtc\",\n\t\"effect/schema/BigDecimal\",\n\t\"effect/schema/Redacted\",\n\t\"effect/schema/Cause\",\n\t\"effect/schema/Chunk\",\n\t\"effect/schema/HashMap\",\n\t\"effect/schema/HashSet\",\n\t\"effect/schema/ReadonlyMap\",\n\t\"effect/schema/ReadonlySet\",\n\t\"effect/schema/Option\",\n\t\"effect/schema/Result\",\n\t\"effect/schema/File\",\n\t\"effect/schema/FormData\",\n\t\"effect/schema/RegExp\",\n)\n\nconst declarationId = (ast: SchemaAST.Declaration): string | undefined => {\n\tconst representation: unknown = ast.annotations?.[\"representation\"]\n\treturn hasProperty(representation, \"id\") &&\n\t\ttypeof representation.id === \"string\"\n\t\t? representation.id\n\t\t: undefined\n}\n\n/** The domain of the values of a Schema node. */\nconst domainOfType = (\n\tast: SchemaAST.AST,\n\topen: ReadonlySet<SchemaAST.AST>,\n): FieldDomain => {\n\tswitch (ast._tag) {\n\t\tcase \"Null\":\n\t\tcase \"Undefined\":\n\t\t\treturn nullDomain\n\t\tcase \"Never\":\n\t\t\treturn emptyDomain\n\t\t// `Schema.Void` takes any value, as `Schema.Unknown` does.\n\t\tcase \"Void\":\n\t\tcase \"Unknown\":\n\t\tcase \"Any\":\n\t\t\treturn anyDomain\n\t\tcase \"String\":\n\t\tcase \"TemplateLiteral\":\n\t\t\treturn { ...emptyDomain, string: true }\n\t\tcase \"Number\": {\n\t\t\tconst checks = ast.checks ?? []\n\t\t\treturn {\n\t\t\t\t...emptyDomain,\n\t\t\t\tnumber: hasCheck(checks, \"effect/schema/isInt\")\n\t\t\t\t\t? \"integer\"\n\t\t\t\t\t: hasCheck(checks, \"effect/schema/isFinite\")\n\t\t\t\t\t\t? \"finite\"\n\t\t\t\t\t\t: \"any\",\n\t\t\t}\n\t\t}\n\t\tcase \"Boolean\":\n\t\t\treturn { ...emptyDomain, boolean: true }\n\t\tcase \"Literal\":\n\t\t\treturn typeof ast.literal === \"bigint\"\n\t\t\t\t? objectDomain\n\t\t\t\t: { ...emptyDomain, literals: [ast.literal] }\n\t\tcase \"Enum\":\n\t\t\treturn { ...emptyDomain, literals: ast.enums.map(([, value]) => value) }\n\t\tcase \"Union\":\n\t\t\treturn joinDomains(ast.types.map((type) => domainOfType(type, open)))\n\t\tcase \"Suspend\":\n\t\t\treturn open.has(ast)\n\t\t\t\t? anyDomain\n\t\t\t\t: domainOfType(ast.thunk(), new Set([...open, ast]))\n\t\tcase \"Objects\":\n\t\t\t// A struct with no fields holds any value: Effect's\n\t\t\t// `Schema.Struct({})` takes a string too.\n\t\t\treturn ast.propertySignatures.length === 0 &&\n\t\t\t\tast.indexSignatures.length === 0\n\t\t\t\t? anyDomain\n\t\t\t\t: objectDomain\n\t\tcase \"Declaration\":\n\t\t\t// A class, and a declaration of Effect in `objectDeclarations`, holds\n\t\t\t// a value with parts. Another declaration may hold any value, as\n\t\t\t// `Schema.Json` or one from `Schema.declare` may, so its domain is all\n\t\t\t// values: a smaller domain could hide a value that a deny rule names.\n\t\t\treturn classStruct(ast) !== undefined ||\n\t\t\t\tHashSet.has(objectDeclarations, declarationId(ast))\n\t\t\t\t? objectDomain\n\t\t\t\t: anyDomain\n\t\tdefault:\n\t\t\treturn objectDomain\n\t}\n}\n\nconst domainAt = (\n\tast: SchemaAST.AST,\n\tnames: ReadonlyArray<string>,\n\tindex: number,\n\tmemo: PathMemo<FieldDomain>,\n): FieldDomain =>\n\t// A walk that comes back to a node at the same place may hold any value.\n\trememberAt(memo, ast, index, anyDomain, () => {\n\t\tif (index === names.length) {\n\t\t\treturn domainOfType(ast, new Set())\n\t\t}\n\t\tconst name = names[index]!\n\t\tswitch (ast._tag) {\n\t\t\tcase \"Objects\": {\n\t\t\t\tconst property = ast.propertySignatures.find(\n\t\t\t\t\t(signature) => signature.name === name,\n\t\t\t\t)\n\t\t\t\tif (property !== undefined) {\n\t\t\t\t\tconst inner = domainAt(property.type, names, index + 1, memo)\n\t\t\t\t\t// A field that may be missing may be `null`. So may a field with\n\t\t\t\t\t// a name of `Object.prototype`: a condition reads it only when a\n\t\t\t\t\t// value gives it another value.\n\t\t\t\t\treturn SchemaAST.isOptional(property.type) || name in Object.prototype\n\t\t\t\t\t\t? joinDomains([nullDomain, inner])\n\t\t\t\t\t\t: inner\n\t\t\t\t}\n\t\t\t\t// A name that the struct does not have may still be a field of a\n\t\t\t\t// value: a condition reads a field that a value has from its\n\t\t\t\t// class, such as a getter, and the Schema does not stop such a\n\t\t\t\t// field. A key of a record is not safe either: the Schema of a\n\t\t\t\t// record checks only the keys that a loop over the keys sees, and\n\t\t\t\t// a condition reads the others too. So such a field may hold any\n\t\t\t\t// value.\n\t\t\t\treturn anyDomain\n\t\t\t}\n\t\t\tcase \"Union\":\n\t\t\t\treturn joinDomains(\n\t\t\t\t\tast.types.map((type) => domainAt(type, names, index, memo)),\n\t\t\t\t)\n\t\t\tcase \"Suspend\":\n\t\t\t\treturn domainAt(ast.thunk(), names, index, memo)\n\t\t\tcase \"Declaration\": {\n\t\t\t\tconst inner = classStruct(ast)\n\t\t\t\treturn inner === undefined\n\t\t\t\t\t? anyDomain\n\t\t\t\t\t: domainAt(inner, names, index, memo)\n\t\t\t}\n\t\t\tcase \"Arrays\":\n\t\t\tcase \"ObjectKeyword\":\n\t\t\tcase \"Unknown\":\n\t\t\tcase \"Any\":\n\t\t\t\t// A path may go into these values, and the Schema does not say\n\t\t\t\t// what is there.\n\t\t\t\treturn anyDomain\n\t\t\tdefault:\n\t\t\t\t// A path does not go into a scalar, so the field is `null`.\n\t\t\t\treturn nullDomain\n\t\t}\n\t})\n\n/**\n * Gives the domain of a field of a Schema, by its path with dots. A path that\n * the Schema does not name gives `null`, as a condition reads such a field.\n *\n * @stability stable\n * @category getters\n * @since 1.0.0\n */\nexport const domainOf = (schema: Schema.Top, path: string): FieldDomain =>\n\t// No cache here: a search keeps the cells of each field for itself. A path\n\t// that is too long to walk may hold any value.\n\tisTooLong(path)\n\t\t? anyDomain\n\t\t: domainAt(schema.ast, path.split(\".\"), 0, new Map())\n\n/**\n * Checks the names of the top fields of a resource at once, when it is made.\n * The names of nested fields are checked when the descriptor is made.\n */\nconst checkFields = (\n\tkind: string,\n\toptions: Options<ReadonlyArray<string>, Schema.Struct.Fields>,\n): void => {\n\t// The kind of a value comes from its `_tag`. A field with this name could\n\t// give a value another kind, so it is a defect.\n\tif (Object.hasOwn(options.fields, \"_tag\")) {\n\t\tthrow new Error(`The resource \"${kind}\" may not have a field \"_tag\"`)\n\t}\n\tArr.map(Object.keys(options.fields), (name) => {\n\t\tif (name.includes(\".\")) {\n\t\t\tthrow new Error(`A field name may not have a dot: \"${name}\"`)\n\t\t}\n\t\tif (name === \"\") {\n\t\t\tthrow new Error(\"A field name may not be empty\")\n\t\t}\n\t})\n}\n\n/**\n * Gives a value that is made on first use, and then kept. The descriptor of a\n * resource reads its Schema, and a recursive Schema refers to the resource\n * class, so it can not be read while the class is made. The cell belongs to\n * one resource.\n */\nconst lazy = <A>(make: () => A): (() => A) => {\n\tconst cell: { value?: A } = {}\n\treturn () => {\n\t\tif (!(\"value\" in cell)) {\n\t\t\tcell.value = make()\n\t\t}\n\t\treturn cell.value as A\n\t}\n}\n\n/**\n * Checks each part of the path of a resource: a string, or a reference to a\n * top-level field of the resource. A reference to another field would read\n * nothing, and a rule on the path could then match a value by mistake.\n */\nconst checkPath = (\n\tkind: string,\n\tfields: Schema.Struct.Fields,\n\tpath: ReadonlyArray<unknown>,\n): ReadonlyArray<PathSegment> =>\n\t// `Array.from` gives `undefined` for a hole of a sparse array, so the check\n\t// sees each place.\n\tArr.map(Array.from(path), (segment): PathSegment => {\n\t\tif (typeof segment === \"string\") {\n\t\t\treturn segment\n\t\t}\n\t\tif (\n\t\t\thasProperty(segment, \"_tag\") &&\n\t\t\tsegment._tag === \"Field\" &&\n\t\t\thasProperty(segment, \"field\") &&\n\t\t\ttypeof segment.field === \"string\" &&\n\t\t\tObject.hasOwn(fields, segment.field)\n\t\t) {\n\t\t\treturn { _tag: \"Field\", field: segment.field }\n\t\t}\n\t\tthrow new globalThis.Error(\n\t\t\t`A part of the path of \"${kind}\" is not a string or a field of the resource`,\n\t\t)\n\t})\n\n/**\n * Copies the options of a resource. The descriptor is made later, when it is\n * first read, so a change to the objects of the caller before then must not\n * change it: the Schema of the values and the descriptor must agree.\n */\nconst snapshot = (\n\toptions: Options<ReadonlyArray<string>, Schema.Struct.Fields>,\n): Options<ReadonlyArray<string>, Schema.Struct.Fields> => ({\n\t...options,\n\tactions: [...options.actions],\n\tfields: { ...options.fields },\n})\n\nconst makeDescriptor = (\n\tkind: string,\n\toptions: Options<ReadonlyArray<string>, Schema.Struct.Fields>,\n): Descriptor => {\n\tconst refs: Record<string, FieldRef<string>> = Object.fromEntries(\n\t\tArr.map(Object.keys(options.fields), (key) => [\n\t\t\tkey,\n\t\t\t{ _tag: \"Field\", field: key },\n\t\t]),\n\t)\n\tconst visits = walkFields(Schema.Struct(options.fields).ast)\n\tconst leaves = Arr.filter(visits, (visit) => visit.leaf)\n\t// In a union, one path may hold a scalar in one branch and a struct in\n\t// another. Such a path holds more than one value, so it is open too.\n\tconst structs = HashSet.fromIterable(\n\t\tArr.map(\n\t\t\tArr.filter(visits, (visit) => !visit.leaf),\n\t\t\t(visit) => visit.path,\n\t\t),\n\t)\n\tconst open = Arr.filter(\n\t\tleaves,\n\t\t(visit) =>\n\t\t\tshapeOf(visit.type) !== \"scalar\" || HashSet.has(structs, visit.path),\n\t)\n\treturn new ResourceDescriptor({\n\t\tkind,\n\t\tactions: [...options.actions],\n\t\tpath:\n\t\t\toptions.path === undefined\n\t\t\t\t? undefined\n\t\t\t\t: checkPath(kind, options.fields, options.path(refs)),\n\t\tfieldPaths: Arr.dedupe(Arr.map(leaves, (visit) => visit.path)),\n\t\topenPaths: Arr.dedupe(Arr.map(open, (visit) => visit.path)),\n\t\tschema: Schema.TaggedStruct(kind, options.fields),\n\t})\n}\n\n/**\n * The type of a class made by {@link Class}.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport type Class<\n\tSelf,\n\tKind extends string,\n\tActions extends ReadonlyArray<string>,\n\tFields extends Schema.Struct.Fields,\n> = Schema.Class<Self, Schema.TaggedStruct<Kind, Fields>, {}> &\n\tResource<\n\t\tKind,\n\t\tActions[number],\n\t\tSchema.Struct.Type<Fields>,\n\t\tSelf & { readonly _tag: Kind }\n\t> & {\n\t\treadonly kind: Kind\n\t\treadonly actions: Actions\n\t}\n\n/**\n * Makes a resource as a Schema class. Use it in the same way as\n * `Schema.TaggedClass`.\n *\n * @example\n * ```ts\n * import { Schema } from \"effect\"\n * import { Resource } from \"@nmnmcc/ability\"\n *\n * class Document extends Resource.Class<Document>()(\"Document\", {\n * actions: [\"read\", \"update\"],\n * fields: {\n * id: Schema.String,\n * teamId: Schema.NullOr(Schema.String),\n * },\n * path: (f) => [\"team\", f.teamId, \"doc\", f.id],\n * }) {}\n *\n * const document = new Document({ id: \"d1\", teamId: \"t1\" })\n * ```\n *\n * @stability stable\n * @category constructors\n * @since 0.3.0\n */\nexport const Class: <Self = never>(\n\tidentifier?: string,\n) => <\n\tconst Kind extends string,\n\tconst Actions extends ReadonlyArray<string>,\n\tconst Fields extends Schema.Struct.Fields,\n>(\n\tkind: Kind,\n\toptions: Options<Actions, Fields>,\n) => [Self] extends [never]\n\t? \"Missing `Self` type: use Resource.Class<Self>()(...)\"\n\t: Class<Self, Kind, Actions, Fields> = ((identifier?: string) =>\n\t(\n\t\tkind: string,\n\t\tinput: Options<ReadonlyArray<string>, Schema.Struct.Fields>,\n\t) => {\n\t\tconst options = snapshot(input)\n\t\tcheckFields(kind, options)\n\t\tconst Base = Schema.TaggedClass<any>(identifier)(kind, options.fields)\n\t\tconst descriptor = lazy(() => makeDescriptor(kind, options))\n\t\treturn class extends Base {\n\t\t\tstatic get descriptor() {\n\t\t\t\treturn descriptor()\n\t\t\t}\n\t\t\tstatic readonly kind = kind\n\t\t\tstatic readonly actions = [...options.actions]\n\t\t}\n\t}) as never\n\n/**\n * A resource made by {@link make}. Its values are plain objects.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport interface Struct<\n\tKind extends string,\n\tActions extends ReadonlyArray<string>,\n\tFields extends Schema.Struct.Fields,\n> extends Resource<\n\tKind,\n\tActions[number],\n\tSchema.Struct.Type<Fields>,\n\tSchema.Struct.Type<Fields> & { readonly _tag: Kind }\n> {\n\treadonly kind: Kind\n\treadonly actions: Actions\n\treadonly schema: Schema.TaggedStruct<Kind, Fields>\n\t/** Makes a value. It puts the `_tag` field on the value for you. */\n\treadonly make: (\n\t\tinput: Schema.Struct.Type<Fields>,\n\t) => Schema.Struct.Type<Fields> & { readonly _tag: Kind }\n}\n\n/**\n * Makes a resource from plain fields. Its values are plain objects with a\n * `_tag` field.\n *\n * @stability stable\n * @category constructors\n * @since 0.3.0\n */\nexport const make: <\n\tconst Kind extends string,\n\tconst Actions extends ReadonlyArray<string>,\n\tconst Fields extends Schema.Struct.Fields,\n>(\n\tkind: Kind,\n\toptions: Options<Actions, Fields>,\n) => Struct<Kind, Actions, Fields> = ((\n\tkind: string,\n\tinput: Options<ReadonlyArray<string>, Schema.Struct.Fields>,\n) => {\n\tconst options = snapshot(input)\n\tcheckFields(kind, options)\n\tconst schema = Schema.TaggedStruct(kind, options.fields)\n\tconst descriptor = lazy(() => makeDescriptor(kind, options))\n\treturn {\n\t\tget descriptor() {\n\t\t\treturn descriptor()\n\t\t},\n\t\tkind,\n\t\tactions: [...options.actions],\n\t\tschema,\n\t\tmake: (input: object) => schema.make(input as never),\n\t}\n}) as never\n\n/**\n * Tests if a value is a resource.\n *\n * @stability stable\n * @category guards\n * @since 0.3.0\n */\nexport const isResource = (u: unknown): u is Any =>\n\thasProperty(u, \"descriptor\") && u.descriptor instanceof ResourceDescriptor\n\n/**\n * Gets the runtime data of a resource.\n *\n * @stability stable\n * @category getters\n * @since 0.3.0\n */\nexport const descriptor = (resource: Any): Descriptor => resource.descriptor\n\n/**\n * Gives the kind name of a resource value, from its `_tag` field.\n *\n * @stability stable\n * @category getters\n * @since 1.0.0\n */\nexport const kindOf = (value: unknown): string | undefined =>\n\thasProperty(value, \"_tag\") && typeof value._tag === \"string\"\n\t\t? value._tag\n\t\t: undefined\n"],"mappings":"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"}
1
+ {"version":3,"file":"Resource.js","names":["Internal.makeClass","Internal.makeStruct"],"sources":["../src/Resource.ts"],"sourcesContent":["/**\n * A resource is a kind of thing that a person may act on, such as a document\n * or an invoice. Each resource has a kind name, a list of actions, a Schema for its\n * data, and an optional path.\n *\n * Make a resource in one of two ways:\n * - {@link Class} makes a Schema class, in the same way as\n * `Schema.TaggedClass`. The class is a Schema, a constructor, and a resource\n * at the same time.\n * - {@link make} makes a resource from plain fields. Its values are plain\n * objects with a `_tag` field.\n *\n * Every value of a resource has a `_tag` field with the kind name. The library\n * uses this field to find the resource of a value. It does not guess from the\n * constructor name.\n *\n * A path puts a resource inside a tree, such as\n * `[\"org\", organizationId, \"team\", teamId, \"doc\", id]`. A condition can\n * then ask if a value is under a part of the tree. See `Condition.under`.\n *\n * @stability stable\n * @since 0.3.0\n */\nimport type * as Schema from \"effect/Schema\"\nimport type * as Catalog from \"./internal/catalog.ts\"\nimport * as Internal from \"./internal/resource.ts\"\n\n/**\n * One part of a resource path. A string is a fixed part. A field reference\n * takes the part from a field of the value.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport type PathSegment = string | FieldRef<string>\n\n/**\n * A reference to a top-level field of a resource, used in a path.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport interface FieldRef<Name extends string> {\n\treadonly _tag: \"Field\"\n\treadonly field: Name\n}\n\n/**\n * The runtime data of a resource.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport interface Descriptor {\n\treadonly kind: string\n\treadonly actions: ReadonlyArray<string>\n\treadonly path: ReadonlyArray<PathSegment> | undefined\n\t/** The catalog of the data fields of the values. */\n\treadonly catalog: Catalog.Catalog\n\t/**\n\t * A struct Schema of the data of the values, with the `_tag` field. It is a\n\t * struct also for a `Resource.Class`. The class Schema must not be read\n\t * before the class is made, because Effect then binds the class Schema to\n\t * the base class, and the values lose the getters of the class.\n\t */\n\treadonly schema: Schema.Top\n}\n\n/**\n * A resource. `Kind` is its name, `Action` is the union of its actions, `Data`\n * is the type of its Schema fields, and `Value` is the type of its values.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport interface Resource<\n\tKind extends string,\n\tAction extends string,\n\tData extends object,\n\tValue extends { readonly _tag: Kind },\n> {\n\treadonly descriptor: Descriptor\n\treadonly \"~Resource\"?: {\n\t\treadonly Kind: Kind\n\t\treadonly Action: Action\n\t\treadonly Data: Data\n\t\treadonly Value: Value\n\t}\n}\n\n/**\n * Any resource.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport type Any = Resource<string, string, object, { readonly _tag: string }>\n\n/**\n * The kind name of a resource.\n *\n * @stability stable\n * @category utility types\n * @since 0.3.0\n */\nexport type Kind<R> = R extends Resource<infer K, any, any, any> ? K : never\n\n/**\n * The actions of a resource.\n *\n * @stability stable\n * @category utility types\n * @since 0.3.0\n */\nexport type Action<R> = R extends Resource<any, infer A, any, any> ? A : never\n\n/**\n * The type of the Schema fields of a resource, without `_tag`.\n *\n * @stability stable\n * @category utility types\n * @since 0.3.0\n */\nexport type Data<R> = R extends Resource<any, any, infer D, any> ? D : never\n\n/**\n * The type of the values of a resource.\n *\n * @stability stable\n * @category utility types\n * @since 0.3.0\n */\nexport type Value<R> = R extends Resource<any, any, any, infer V> ? V : never\n\n/**\n * The options of a resource.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport interface Options<\n\tActions extends ReadonlyArray<string>,\n\tFields extends Schema.Struct.Fields,\n> {\n\treadonly actions: Actions\n\treadonly fields: Fields\n\t/**\n\t * Gives the path of the resource. The function gets one reference for each\n\t * top-level field.\n\t */\n\treadonly path?: (fields: {\n\t\treadonly [K in keyof Fields & string]: FieldRef<K>\n\t}) => ReadonlyArray<string | FieldRef<keyof Fields & string>>\n}\n\n/**\n * The type of a class made by {@link Class}.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport type Class<\n\tSelf,\n\tKind extends string,\n\tActions extends ReadonlyArray<string>,\n\tFields extends Schema.Struct.Fields,\n> = Schema.Class<Self, Schema.TaggedStruct<Kind, Fields>, {}> &\n\tResource<\n\t\tKind,\n\t\tActions[number],\n\t\tSchema.Struct.Type<Fields>,\n\t\tSelf & { readonly _tag: Kind }\n\t> & {\n\t\treadonly kind: Kind\n\t\treadonly actions: Actions\n\t}\n\n/**\n * Makes a resource as a Schema class. Use it in the same way as\n * `Schema.TaggedClass`.\n *\n * @example\n * ```ts\n * import { Schema } from \"effect\"\n * import { Resource } from \"@nmnmcc/ability\"\n *\n * class Document extends Resource.Class<Document>()(\"Document\", {\n * actions: [\"read\", \"update\"],\n * fields: {\n * id: Schema.String,\n * teamId: Schema.NullOr(Schema.String),\n * },\n * path: (f) => [\"team\", f.teamId, \"doc\", f.id],\n * }) {}\n *\n * const document = new Document({ id: \"d1\", teamId: \"t1\" })\n * ```\n *\n * @stability stable\n * @category constructors\n * @since 0.3.0\n */\nexport const Class: <Self = never>(\n\tidentifier?: string,\n) => <\n\tconst Kind extends string,\n\tconst Actions extends ReadonlyArray<string>,\n\tconst Fields extends Schema.Struct.Fields,\n>(\n\tkind: Kind,\n\toptions: Options<Actions, Fields>,\n) => [Self] extends [never]\n\t? \"Missing `Self` type: use Resource.Class<Self>()(...)\"\n\t: Class<Self, Kind, Actions, Fields> = Internal.makeClass as never\n\n/**\n * A resource made by {@link make}. Its values are plain objects.\n *\n * @stability stable\n * @category models\n * @since 0.3.0\n */\nexport interface Struct<\n\tKind extends string,\n\tActions extends ReadonlyArray<string>,\n\tFields extends Schema.Struct.Fields,\n> extends Resource<\n\tKind,\n\tActions[number],\n\tSchema.Struct.Type<Fields>,\n\tSchema.Struct.Type<Fields> & { readonly _tag: Kind }\n> {\n\treadonly kind: Kind\n\treadonly actions: Actions\n\treadonly schema: Schema.TaggedStruct<Kind, Fields>\n\t/** Makes a value. It puts the `_tag` field on the value for you. */\n\treadonly make: (\n\t\tinput: Schema.Struct.Type<Fields>,\n\t) => Schema.Struct.Type<Fields> & { readonly _tag: Kind }\n}\n\n/**\n * Makes a resource from plain fields. Its values are plain objects with a\n * `_tag` field.\n *\n * @stability stable\n * @category constructors\n * @since 0.3.0\n */\nexport const make: <\n\tconst Kind extends string,\n\tconst Actions extends ReadonlyArray<string>,\n\tconst Fields extends Schema.Struct.Fields,\n>(\n\tkind: Kind,\n\toptions: Options<Actions, Fields>,\n) => Struct<Kind, Actions, Fields> = Internal.makeStruct as never\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiNA,MAAa,QAW2BA;;;;;;;;;AAoCxC,MAAa,OAOwBC"}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,8 @@
1
1
  import { Resource_d_exports } from "./Resource.js";
2
2
  import { Condition_d_exports } from "./Condition.js";
3
- import { Principal_d_exports } from "./Principal.js";
4
3
  import { Domain_d_exports } from "./Domain.js";
5
- import { Rule_d_exports } from "./Rule.js";
6
- import { Decision_d_exports } from "./Decision.js";
7
4
  import { Policy_d_exports } from "./Policy.js";
5
+ import { Decision_d_exports } from "./Decision.js";
8
6
  import { Authorizer_d_exports } from "./Authorizer.js";
9
- export { Authorizer_d_exports as Authorizer, Condition_d_exports as Condition, Decision_d_exports as Decision, Domain_d_exports as Domain, Policy_d_exports as Policy, Principal_d_exports as Principal, Resource_d_exports as Resource, Rule_d_exports as Rule };
7
+ import { Limits_d_exports } from "./Limits.js";
8
+ export { Authorizer_d_exports as Authorizer, Condition_d_exports as Condition, Decision_d_exports as Decision, Domain_d_exports as Domain, Limits_d_exports as Limits, Policy_d_exports as Policy, Resource_d_exports as Resource };
package/dist/index.js CHANGED
@@ -1,9 +1,8 @@
1
+ import { Decision_exports } from "./Decision.js";
1
2
  import { Resource_exports } from "./Resource.js";
2
3
  import { Condition_exports } from "./Condition.js";
3
- import { Decision_exports } from "./Decision.js";
4
+ import { Authorizer_exports } from "./Authorizer.js";
4
5
  import { Domain_exports } from "./Domain.js";
5
- import { Rule_exports } from "./Rule.js";
6
+ import { Limits_exports } from "./Limits.js";
6
7
  import { Policy_exports } from "./Policy.js";
7
- import { Authorizer_exports } from "./Authorizer.js";
8
- import { Principal_exports } from "./Principal.js";
9
- export { Authorizer_exports as Authorizer, Condition_exports as Condition, Decision_exports as Decision, Domain_exports as Domain, Policy_exports as Policy, Principal_exports as Principal, Resource_exports as Resource, Rule_exports as Rule };
8
+ export { Authorizer_exports as Authorizer, Condition_exports as Condition, Decision_exports as Decision, Domain_exports as Domain, Limits_exports as Limits, Policy_exports as Policy, Resource_exports as Resource };
@@ -0,0 +1,267 @@
1
+ import { And, Compare, In, Not, Or, Predicate, isScalar, literal, nodes_exports, runOf } from "./nodes.js";
2
+ import { readPath } from "./read.js";
3
+ import * as Effect from "effect/Effect";
4
+ import * as Arr from "effect/Array";
5
+ import * as HashSet from "effect/HashSet";
6
+ import * as Option from "effect/Option";
7
+ // src/internal/algebra.ts
8
+ /**
9
+ * The work on condition nodes: smart constructors, simplification, the step
10
+ * that puts the principal in, tests on a value, and folds.
11
+ *
12
+ * The constructors of the nodes keep each condition small and low, so each
13
+ * walk here is a plain walk with no memo. A shared child is walked again for
14
+ * each place, and the limits of the nodes keep that work small.
15
+ */
16
+ const { always, never } = nodes_exports;
17
+ /**
18
+ * Keeps the first node of each structure, in order. A node with a predicate is
19
+ * equal only to itself, as its test is a function.
20
+ */
21
+ const dedupe = (nodes) => Arr.flatten(Arr.mapAccum(nodes, HashSet.empty(), (seen, node) => [HashSet.add(seen, node), HashSet.has(seen, node) ? [] : [node]])[1]);
22
+ /**
23
+ * Removes the children that the other children make useless. In an `Or`,
24
+ * `a OR (a AND b)` is `a`. In an `And`, `a AND (a OR b)` is `a`.
25
+ */
26
+ const absorb = (inner, nodes) => {
27
+ const all = HashSet.fromIterable(nodes);
28
+ return Arr.filter(nodes, (node) => node._tag !== inner || !Arr.some(node.conditions, (part) => HashSet.has(all, part)));
29
+ };
30
+ /**
31
+ * Gives the result of an `And` with a `False` child, or of an `Or` with a
32
+ * `True` child. The children are tested in order, so a predicate before the
33
+ * constant still runs, and it may fail. When there is such a predicate, the
34
+ * children before the constant stay, so the failure is not lost.
35
+ */
36
+ const shortCircuit = (tag, children, index) => {
37
+ const constant = tag === "And" ? never : always;
38
+ const neutral = tag === "And" ? "True" : "False";
39
+ const before = Arr.filter(Arr.take(children, index), (child) => child._tag !== neutral);
40
+ if (!Arr.some(before, (child) => child.opaque)) return constant;
41
+ return tag === "And" ? new And([...before, constant]) : new Or([...before, constant]);
42
+ };
43
+ /**
44
+ * Makes an `And` or an `Or` of simple children, and makes it simple. It looks
45
+ * one level down only:
46
+ * - it puts the children of a child of the same kind into the node;
47
+ * - it stops at a `False` in an `And`, or at a `True` in an `Or`;
48
+ * - it removes `True` from an `And`, `False` from an `Or`, copies, and the
49
+ * children that other children make useless.
50
+ *
51
+ * A predicate may fail, and it may give another answer when it runs again. So
52
+ * when a child has a predicate, the children stay as they are, and each one
53
+ * runs in its place. A child with a predicate is not put into the node either.
54
+ */
55
+ const junction = (tag, children) => {
56
+ const constant = tag === "And" ? "False" : "True";
57
+ const neutral = tag === "And" ? "True" : "False";
58
+ const flat = Arr.flatMap(children, (child) => child._tag === tag && !child.opaque ? child.conditions : [child]);
59
+ return Option.match(Arr.findFirstIndex(flat, (child) => child._tag === constant), {
60
+ onSome: (stop) => shortCircuit(tag, flat, stop),
61
+ onNone: () => {
62
+ const kept = Arr.filter(flat, (child) => child._tag !== neutral);
63
+ const unique = Arr.some(kept, (child) => child.opaque) ? kept : absorb(tag === "And" ? "Or" : "And", dedupe(kept));
64
+ return unique.length === 0 ? tag === "And" ? always : never : unique.length === 1 ? unique[0] : tag === "And" ? new And(unique) : new Or(unique);
65
+ }
66
+ });
67
+ };
68
+ /** An `And` of simple children, made simple. */
69
+ const and = (children) => junction("And", children);
70
+ /** An `Or` of simple children, made simple. */
71
+ const or = (children) => junction("Or", children);
72
+ /** A `Not` of a simple child, made simple. */
73
+ const not = (child) => {
74
+ switch (child._tag) {
75
+ case "True": return never;
76
+ case "False": return always;
77
+ case "Not": return child.condition;
78
+ case "Compare": return child.value._tag === "Literal" && (child.op === "eq" || child.op === "ne") ? new Compare({
79
+ op: child.op === "eq" ? "ne" : "eq",
80
+ field: child.field,
81
+ value: child.value
82
+ }) : new Not(child);
83
+ default: return new Not(child);
84
+ }
85
+ };
86
+ /** Makes a condition simple, from its leaves up. */
87
+ const simplify = (node) => {
88
+ switch (node._tag) {
89
+ case "And":
90
+ case "Or": return junction(node._tag, Arr.map(node.conditions, simplify));
91
+ case "Not": return node.condition.pipe(simplify, not);
92
+ case "In": return node.values.length === 0 ? never : node;
93
+ default: return node;
94
+ }
95
+ };
96
+ /**
97
+ * Gets a field of a value by a path with dots. It reads only plain data: see
98
+ * `readPart`. A missing field, or a field under a value that is not an object,
99
+ * gives `null`.
100
+ */
101
+ const getField = (value, path) => readPath(value, path.split("."));
102
+ /**
103
+ * Gives the value of an operand. A principal field that is `null`, missing, or
104
+ * not a scalar gives `undefined`. No field of a resource is `undefined`, so a
105
+ * test with it is never true. This keeps the check closed: a principal with no
106
+ * id never matches a resource with no owner.
107
+ */
108
+ const resolve = (operand, principal) => {
109
+ if (operand._tag === "Literal") return operand.value;
110
+ const value = getField(principal, operand.path);
111
+ return value !== null && isScalar(value) ? value : void 0;
112
+ };
113
+ const testCompare = (op, left, right) => {
114
+ if (right === void 0) return false;
115
+ switch (op) {
116
+ case "eq": return left === right;
117
+ case "ne": return left !== right;
118
+ default: {
119
+ if (!(typeof left === "number" && typeof right === "number" || typeof left === "string" && typeof right === "string")) return false;
120
+ const a = left;
121
+ const b = right;
122
+ switch (op) {
123
+ case "lt": return a < b;
124
+ case "lte": return a <= b;
125
+ case "gt": return a > b;
126
+ case "gte": return a >= b;
127
+ }
128
+ }
129
+ }
130
+ };
131
+ /** Gives the values of the path of a resource, or `undefined` for no path. */
132
+ const pathValues = (value, path) => path?.map((segment) => typeof segment === "string" ? segment : getField(value, segment.field));
133
+ const testUnder = (prefix, input) => {
134
+ const values = pathValues(input.value, input.path);
135
+ if (values === void 0 || prefix.length > values.length) return false;
136
+ return prefix.every((operand, index) => {
137
+ const value = resolve(operand, input.principal);
138
+ return value !== void 0 && value === values[index];
139
+ });
140
+ };
141
+ /** Tests a condition with no predicate on a value. */
142
+ const evaluateSync = (node, input) => {
143
+ switch (node._tag) {
144
+ case "True": return true;
145
+ case "False": return false;
146
+ case "Compare": return testCompare(node.op, getField(input.value, node.field), resolve(node.value, input.principal));
147
+ case "In": {
148
+ const field = getField(input.value, node.field);
149
+ return node.values.some((operand) => resolve(operand, input.principal) === field);
150
+ }
151
+ case "Exists": return getField(input.value, node.field) !== null;
152
+ case "Under": return testUnder(node.prefix, input);
153
+ case "And": return Arr.every(node.conditions, (child) => evaluateSync(child, input));
154
+ case "Or": return Arr.some(node.conditions, (child) => evaluateSync(child, input));
155
+ case "Not": return !evaluateSync(node.condition, input);
156
+ case "Predicate": throw new Error(`The predicate "${node.name}" needs an Effect. Use Condition.evaluate.`);
157
+ }
158
+ };
159
+ /**
160
+ * Tests a condition on a value. The children of `And` and `Or` run in order,
161
+ * and they stop at the first child that gives the answer.
162
+ */
163
+ const evaluate = (node, input) => {
164
+ if (!node.opaque) return Effect.sync(() => evaluateSync(node, input));
165
+ switch (node._tag) {
166
+ case "Predicate": return runOf(node)(input.value, input.principal);
167
+ case "Not": return Effect.map(evaluate(node.condition, input), (value) => !value);
168
+ case "And": return Effect.map(Effect.findFirst(node.conditions, (child) => Effect.map(evaluate(child, input), (value) => !value)), Option.isNone);
169
+ case "Or": return Effect.map(Effect.findFirst(node.conditions, (child) => evaluate(child, input)), Option.isSome);
170
+ default: return Effect.sync(() => evaluateSync(node, input));
171
+ }
172
+ };
173
+ /**
174
+ * Puts the value of the principal into an operand. It gives `undefined` for a
175
+ * principal field with no value. See {@link resolve}.
176
+ */
177
+ const bindOperand = (operand, principal) => {
178
+ if (operand._tag === "Literal") return operand;
179
+ const value = resolve(operand, principal);
180
+ return value === void 0 ? void 0 : literal(value);
181
+ };
182
+ const expandUnder = (prefix, principal, path) => {
183
+ if (path === void 0 || prefix.length > path.length) return never;
184
+ return and(Arr.map(prefix, (operand, index) => {
185
+ const value = resolve(operand, principal);
186
+ const segment = path[index];
187
+ return value === void 0 ? never : typeof segment === "string" ? segment === value ? always : never : new Compare({
188
+ op: "eq",
189
+ field: segment.field,
190
+ value: literal(value)
191
+ });
192
+ }));
193
+ };
194
+ /**
195
+ * Puts the principal into a condition and expands `Under` with the path of the
196
+ * resource. The result is simple. It has no principal fields and no `Under`
197
+ * nodes. A predicate keeps the principal.
198
+ */
199
+ const partial = (node, input) => {
200
+ const bind = (current) => {
201
+ switch (current._tag) {
202
+ case "Compare": {
203
+ const value = bindOperand(current.value, input.principal);
204
+ return value === void 0 ? never : value === current.value ? current : new Compare({
205
+ op: current.op,
206
+ field: current.field,
207
+ value
208
+ });
209
+ }
210
+ case "In": {
211
+ const values = Arr.flatMap(current.values, (operand) => Option.toArray(Option.fromUndefinedOr(bindOperand(operand, input.principal))));
212
+ return values.length === 0 ? never : new In({
213
+ field: current.field,
214
+ values
215
+ });
216
+ }
217
+ case "Under": return expandUnder(current.prefix, input.principal, input.path);
218
+ case "And": return and(Arr.map(current.conditions, bind));
219
+ case "Or": return or(Arr.map(current.conditions, bind));
220
+ case "Not": return current.condition.pipe(bind, not);
221
+ case "Predicate": {
222
+ const run = runOf(current);
223
+ return new Predicate({
224
+ name: current.name,
225
+ run: (value) => run(value, input.principal)
226
+ });
227
+ }
228
+ default: return current;
229
+ }
230
+ };
231
+ return bind(node);
232
+ };
233
+ /** Gives the services in `context` to every predicate of a condition. */
234
+ const provide = (node, context) => {
235
+ if (!node.opaque) return node;
236
+ switch (node._tag) {
237
+ case "Predicate": {
238
+ const run = runOf(node);
239
+ return new Predicate({
240
+ name: node.name,
241
+ run: (value, principal) => Effect.provideContext(run(value, principal), context)
242
+ });
243
+ }
244
+ case "And": return new And(Arr.map(node.conditions, (child) => provide(child, context)));
245
+ case "Or": return new Or(Arr.map(node.conditions, (child) => provide(child, context)));
246
+ case "Not": return new Not(provide(node.condition, context));
247
+ default: return node;
248
+ }
249
+ };
250
+ /** The fields that a condition tests, in the order that they first come. */
251
+ const fields = (node) => {
252
+ const all = (current) => {
253
+ switch (current._tag) {
254
+ case "Compare":
255
+ case "In":
256
+ case "Exists": return [current.field];
257
+ case "And":
258
+ case "Or": return Arr.flatMap(current.conditions, all);
259
+ case "Not": return all(current.condition);
260
+ default: return [];
261
+ }
262
+ };
263
+ return Arr.flatten(Arr.mapAccum(all(node), HashSet.empty(), (seen, field) => [HashSet.add(seen, field), HashSet.has(seen, field) ? [] : [field]])[1]);
264
+ };
265
+ export { and, evaluate, evaluateSync, fields, not, or, partial, provide, simplify, testCompare };
266
+
267
+ //# sourceMappingURL=algebra.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"algebra.js","names":["Nodes","Nodes.And","Nodes.Or","Nodes.Compare","Nodes.Not","Nodes.isScalar","Nodes.runOf","Nodes.literal","Nodes.In","Nodes.Predicate"],"sources":["../../src/internal/algebra.ts"],"sourcesContent":["/**\n * The work on condition nodes: smart constructors, simplification, the step\n * that puts the principal in, tests on a value, and folds.\n *\n * The constructors of the nodes keep each condition small and low, so each\n * walk here is a plain walk with no memo. A shared child is walked again for\n * each place, and the limits of the nodes keep that work small.\n */\n// A predicate gives an Effect with an error type and a service type that this\n// code does not know, so they are `unknown` here.\n// @effect-diagnostics anyUnknownInErrorContext:off\nimport * as Arr from \"effect/Array\"\nimport type * as Context from \"effect/Context\"\nimport * as Effect from \"effect/Effect\"\nimport * as HashSet from \"effect/HashSet\"\nimport * as Option from \"effect/Option\"\nimport type * as Resource from \"../Resource.ts\"\nimport * as Nodes from \"./nodes.ts\"\nimport { readPath } from \"./read.ts\"\n\ntype Node = Nodes.Node\n\nconst { always, never } = Nodes\n\n// Smart constructors\n\n/**\n * Keeps the first node of each structure, in order. A node with a predicate is\n * equal only to itself, as its test is a function.\n */\nconst dedupe = (nodes: ReadonlyArray<Node>): ReadonlyArray<Node> =>\n\tArr.flatten(\n\t\tArr.mapAccum(nodes, HashSet.empty<Node>(), (seen, node) => [\n\t\t\tHashSet.add(seen, node),\n\t\t\tHashSet.has(seen, node) ? [] : [node],\n\t\t])[1],\n\t)\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\tnodes: ReadonlyArray<Node>,\n): ReadonlyArray<Node> => {\n\tconst all = HashSet.fromIterable(nodes)\n\treturn Arr.filter(\n\t\tnodes,\n\t\t(node) =>\n\t\t\tnode._tag !== inner ||\n\t\t\t!Arr.some(node.conditions, (part) => HashSet.has(all, part)),\n\t)\n}\n\n/**\n * Gives the result of an `And` with a `False` child, or of an `Or` with a\n * `True` child. The children are tested in order, so a predicate before the\n * constant still runs, and it may fail. When there is such a predicate, the\n * children before the constant stay, so the failure is not lost.\n */\nconst shortCircuit = (\n\ttag: \"And\" | \"Or\",\n\tchildren: ReadonlyArray<Node>,\n\tindex: number,\n): Node => {\n\tconst constant = tag === \"And\" ? never : always\n\tconst neutral = tag === \"And\" ? \"True\" : \"False\"\n\tconst before = Arr.filter(\n\t\tArr.take(children, index),\n\t\t(child) => child._tag !== neutral,\n\t)\n\tif (!Arr.some(before, (child) => child.opaque)) {\n\t\treturn constant\n\t}\n\treturn tag === \"And\"\n\t\t? new Nodes.And([...before, constant])\n\t\t: new Nodes.Or([...before, constant])\n}\n\n/**\n * Makes an `And` or an `Or` of simple children, and makes it simple. It looks\n * one level down only:\n * - it puts the children of a child of the same kind into the node;\n * - it stops at a `False` in an `And`, or at a `True` in an `Or`;\n * - it removes `True` from an `And`, `False` from an `Or`, copies, and the\n * children that other children make useless.\n *\n * A predicate may fail, and it may give another answer when it runs again. So\n * when a child has a predicate, the children stay as they are, and each one\n * runs in its place. A child with a predicate is not put into the node either.\n */\nconst junction = (tag: \"And\" | \"Or\", children: ReadonlyArray<Node>): Node => {\n\tconst constant = tag === \"And\" ? \"False\" : \"True\"\n\tconst neutral = tag === \"And\" ? \"True\" : \"False\"\n\tconst flat = Arr.flatMap(children, (child) =>\n\t\tchild._tag === tag && !child.opaque ? child.conditions : [child],\n\t)\n\treturn Option.match(\n\t\tArr.findFirstIndex(flat, (child) => child._tag === constant),\n\t\t{\n\t\t\tonSome: (stop) => shortCircuit(tag, flat, stop),\n\t\t\tonNone: () => {\n\t\t\t\tconst kept = Arr.filter(flat, (child) => child._tag !== neutral)\n\t\t\t\tconst unique = Arr.some(kept, (child) => child.opaque)\n\t\t\t\t\t? kept\n\t\t\t\t\t: absorb(tag === \"And\" ? \"Or\" : \"And\", dedupe(kept))\n\t\t\t\treturn unique.length === 0\n\t\t\t\t\t? tag === \"And\"\n\t\t\t\t\t\t? always\n\t\t\t\t\t\t: never\n\t\t\t\t\t: unique.length === 1\n\t\t\t\t\t\t? unique[0]!\n\t\t\t\t\t\t: tag === \"And\"\n\t\t\t\t\t\t\t? new Nodes.And(unique)\n\t\t\t\t\t\t\t: new Nodes.Or(unique)\n\t\t\t},\n\t\t},\n\t)\n}\n\n/** An `And` of simple children, made simple. */\nexport const and = (children: ReadonlyArray<Node>): Node =>\n\tjunction(\"And\", children)\n\n/** An `Or` of simple children, made simple. */\nexport const or = (children: ReadonlyArray<Node>): Node =>\n\tjunction(\"Or\", children)\n\n/** A `Not` of a simple child, made simple. */\nexport const not = (child: Node): Node => {\n\tswitch (child._tag) {\n\t\tcase \"True\":\n\t\t\treturn never\n\t\tcase \"False\":\n\t\t\treturn always\n\t\tcase \"Not\":\n\t\t\treturn child.condition\n\t\tcase \"Compare\":\n\t\t\t// A principal field with no value makes `eq` and `ne` both false, so\n\t\t\t// only a fixed value lets `not eq` become `ne`.\n\t\t\treturn child.value._tag === \"Literal\" &&\n\t\t\t\t(child.op === \"eq\" || child.op === \"ne\")\n\t\t\t\t? new Nodes.Compare({\n\t\t\t\t\t\top: child.op === \"eq\" ? \"ne\" : \"eq\",\n\t\t\t\t\t\tfield: child.field,\n\t\t\t\t\t\tvalue: child.value,\n\t\t\t\t\t})\n\t\t\t\t: new Nodes.Not(child)\n\t\tdefault:\n\t\t\treturn new Nodes.Not(child)\n\t}\n}\n\n/** Makes a condition simple, from its leaves up. */\nexport const simplify = (node: Node): Node => {\n\tswitch (node._tag) {\n\t\tcase \"And\":\n\t\tcase \"Or\":\n\t\t\treturn junction(node._tag, Arr.map(node.conditions, simplify))\n\t\tcase \"Not\":\n\t\t\treturn node.condition.pipe(simplify, not)\n\t\tcase \"In\":\n\t\t\treturn node.values.length === 0 ? never : node\n\t\tdefault:\n\t\t\treturn node\n\t}\n}\n\n// Tests on a value\n\n/** The data that a condition needs for a test. */\nexport interface Input {\n\treadonly value: object\n\treadonly principal?: object | undefined\n\treadonly path?: ReadonlyArray<Resource.PathSegment> | undefined\n}\n\n/**\n * Gets a field of a value by a path with dots. It reads only plain data: see\n * `readPart`. A missing field, or a field under a value that is not an object,\n * gives `null`.\n */\nconst getField = (value: unknown, path: string): unknown =>\n\treadPath(value, path.split(\".\"))\n\n/**\n * Gives the value of an operand. A principal field that is `null`, missing, or\n * not a scalar gives `undefined`. No field of a resource is `undefined`, so a\n * test with it is never true. This keeps the check closed: a principal with no\n * id never matches a resource with no owner.\n */\nconst resolve = (operand: Nodes.Operand, principal: unknown): unknown => {\n\tif (operand._tag === \"Literal\") {\n\t\treturn operand.value\n\t}\n\tconst value = getField(principal, operand.path)\n\treturn value !== null && Nodes.isScalar(value) ? value : undefined\n}\n\nexport const testCompare = (\n\top: Nodes.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/** Gives the values of the path of a resource, or `undefined` for no path. */\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<Nodes.Operand>,\n\tinput: 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\t// An operand with no value never matches, also a hole in a path that gives\n\t// `undefined` too.\n\treturn prefix.every((operand, index) => {\n\t\tconst value = resolve(operand, input.principal)\n\t\treturn value !== undefined && value === values[index]\n\t})\n}\n\n/** Tests a condition with no predicate on a value. */\nexport const evaluateSync = (node: Node, input: Input): boolean => {\n\tswitch (node._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\tnode.op,\n\t\t\t\tgetField(input.value, node.field),\n\t\t\t\tresolve(node.value, input.principal),\n\t\t\t)\n\t\tcase \"In\": {\n\t\t\tconst field = getField(input.value, node.field)\n\t\t\treturn node.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, node.field) !== null\n\t\tcase \"Under\":\n\t\t\treturn testUnder(node.prefix, input)\n\t\tcase \"And\":\n\t\t\treturn Arr.every(node.conditions, (child) => evaluateSync(child, input))\n\t\tcase \"Or\":\n\t\t\treturn Arr.some(node.conditions, (child) => evaluateSync(child, input))\n\t\tcase \"Not\":\n\t\t\treturn !evaluateSync(node.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 \"${node.name}\" needs an Effect. Use Condition.evaluate.`,\n\t\t\t)\n\t}\n}\n\n/**\n * Tests a condition on a value. The children of `And` and `Or` run in order,\n * and they stop at the first child that gives the answer.\n */\nexport const evaluate = (\n\tnode: Node,\n\tinput: Input,\n): Effect.Effect<boolean, unknown, unknown> => {\n\tif (!node.opaque) {\n\t\treturn Effect.sync(() => evaluateSync(node, input))\n\t}\n\tswitch (node._tag) {\n\t\tcase \"Predicate\":\n\t\t\treturn Nodes.runOf(node)(input.value, input.principal)\n\t\tcase \"Not\":\n\t\t\treturn Effect.map(evaluate(node.condition, input), (value) => !value)\n\t\tcase \"And\":\n\t\t\treturn Effect.map(\n\t\t\t\tEffect.findFirst(node.conditions, (child) =>\n\t\t\t\t\tEffect.map(evaluate(child, input), (value) => !value),\n\t\t\t\t),\n\t\t\t\tOption.isNone,\n\t\t\t)\n\t\tcase \"Or\":\n\t\t\treturn Effect.map(\n\t\t\t\tEffect.findFirst(node.conditions, (child) => evaluate(child, input)),\n\t\t\t\tOption.isSome,\n\t\t\t)\n\t\tdefault:\n\t\t\treturn Effect.sync(() => evaluateSync(node, input))\n\t}\n}\n\n// The principal and the path\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: Nodes.Operand,\n\tprincipal: unknown,\n): Nodes.Literal | undefined => {\n\tif (operand._tag === \"Literal\") {\n\t\treturn operand\n\t}\n\tconst value = resolve(operand, principal)\n\treturn value === undefined ? undefined : Nodes.literal(value as Nodes.Scalar)\n}\n\nconst expandUnder = (\n\tprefix: ReadonlyArray<Nodes.Operand>,\n\tprincipal: unknown,\n\tpath: ReadonlyArray<Resource.PathSegment> | undefined,\n): Node => {\n\tif (path === undefined || prefix.length > path.length) {\n\t\treturn never\n\t}\n\treturn and(\n\t\tArr.map(prefix, (operand, index): Node => {\n\t\t\tconst value = resolve(operand, principal)\n\t\t\tconst segment = path[index]!\n\t\t\treturn value === undefined\n\t\t\t\t? never\n\t\t\t\t: typeof segment === \"string\"\n\t\t\t\t\t? segment === value\n\t\t\t\t\t\t? always\n\t\t\t\t\t\t: never\n\t\t\t\t\t: new Nodes.Compare({\n\t\t\t\t\t\t\top: \"eq\",\n\t\t\t\t\t\t\tfield: segment.field,\n\t\t\t\t\t\t\tvalue: Nodes.literal(value as Nodes.Scalar),\n\t\t\t\t\t\t})\n\t\t}),\n\t)\n}\n\n/** The principal and the path of the resource, for {@link partial}. */\nexport interface PartialInput {\n\treadonly principal?: object | undefined\n\treadonly path?: ReadonlyArray<Resource.PathSegment> | undefined\n}\n\n/**\n * Puts the principal into a condition and expands `Under` with the path of the\n * resource. The result is simple. It has no principal fields and no `Under`\n * nodes. A predicate keeps the principal.\n */\nexport const partial = (node: Node, input: PartialInput): Node => {\n\tconst bind = (current: Node): Node => {\n\t\tswitch (current._tag) {\n\t\t\tcase \"Compare\": {\n\t\t\t\tconst value = bindOperand(current.value, input.principal)\n\t\t\t\treturn value === undefined\n\t\t\t\t\t? never\n\t\t\t\t\t: value === current.value\n\t\t\t\t\t\t? current\n\t\t\t\t\t\t: new Nodes.Compare({ op: current.op, field: current.field, value })\n\t\t\t}\n\t\t\tcase \"In\": {\n\t\t\t\tconst values = Arr.flatMap(current.values, (operand) =>\n\t\t\t\t\tOption.toArray(\n\t\t\t\t\t\tOption.fromUndefinedOr(bindOperand(operand, input.principal)),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t\treturn values.length === 0\n\t\t\t\t\t? never\n\t\t\t\t\t: new Nodes.In({ field: current.field, values })\n\t\t\t}\n\t\t\tcase \"Under\":\n\t\t\t\treturn expandUnder(current.prefix, input.principal, input.path)\n\t\t\tcase \"And\":\n\t\t\t\treturn and(Arr.map(current.conditions, bind))\n\t\t\tcase \"Or\":\n\t\t\t\treturn or(Arr.map(current.conditions, bind))\n\t\t\tcase \"Not\":\n\t\t\t\treturn current.condition.pipe(bind, not)\n\t\t\tcase \"Predicate\": {\n\t\t\t\tconst run = Nodes.runOf(current)\n\t\t\t\treturn new Nodes.Predicate({\n\t\t\t\t\tname: current.name,\n\t\t\t\t\trun: (value) => run(value, input.principal),\n\t\t\t\t})\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn current\n\t\t}\n\t}\n\treturn bind(node)\n}\n\n/** Gives the services in `context` to every predicate of a condition. */\nexport const provide = (node: Node, context: Context.Context<never>): Node => {\n\tif (!node.opaque) {\n\t\treturn node\n\t}\n\tswitch (node._tag) {\n\t\tcase \"Predicate\": {\n\t\t\tconst run = Nodes.runOf(node)\n\t\t\treturn new Nodes.Predicate({\n\t\t\t\tname: node.name,\n\t\t\t\trun: (value, principal) =>\n\t\t\t\t\tEffect.provideContext(run(value, principal), context),\n\t\t\t})\n\t\t}\n\t\tcase \"And\":\n\t\t\treturn new Nodes.And(\n\t\t\t\tArr.map(node.conditions, (child) => provide(child, context)),\n\t\t\t)\n\t\tcase \"Or\":\n\t\t\treturn new Nodes.Or(\n\t\t\t\tArr.map(node.conditions, (child) => provide(child, context)),\n\t\t\t)\n\t\tcase \"Not\":\n\t\t\treturn new Nodes.Not(provide(node.condition, context))\n\t\tdefault:\n\t\t\treturn node\n\t}\n}\n\n/** The fields that a condition tests, in the order that they first come. */\nexport const fields = (node: Node): ReadonlyArray<string> => {\n\tconst all = (current: Node): ReadonlyArray<string> => {\n\t\tswitch (current._tag) {\n\t\t\tcase \"Compare\":\n\t\t\tcase \"In\":\n\t\t\tcase \"Exists\":\n\t\t\t\treturn [current.field]\n\t\t\tcase \"And\":\n\t\t\tcase \"Or\":\n\t\t\t\treturn Arr.flatMap(current.conditions, all)\n\t\t\tcase \"Not\":\n\t\t\t\treturn all(current.condition)\n\t\t\tdefault:\n\t\t\t\treturn []\n\t\t}\n\t}\n\treturn Arr.flatten(\n\t\tArr.mapAccum(all(node), HashSet.empty<string>(), (seen, field) => [\n\t\t\tHashSet.add(seen, field),\n\t\t\tHashSet.has(seen, field) ? [] : [field],\n\t\t])[1],\n\t)\n}\n"],"mappings":"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"}