@aventara/core 1.0.0-rc.1 → 1.0.0-rc.11

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 (261) hide show
  1. package/CHANGELOG.md +1022 -16
  2. package/ERRORS.md +142 -0
  3. package/README.md +330 -16
  4. package/dist/adapters/adapter-discovery-diagnostic.guidance.d.ts +6 -0
  5. package/dist/adapters/adapter-discovery-diagnostic.guidance.js +7 -0
  6. package/dist/adapters/adapter-field.d.ts +22 -0
  7. package/dist/adapters/adapter-identifier.d.ts +9 -0
  8. package/dist/adapters/adapter-identifier.js +6 -1
  9. package/dist/adapters/adapter-model.d.ts +9 -0
  10. package/dist/adapters/adapter-operation.d.ts +18 -3
  11. package/dist/adapters/adapter-resource.d.ts +5 -0
  12. package/dist/adapters/adapter.interface.d.ts +10 -0
  13. package/dist/avz/avz.d.ts +1 -1
  14. package/dist/avz/json-shape.registry.d.ts +2 -1
  15. package/dist/compiler/contract-compiler-diagnostic.guidance.d.ts +6 -0
  16. package/dist/compiler/contract-compiler-diagnostic.guidance.js +97 -0
  17. package/dist/compiler/contract.compiler.d.ts +6 -0
  18. package/dist/compiler/contract.compiler.js +281 -31
  19. package/dist/compiler/create-requirements.projector.js +1 -3
  20. package/dist/compiler/field-validator.compiler.js +1 -3
  21. package/dist/compiler/managed-elsewhere.projector.d.ts +52 -0
  22. package/dist/compiler/managed-elsewhere.projector.js +179 -0
  23. package/dist/compiler/managed-elsewhere.validator.d.ts +9 -0
  24. package/dist/compiler/managed-elsewhere.validator.js +74 -0
  25. package/dist/config/cache-stage.factory.d.ts +24 -0
  26. package/dist/config/cache-stage.factory.js +3 -0
  27. package/dist/config/computed-fields.d.ts +62 -0
  28. package/dist/config/computed-fields.js +73 -0
  29. package/dist/config/config-diagnostic.guidance.d.ts +6 -0
  30. package/dist/config/config-diagnostic.guidance.js +32 -0
  31. package/dist/config/config.resolver.d.ts +24 -0
  32. package/dist/config/config.resolver.js +66 -7
  33. package/dist/config/config.validator.js +283 -21
  34. package/dist/config/define-resource.d.ts +1 -5
  35. package/dist/config/entrypoint.normalizer.d.ts +3 -2
  36. package/dist/config/exact-framework-config.d.ts +73 -22
  37. package/dist/config/field-compute.resolver.d.ts +2 -0
  38. package/dist/config/field-compute.resolver.js +9 -3
  39. package/dist/config/framework-config.d.ts +53 -15
  40. package/dist/config/framework-resources-config.d.ts +25 -14
  41. package/dist/config/pipeline-config.d.ts +20 -4
  42. package/dist/config/pipeline-tree.resolver.d.ts +2 -2
  43. package/dist/config/pipeline-tree.resolver.js +2 -3
  44. package/dist/contracts/access-route.rules.d.ts +10 -0
  45. package/dist/contracts/access-route.rules.js +45 -0
  46. package/dist/contracts/canonical-json.writer.d.ts +7 -0
  47. package/dist/contracts/canonical-json.writer.js +55 -0
  48. package/dist/contracts/capability.d.ts +26 -1
  49. package/dist/contracts/capability.js +20 -0
  50. package/dist/contracts/client-contract-structure.validator.d.ts +365 -89
  51. package/dist/contracts/client-contract-structure.validator.js +49 -2
  52. package/dist/contracts/contract-access.d.ts +29 -0
  53. package/dist/contracts/contract-access.js +1 -0
  54. package/dist/contracts/contract-canonicalizer.d.ts +9 -1
  55. package/dist/contracts/contract-canonicalizer.js +35 -4
  56. package/dist/contracts/contract-hash.d.ts +0 -1
  57. package/dist/contracts/contract-hash.js +1 -1
  58. package/dist/contracts/contract-limits.d.ts +6 -0
  59. package/dist/contracts/contract-limits.js +2 -0
  60. package/dist/contracts/contract.d.ts +42 -1
  61. package/dist/contracts/field.d.ts +58 -1
  62. package/dist/contracts/json-schema.projector.d.ts +11 -0
  63. package/dist/contracts/json-schema.projector.js +76 -0
  64. package/dist/contracts/scalar-value-type.d.ts +3 -1
  65. package/dist/framework/access-facade.d.ts +116 -0
  66. package/dist/framework/access-facade.js +118 -0
  67. package/dist/framework/contract-view.d.ts +120 -16
  68. package/dist/framework/framework-construction.error.d.ts +14 -4
  69. package/dist/framework/framework-construction.error.js +18 -2
  70. package/dist/framework/framework.d.ts +26 -5
  71. package/dist/framework/framework.factory.d.ts +1 -1
  72. package/dist/framework/framework.factory.js +145 -24
  73. package/dist/framework/operation-facade.d.ts +141 -13
  74. package/dist/framework/operation-facade.js +9 -1
  75. package/dist/framework/operation-set.runner.d.ts +47 -0
  76. package/dist/framework/operation-set.runner.js +168 -0
  77. package/dist/index.d.ts +19 -5
  78. package/dist/index.js +3 -0
  79. package/dist/internal.d.ts +9 -2
  80. package/dist/internal.js +8 -0
  81. package/dist/operations/database-refusal.d.ts +51 -0
  82. package/dist/operations/database-refusal.js +45 -0
  83. package/dist/operations/operation-arguments.d.ts +148 -60
  84. package/dist/operations/operation-call.d.ts +9 -5
  85. package/dist/operations/operation-result.d.ts +6 -4
  86. package/dist/operations/operation-validator-core.js +160 -39
  87. package/dist/operations/operation-validator.d.ts +1 -1
  88. package/dist/operations/structural-limits.walker.d.ts +1 -1
  89. package/dist/operations/structural-limits.walker.js +1 -3
  90. package/dist/operations/validation-code.guidance.d.ts +6 -0
  91. package/dist/operations/validation-code.guidance.js +90 -0
  92. package/dist/operations/write-scope.resolver.d.ts +4 -0
  93. package/dist/operations/write-scope.resolver.js +2 -0
  94. package/dist/policy/access-provider.interface.d.ts +91 -0
  95. package/dist/policy/access-provider.interface.js +1 -0
  96. package/dist/policy/access-provider.registry.d.ts +17 -0
  97. package/dist/policy/access-provider.registry.js +15 -0
  98. package/dist/policy/access-question.d.ts +20 -0
  99. package/dist/policy/access-question.js +1 -0
  100. package/dist/policy/access-question.registry.d.ts +5 -0
  101. package/dist/policy/access-question.registry.js +19 -0
  102. package/dist/policy/access-question.runtime.d.ts +36 -0
  103. package/dist/policy/access-question.runtime.js +295 -0
  104. package/dist/policy/access-verb.table.d.ts +56 -0
  105. package/dist/policy/access-verb.table.js +21 -0
  106. package/dist/policy/access-verbs.d.ts +46 -0
  107. package/dist/policy/access-verbs.js +1 -0
  108. package/dist/policy/policy-admission.d.ts +20 -0
  109. package/dist/policy/policy-admission.js +407 -0
  110. package/dist/policy/policy-after-update.runtime.d.ts +79 -0
  111. package/dist/policy/policy-after-update.runtime.js +206 -0
  112. package/dist/policy/policy-condition.d.ts +15 -0
  113. package/dist/policy/policy-condition.js +36 -0
  114. package/dist/policy/policy-engine.d.ts +205 -0
  115. package/dist/policy/policy-engine.js +1 -0
  116. package/dist/policy/policy-named-rows.d.ts +18 -0
  117. package/dist/policy/policy-named-rows.js +51 -0
  118. package/dist/policy/policy-nested-write.runtime.d.ts +44 -0
  119. package/dist/policy/policy-nested-write.runtime.js +536 -0
  120. package/dist/policy/policy-read.runtime.d.ts +81 -0
  121. package/dist/policy/policy-read.runtime.js +501 -0
  122. package/dist/policy/policy-reference-write.runtime.d.ts +51 -0
  123. package/dist/policy/policy-reference-write.runtime.js +336 -0
  124. package/dist/policy/policy-request.d.ts +72 -0
  125. package/dist/policy/policy-request.js +115 -0
  126. package/dist/policy/policy-session.d.ts +106 -0
  127. package/dist/policy/policy-session.js +293 -0
  128. package/dist/policy/policy-startup.validator.d.ts +10 -0
  129. package/dist/policy/policy-startup.validator.js +112 -0
  130. package/dist/policy/policy-write.runtime.d.ts +39 -0
  131. package/dist/policy/policy-write.runtime.js +530 -0
  132. package/dist/prebuilt/core-version.generated.d.ts +2 -0
  133. package/dist/prebuilt/core-version.generated.js +1 -0
  134. package/dist/prebuilt/prebuilt-changes.d.ts +29 -0
  135. package/dist/prebuilt/prebuilt-changes.js +63 -0
  136. package/dist/prebuilt/prebuilt-contracts.d.ts +40 -0
  137. package/dist/prebuilt/prebuilt-contracts.emitter.d.ts +16 -0
  138. package/dist/prebuilt/prebuilt-contracts.emitter.js +50 -0
  139. package/dist/prebuilt/prebuilt-contracts.js +1 -0
  140. package/dist/prebuilt/prebuilt-contracts.loader.d.ts +19 -0
  141. package/dist/prebuilt/prebuilt-contracts.loader.js +75 -0
  142. package/dist/prebuilt/prebuilt-inputs.fingerprint.d.ts +16 -0
  143. package/dist/prebuilt/prebuilt-inputs.fingerprint.js +227 -0
  144. package/dist/protocol/absent-route.responder.d.ts +49 -14
  145. package/dist/protocol/absent-route.responder.js +92 -15
  146. package/dist/protocol/contract-document.responder.d.ts +9 -1
  147. package/dist/protocol/contract-document.responder.js +3 -2
  148. package/dist/protocol/http-request.decoder.d.ts +52 -3
  149. package/dist/protocol/http-request.decoder.js +45 -6
  150. package/dist/protocol/http-request.reader.d.ts +10 -3
  151. package/dist/protocol/http-request.reader.js +12 -2
  152. package/dist/protocol/http-response.encoder.d.ts +12 -0
  153. package/dist/protocol/http-response.encoder.js +17 -3
  154. package/dist/protocol/operation-response.guard.js +1 -3
  155. package/dist/protocol/operation-set.decoder.d.ts +48 -0
  156. package/dist/protocol/operation-set.decoder.js +185 -0
  157. package/dist/protocol/operation-set.handler.d.ts +27 -0
  158. package/dist/protocol/operation-set.handler.js +179 -0
  159. package/dist/protocol/protocol-headers.d.ts +12 -3
  160. package/dist/protocol/protocol-headers.js +12 -5
  161. package/dist/protocol/protocol-surface.d.ts +16 -3
  162. package/dist/protocol/protocol-surface.js +41 -1
  163. package/dist/protocol/protocol.binder.d.ts +52 -1
  164. package/dist/protocol/protocol.binder.js +6 -1
  165. package/dist/protocol/protocol.handler.d.ts +45 -1
  166. package/dist/protocol/protocol.handler.js +164 -19
  167. package/dist/protocol/read-cache.responder.d.ts +26 -0
  168. package/dist/protocol/read-cache.responder.js +47 -0
  169. package/dist/protocol/read-query.codec.d.ts +34 -0
  170. package/dist/protocol/read-query.codec.js +125 -0
  171. package/dist/runtime/caller-data.copier.d.ts +18 -3
  172. package/dist/runtime/caller-data.copier.js +21 -8
  173. package/dist/runtime/caller-data.door.d.ts +13 -6
  174. package/dist/runtime/computed-read-runtime.d.ts +6 -1
  175. package/dist/runtime/computed-read-runtime.js +229 -48
  176. package/dist/runtime/computed-value.error.d.ts +3 -2
  177. package/dist/runtime/computed-value.error.js +3 -2
  178. package/dist/runtime/context-executor.runtime.d.ts +4 -3
  179. package/dist/runtime/context-executor.runtime.js +4 -2
  180. package/dist/runtime/core-class.brand.d.ts +10 -0
  181. package/dist/runtime/core-class.brand.js +21 -0
  182. package/dist/runtime/create-requirement.d.ts +31 -5
  183. package/dist/runtime/create-requirement.js +130 -24
  184. package/dist/runtime/decimal.d.ts +14 -0
  185. package/dist/runtime/decimal.js +21 -0
  186. package/dist/runtime/diagnostics-reporter.d.ts +49 -9
  187. package/dist/runtime/diagnostics-reporter.js +16 -9
  188. package/dist/runtime/error-boundary.d.ts +9 -2
  189. package/dist/runtime/error-boundary.js +12 -0
  190. package/dist/runtime/error-guidance.d.ts +12 -0
  191. package/dist/runtime/error-guidance.js +1 -0
  192. package/dist/runtime/error.catalog.d.ts +49 -0
  193. package/dist/runtime/error.catalog.js +49 -0
  194. package/dist/runtime/execution-options.d.ts +8 -0
  195. package/dist/runtime/field-check.evaluator.d.ts +0 -2
  196. package/dist/runtime/field-check.evaluator.js +1 -1
  197. package/dist/runtime/field-compute.d.ts +11 -10
  198. package/dist/runtime/field-stage.runtime.d.ts +3 -3
  199. package/dist/runtime/field-stage.runtime.js +9 -11
  200. package/dist/runtime/field-validator.runtime.d.ts +19 -1
  201. package/dist/runtime/field-validator.runtime.js +49 -9
  202. package/dist/runtime/framework-error.js +9 -0
  203. package/dist/runtime/framework-warning.emitter.d.ts +6 -0
  204. package/dist/runtime/framework-warning.emitter.js +8 -0
  205. package/dist/runtime/json-value.d.ts +10 -5
  206. package/dist/runtime/level-lifecycle.runtime.d.ts +4 -3
  207. package/dist/runtime/level-lifecycle.runtime.js +3 -5
  208. package/dist/runtime/mutation-planner.d.ts +1 -6
  209. package/dist/runtime/mutation-planner.js +4 -17
  210. package/dist/runtime/nested-write.walker.js +2 -1
  211. package/dist/runtime/operation-code.guidance.d.ts +6 -0
  212. package/dist/runtime/operation-code.guidance.js +167 -0
  213. package/dist/runtime/operation-request.d.ts +16 -9
  214. package/dist/runtime/operation-runtime.d.ts +35 -17
  215. package/dist/runtime/operation-runtime.js +220 -49
  216. package/dist/runtime/outcome-mapper.d.ts +2 -1
  217. package/dist/runtime/output-validator.d.ts +1 -1
  218. package/dist/runtime/output-validator.js +1 -3
  219. package/dist/runtime/owned-execution.registry.d.ts +34 -4
  220. package/dist/runtime/pipe-output.validator.d.ts +10 -0
  221. package/dist/runtime/pipe-output.validator.js +4 -2
  222. package/dist/runtime/pipeline.d.ts +52 -23
  223. package/dist/runtime/readonly-value.d.ts +20 -5
  224. package/dist/runtime/readonly-value.js +74 -26
  225. package/dist/runtime/record.guard.d.ts +14 -0
  226. package/dist/runtime/record.guard.js +10 -0
  227. package/dist/runtime/referential-action.d.ts +1 -1
  228. package/dist/runtime/request-envelope.validator.js +13 -10
  229. package/dist/runtime/scalar-runtime.d.ts +4 -21
  230. package/dist/runtime/scalar-runtime.js +91 -31
  231. package/dist/runtime/thenable.guard.d.ts +7 -0
  232. package/dist/runtime/thenable.guard.js +5 -0
  233. package/dist/runtime/unsent-value.normalizer.d.ts +15 -0
  234. package/dist/runtime/unsent-value.normalizer.js +129 -0
  235. package/dist/transactions/operation-arguments-encoder.js +9 -10
  236. package/dist/transactions/operation-fingerprint.js +2 -2
  237. package/dist/transactions/sql-statement.d.ts +10 -2
  238. package/dist/transactions/sql-statement.validator.d.ts +2 -2
  239. package/dist/transactions/sql-statement.validator.js +40 -6
  240. package/dist/transactions/transaction-envelope.d.ts +5 -4
  241. package/dist/transactions/transaction-integrity-error.js +2 -0
  242. package/dist/transactions/transaction-plan-assembler.d.ts +12 -5
  243. package/dist/transactions/transaction-plan-assembler.js +49 -17
  244. package/dist/transactions/transaction-plan-validator.d.ts +23 -7
  245. package/dist/transactions/transaction-plan-validator.js +31 -7
  246. package/dist/transactions/transaction-reference-collector.js +8 -10
  247. package/dist/transactions/transaction-reference-resolver.d.ts +3 -2
  248. package/dist/transactions/transaction-reference-resolver.js +1 -3
  249. package/dist/transactions/transaction-reference-validator.d.ts +43 -3
  250. package/dist/transactions/transaction-reference-validator.js +83 -57
  251. package/dist/transactions/transaction-reference.d.ts +1 -1
  252. package/dist/transactions/transaction-reference.js +5 -0
  253. package/dist/transactions/transaction-request.d.ts +8 -8
  254. package/dist/transactions/transaction-runtime.d.ts +5 -2
  255. package/dist/transactions/transaction-runtime.js +108 -27
  256. package/dist/transactions/transaction-settlement.runtime.d.ts +4 -3
  257. package/dist/transactions/transaction-slot-path-error.js +2 -0
  258. package/dist/transactions/transaction-stage.runtime.d.ts +5 -3
  259. package/dist/transactions/transaction-stage.runtime.js +8 -7
  260. package/package.json +6 -5
  261. package/src/runtime/field-check.evaluator.ts +1 -1
@@ -1,3 +1,4 @@
1
+ import { isRecord } from "../runtime/record.guard.js";
1
2
  function chainWrite(root, overlay) {
2
3
  if (root === undefined || overlay === undefined) {
3
4
  return root ?? overlay;
@@ -46,9 +47,6 @@ function chainRead(root, overlay) {
46
47
  ? compute
47
48
  : { dependsOn, compute };
48
49
  }
49
- function isRecord(value) {
50
- return value !== null && typeof value === "object" && !Array.isArray(value);
51
- }
52
50
  export function computeOfLayer(resources) {
53
51
  const result = {};
54
52
  if (!isRecord(resources)) {
@@ -113,3 +111,11 @@ export function chainCompute(root, overlay) {
113
111
  }
114
112
  return result;
115
113
  }
114
+ export function createComputedFields(compute, resource) {
115
+ const fields = Object.hasOwn(compute, resource)
116
+ ? compute[resource]
117
+ : undefined;
118
+ return new Set(Object.entries(fields ?? {})
119
+ .filter(([, phases]) => phases.create !== undefined)
120
+ .map(([field]) => field));
121
+ }
@@ -2,19 +2,28 @@ import type { AvAdapter } from "../adapters/adapter.interface.js";
2
2
  import type { AvAdapterModel } from "../adapters/adapter-model.js";
3
3
  import type { AvContractLimits } from "../contracts/contract-limits.js";
4
4
  import type { AvTransactionCapability } from "../contracts/transaction-capability.js";
5
+ import type { AvAccessProvider } from "../policy/access-provider.interface.js";
6
+ import type { AvPolicyEngine } from "../policy/policy-engine.js";
7
+ import type { AvPrebuiltContracts } from "../prebuilt/prebuilt-contracts.js";
5
8
  import type { AvDiagnosticsSink } from "../runtime/diagnostics-reporter.js";
6
9
  import type { AvMisuseSink } from "../runtime/misuse-reporter.js";
10
+ import type { AvState } from "../runtime/request-state.js";
7
11
  import type { AvConfigAny } from "./any-framework-config.js";
12
+ import type { AvConfigLayerName, AvRequestOrigin } from "./config-layer.js";
8
13
  import type { AvConfigExemptions } from "./framework-exemptions-config.js";
9
- import type { AvConfigLayerKind, AvConfigResources } from "./framework-resources-config.js";
14
+ import type { AvConfigLayerKind, AvConfigResources, LayerOfKind } from "./framework-resources-config.js";
10
15
  import type { AvPipeline } from "./pipeline-config.js";
11
16
  /**
12
17
  * Request limits to override; each one left out takes its default from
13
18
  * {@link DEFAULT_CONTRACT_LIMITS}.
14
19
  */
15
20
  export type AvConfigLimits = Partial<AvContractLimits>;
16
- /** rc.0's layer keys, each refused with its rc.1 location. */
17
- type MovedLayerKeys = {
21
+ /**
22
+ * The six keys every layer holds: the root, `application`, `client` and
23
+ * `agent`. Stages are added to the root's; `transactionsStyle` and `limits`
24
+ * replace it where an overlay states them; exposure only narrows.
25
+ */
26
+ export type AvConfigLayer<M extends AvAdapterModel = AvAdapterModel, Cfg = AvConfigAny, Kind extends AvConfigLayerKind = "root", Layer extends AvConfigLayerName = LayerOfKind<Kind>> = {
18
27
  /** Moved: `exposed` + `exemptions`. */
19
28
  readonly restrictions?: never;
20
29
  /** Moved: `resources.<R>.fields.<f>.pipelines.compute`. */
@@ -23,13 +32,6 @@ type MovedLayerKeys = {
23
32
  readonly fields?: never;
24
33
  /** Moved: `transactionsStyle`. */
25
34
  readonly transactions?: never;
26
- };
27
- /**
28
- * The six keys every layer holds: the root, `application`, `client` and
29
- * `agent`. Stages are added to the root's; `transactionsStyle` and `limits`
30
- * replace it where an overlay states them; exposure only narrows.
31
- */
32
- export type AvConfigLayer<M extends AvAdapterModel = AvAdapterModel, Cfg = AvConfigAny, Kind extends AvConfigLayerKind = "root"> = MovedLayerKeys & {
33
35
  /**
34
36
  * Whether the layer's `exemptions` hide (`true`, the root's default) or are
35
37
  * the only entries exposed (`false`). Each layer narrows its parent: the root
@@ -43,7 +45,7 @@ export type AvConfigLayer<M extends AvAdapterModel = AvAdapterModel, Cfg = AvCon
43
45
  /** Guards, pipes, hooks, interceptors and filters run around every operation of the layer. */
44
46
  readonly pipelines?: AvPipeline<NoInfer<M>>;
45
47
  /** The per-Resource tree: stages, operations, transactions and fields. */
46
- readonly resources?: AvConfigResources<M, Cfg, Kind>;
48
+ readonly resources?: AvConfigResources<M, Cfg, Kind, Layer>;
47
49
  /**
48
50
  * The entries that are the opposite of `exposed`. An overlay that sets them
49
51
  * states its own `exposed`.
@@ -70,11 +72,45 @@ export type AvConfig<M extends AvAdapterModel = AvAdapterModel, Cfg = AvConfigAn
70
72
  */
71
73
  readonly mcp?: AvConfigMcp;
72
74
  readonly adapter: AvAdapter<M>;
75
+ /**
76
+ * Contracts compiled ahead of time (the generated `aventaraContracts`), for a
77
+ * fast cold start on serverless and edge platforms. Used only when they were
78
+ * compiled from this configuration and the adapter's model by this core;
79
+ * otherwise the Contracts are compiled at startup, as without it, and a
80
+ * `AVENTARA_PREBUILT_STALE` warning says why.
81
+ */
82
+ readonly prebuilt?: AvPrebuiltContracts;
83
+ /**
84
+ * The policy engine every client and agent request is checked against, and
85
+ * how a request's principal is derived from its `ctx.$state`. Application
86
+ * calls bypass it unless they name a principal (`{ as }`); calls a stage
87
+ * makes through `ctx` always do.
88
+ */
89
+ readonly policy?: {
90
+ readonly engine: AvPolicyEngine;
91
+ /**
92
+ * The request's principal, from its `ctx.$state` and its layer; `null` for
93
+ * an anonymous caller. It may answer with a promise (rc.5), which is
94
+ * awaited; a throw or a rejection answers `A3000`.
95
+ */
96
+ readonly principal: (facts: {
97
+ readonly $state: AvState;
98
+ readonly $origin: AvRequestOrigin;
99
+ }) => unknown;
100
+ };
101
+ /**
102
+ * The access provider (Aventara Access, or one written by hand): its
103
+ * `policy` engine checks every client and agent request, with
104
+ * `ctx.$state.me` as the principal, and the host seeds each request's
105
+ * `ctx.$state` with its `state`. Not together with `policy`, nor with a
106
+ * host's own `state` option.
107
+ */
108
+ readonly access?: AvAccessProvider;
73
109
  readonly diagnostics?: AvDiagnosticsSink;
74
110
  /** Told about every caller value refused as unreadable or not plain data. */
75
111
  readonly misuse?: AvMisuseSink;
76
- readonly application?: AvConfigLayer<M, Cfg, "overlay">;
77
- readonly client?: AvConfigLayer<M, Cfg, "overlay">;
112
+ readonly application?: AvConfigLayer<M, Cfg, "overlay", "application">;
113
+ readonly client?: AvConfigLayer<M, Cfg, "overlay", "client">;
78
114
  /**
79
115
  * The layer an AI agent's calls run under. It narrows the view of the layer it
80
116
  * `extends` (the client's when left out), and its stages run after that
@@ -95,7 +131,9 @@ export type AvConfigMcp = string | {
95
131
  readonly authorization?: {
96
132
  /**
97
133
  * The authorization servers (https URLs) a caller obtains its token
98
- * from, advertised in the endpoint's protected-resource metadata.
134
+ * from, advertised in the endpoint's protected-resource metadata. A
135
+ * server on this machine may be http: `http://127.0.0.1` or
136
+ * `http://[::1]`, with any port and path (not `localhost`).
99
137
  */
100
138
  readonly servers: readonly string[];
101
139
  /**
@@ -109,7 +147,7 @@ export type AvConfigMcp = string | {
109
147
  * The `agent` layer: the six layer keys, and `extends`, the layer whose final
110
148
  * view it narrows and whose stages run before its own.
111
149
  */
112
- export type AvConfigAgentLayer<M extends AvAdapterModel = AvAdapterModel, Cfg = AvConfigAny> = AvConfigLayer<M, Cfg, "overlay"> & {
150
+ export type AvConfigAgentLayer<M extends AvAdapterModel = AvAdapterModel, Cfg = AvConfigAny> = AvConfigLayer<M, Cfg, "overlay", "agent"> & {
113
151
  /**
114
152
  * The layer the agent starts from: `"client"` (the default), `"application"`
115
153
  * or `"root"`. The agent never widens it.
@@ -2,8 +2,10 @@ import type { AvAdapterModel } from "../adapters/adapter-model.js";
2
2
  import type { AvAdapterFieldKey } from "../adapters/adapter-resource.js";
3
3
  import type { AvZCheck } from "../avz/avz-check.registry.js";
4
4
  import type { AvOperationFamily } from "../operations/operation-identity.js";
5
- import type { AvStageArguments } from "../runtime/pipeline.js";
5
+ import type { AvPreComputeStageArguments, AvStageArguments } from "../runtime/pipeline.js";
6
6
  import type { AvConfigAny } from "./any-framework-config.js";
7
+ import type { AvPreComputeLift } from "./computed-fields.js";
8
+ import type { AvConfigLayerName } from "./config-layer.js";
7
9
  import type { AvEffectiveFieldKey } from "./effective-fields.js";
8
10
  import type { AvRelationFieldPipeline, AvScalarFieldPipeline } from "./field-pipeline-config.js";
9
11
  import type { AvConfigAddedFieldDefinition, AvConfigFieldDefinition, AvConfigKnownFieldDefinition, AvConfigResourceKey } from "./framework-field-definition.js";
@@ -14,29 +16,29 @@ import type { AvPipeline, AvTransactionPipeline } from "./pipeline-config.js";
14
16
  */
15
17
  export type AvConfigLayerKind = "root" | "overlay";
16
18
  /** One operation variant's level: its stages and `forceTransaction`. */
17
- export type AvConfigVariant<M extends AvAdapterModel = AvAdapterModel, R extends string = AvConfigResourceKey<M>, F extends AvOperationFamily = AvOperationFamily, V extends string = string, A = NoInfer<AvStageArguments<M, R, F, V>>> = {
19
+ export type AvConfigVariant<M extends AvAdapterModel = AvAdapterModel, R extends string = AvConfigResourceKey<M>, F extends AvOperationFamily = AvOperationFamily, V extends string = string, A = NoInfer<AvStageArguments<M, R, F, V>>, PreCompute = NoInfer<AvPreComputeStageArguments<M, R, F, V>>> = {
18
20
  /**
19
21
  * Stages that run for this one operation: at a variant, `ctx.$args` (and a
20
- * pipe's arguments) are typed as the operation's arguments.
22
+ * pipe's arguments) are typed as the operation's arguments; in a guard, a
23
+ * pipe or a filter a create may lack the fields `compute.create` fills
24
+ * (write compute runs after them).
21
25
  */
22
- readonly pipelines?: AvPipeline<NoInfer<M>, R, F, V, A>;
26
+ readonly pipelines?: AvPipeline<NoInfer<M>, R, F, V, A, PreCompute>;
23
27
  /** Runs a plain call of this operation as a one-step transaction. */
24
28
  readonly forceTransaction?: boolean;
25
29
  };
26
- /** The variants a family's stages are told: its own, and `"one"` for a nested target. */
27
- type FamilyStageVariant<F extends AvOperationFamily, V extends string> = F extends "create" | "update" | "delete" ? V | "one" : V;
28
30
  /**
29
31
  * One operation family's level: stages and `forceTransaction` for every variant
30
32
  * of it, and each variant's own level by name.
31
33
  */
32
34
  export type AvConfigFamily<M extends AvAdapterModel = AvAdapterModel, Variants = {
33
35
  readonly [V in "first" | "unique" | "many" | "count" | "one"]?: unknown;
34
- }, R extends string = AvConfigResourceKey<M>, F extends AvOperationFamily = AvOperationFamily> = AvConfigVariant<M, R, F, FamilyStageVariant<F, Extract<keyof NonNullable<Variants>, string>>, unknown> & {
35
- readonly [V in Extract<keyof NonNullable<Variants>, string>]?: AvConfigVariant<M, R, F, V> | undefined;
36
+ }, R extends string = AvConfigResourceKey<M>, F extends AvOperationFamily = AvOperationFamily, Layer extends AvConfigLayerName = "root"> = AvConfigVariant<M, R, F, F extends "create" | "update" | "delete" ? Extract<keyof NonNullable<Variants>, string> | "one" : Extract<keyof NonNullable<Variants>, string>, unknown, unknown> & {
37
+ readonly [V in Extract<keyof NonNullable<Variants>, string>]?: AvConfigVariant<M, R, F, V, NoInfer<AvStageArguments<M, R, F, V>>, NoInfer<AvPreComputeStageArguments<M, R, F, V, AvPreComputeLift<M, Layer>>>> | undefined;
36
38
  };
37
39
  /** A Resource's families, as the adapter model offers them, each with its level. */
38
- export type AvConfigOperations<M extends AvAdapterModel = AvAdapterModel, R extends AvConfigResourceKey<M> = AvConfigResourceKey<M>> = {
39
- readonly [F in Extract<keyof M["resources"][R]["operations"], AvOperationFamily>]?: AvConfigFamily<M, M["resources"][R]["operations"][F], R, F>;
40
+ export type AvConfigOperations<M extends AvAdapterModel = AvAdapterModel, R extends AvConfigResourceKey<M> = AvConfigResourceKey<M>, Layer extends AvConfigLayerName = "root"> = {
41
+ readonly [F in Extract<keyof M["resources"][R]["operations"], AvOperationFamily>]?: AvConfigFamily<M, M["resources"][R]["operations"][F], R, F, Layer>;
40
42
  };
41
43
  /** A Resource's transaction level. */
42
44
  export type AvConfigResourceTransactions<M extends AvAdapterModel = AvAdapterModel> = {
@@ -99,18 +101,27 @@ export type AvConfigResourceFields<in out M extends AvAdapterModel = AvAdapterMo
99
101
  readonly [F in AvEffectiveFieldKey<M, Cfg, R>]?: Kind extends "root" ? RootFieldConfigFor<M, Cfg, R, F> : OverlayFieldConfigFor<M, Cfg, R, F>;
100
102
  };
101
103
  /** One Resource's tree: its stages, operations, transactions and fields. */
102
- export type AvConfigResource<in out M extends AvAdapterModel = AvAdapterModel, in out Cfg = AvConfigAny, in out R extends AvConfigResourceKey<M> = AvConfigResourceKey<M>, Kind extends AvConfigLayerKind = "root"> = {
104
+ export type AvConfigResource<in out M extends AvAdapterModel = AvAdapterModel, in out Cfg = AvConfigAny, in out R extends AvConfigResourceKey<M> = AvConfigResourceKey<M>, Kind extends AvConfigLayerKind = "root", Layer extends AvConfigLayerName = LayerOfKind<Kind>> = {
103
105
  /** Stages that run for every operation of this Resource. */
104
106
  readonly pipelines?: AvPipeline<NoInfer<M>, R>;
105
107
  /** Per family, and per variant under its family. */
106
- readonly operations?: AvConfigOperations<M, R>;
108
+ readonly operations?: AvConfigOperations<M, R, Layer>;
107
109
  /** Stages that run once per transaction with a top-level step on this Resource. */
108
110
  readonly transactions?: AvConfigResourceTransactions<M>;
109
111
  /** Per field: its definition (root only) and its stages. */
110
112
  readonly fields?: AvConfigResourceFields<M, Cfg, R, Kind>;
113
+ /**
114
+ * `true`: another service owns this Resource's table and migrates it. It is
115
+ * read and joined, never written: it has no write operation, no nested write
116
+ * reaches its rows, and the client and agent Contracts leave it out, with
117
+ * every relation to it. Root only.
118
+ */
119
+ readonly managedElsewhere?: Kind extends "root" ? boolean : never;
111
120
  };
112
121
  /** The `resources` tree of one layer, keyed by the adapter's Resource names. */
113
- export type AvConfigResources<in out M extends AvAdapterModel = AvAdapterModel, in out Cfg = AvConfigAny, in out Kind extends AvConfigLayerKind = "root"> = {
114
- readonly [R in AvConfigResourceKey<M>]?: AvConfigResource<M, Cfg, R, Kind>;
122
+ export type AvConfigResources<in out M extends AvAdapterModel = AvAdapterModel, in out Cfg = AvConfigAny, in out Kind extends AvConfigLayerKind = "root", in out Layer extends AvConfigLayerName = LayerOfKind<Kind>> = {
123
+ readonly [R in AvConfigResourceKey<M>]?: AvConfigResource<M, Cfg, R, Kind, Layer>;
115
124
  };
125
+ /** The layers a tree of kind `Kind` may be written in, when it names none. */
126
+ export type LayerOfKind<Kind extends AvConfigLayerKind> = Kind extends "root" ? "root" : Exclude<AvConfigLayerName, "root">;
116
127
  export {};
@@ -6,11 +6,11 @@ import type { AvConfigResourceKey } from "./framework-field-definition.js";
6
6
  * Pipeline registrations for one level of the configuration: a layer, a
7
7
  * Resource, a family or a variant. See {@link AvContext}.
8
8
  */
9
- export type AvPipeline<M extends AvAdapterModel = AvAdapterModel, R extends string = AvConfigResourceKey<M>, F extends AvOperationFamily = AvOperationFamily, V extends string = string, A = unknown> = {
9
+ export type AvPipeline<M extends AvAdapterModel = AvAdapterModel, R extends string = AvConfigResourceKey<M>, F extends AvOperationFamily = AvOperationFamily, V extends string = string, A = unknown, PreCompute = A> = {
10
10
  /** Run first; a guard returning `false` denies the operation with `A4001`. */
11
- readonly guards?: readonly AvGuard<M, R, F, V, A>[];
11
+ readonly guards?: readonly AvGuard<M, R, F, V, PreCompute>[];
12
12
  /** Run in order on the arguments; a pipe may return replacement arguments. */
13
- readonly pipes?: readonly AvPipe<M, R, F, V, A>[];
13
+ readonly pipes?: readonly AvPipe<M, R, F, V, PreCompute>[];
14
14
  /**
15
15
  * Run around the operation, inside every level's interceptors: `before`
16
16
  * hooks outer to inner, `after` hooks inner to outer.
@@ -22,7 +22,18 @@ export type AvPipeline<M extends AvAdapterModel = AvAdapterModel, R extends stri
22
22
  /** Wrap everything below this level; each calls `next()` to continue. */
23
23
  readonly interceptors?: readonly AvInterceptor<M, R, F, V, A>[];
24
24
  /** Turn a thrown error into a {@link AvError} outcome. */
25
- readonly filters?: readonly AvFilter<M, R, F, V, A>[];
25
+ readonly filters?: readonly AvFilter<M, R, F, V, PreCompute>[];
26
+ /**
27
+ * A read's cache stage, `cache({ for: "user", maxAge: 60 })`: the reads this
28
+ * level covers (its `find` operations) are also served as a GET a browser or
29
+ * a CDN may keep. The most specific level's stage wins. Always write `for`,
30
+ * even for the default `"user"`: the audience is the promise this read
31
+ * makes, and it should be visible in the code.
32
+ */
33
+ readonly cache?: {
34
+ readonly for?: "user" | "anonymous" | "everyone";
35
+ readonly maxAge: number;
36
+ };
26
37
  };
27
38
  /**
28
39
  * A Resource's transaction stages: they run once per transaction with a
@@ -51,6 +62,11 @@ export type ResolvedPipelineConfig = {
51
62
  };
52
63
  readonly interceptors: readonly AvInterceptor[];
53
64
  readonly filters: readonly AvFilter[];
65
+ /** The level's read cache stage, as authored (validated); rc.11. */
66
+ readonly cache?: {
67
+ readonly for?: "user" | "anonymous" | "everyone";
68
+ readonly maxAge: number;
69
+ };
54
70
  };
55
71
  /** One layer's registrations on one Resource's transactions. */
56
72
  export type ResolvedTransactionPipelineConfig = {
@@ -2,12 +2,12 @@ import type { AvOperationIdentity } from "../operations/operation-identity.js";
2
2
  import type { AvFieldGuard, AvFieldPipe } from "../runtime/pipeline.js";
3
3
  import type { ResolvedPipelineConfig, ResolvedTransactionPipelineConfig } from "./pipeline-config.js";
4
4
  /** One variant's levels and whether a layer forces it. */
5
- export type ResolvedVariantPipelines = {
5
+ type ResolvedVariantPipelines = {
6
6
  readonly pipelines: readonly ResolvedPipelineConfig[];
7
7
  readonly forceTransaction: boolean;
8
8
  };
9
9
  /** One family's levels, its variants' and whether a layer forces the family. */
10
- export type ResolvedFamilyPipelines = ResolvedVariantPipelines & {
10
+ type ResolvedFamilyPipelines = ResolvedVariantPipelines & {
11
11
  readonly variants: Readonly<Record<string, ResolvedVariantPipelines>>;
12
12
  };
13
13
  /** One field's stages for one origin: the root's, then the overlay's. */
@@ -1,6 +1,4 @@
1
- function isRecord(value) {
2
- return value !== null && typeof value === "object" && !Array.isArray(value);
3
- }
1
+ import { isRecord } from "../runtime/record.guard.js";
4
2
  function own(record, key) {
5
3
  return record !== undefined && Object.hasOwn(record, key)
6
4
  ? record[key]
@@ -23,6 +21,7 @@ function levelOf(value) {
23
21
  },
24
22
  interceptors: list(pipeline.interceptors),
25
23
  filters: list(pipeline.filters),
24
+ ...(isRecord(pipeline.cache) ? { cache: pipeline.cache } : {}),
26
25
  };
27
26
  }
28
27
  function transactionLevelOf(value) {
@@ -0,0 +1,10 @@
1
+ /**
2
+ * An absolute `http:`/`https:` URL, or a root-relative path other than `"/"`:
3
+ * never `//host`, a backslash, a control character, a space or a dot segment.
4
+ */
5
+ export declare function isAccessUrl(value: unknown): value is string;
6
+ /**
7
+ * A verb's path under the section's `url`: starting with one `/`, never a
8
+ * backslash, a control character, a space or a dot segment.
9
+ */
10
+ export declare function isAccessPath(value: unknown): value is string;
@@ -0,0 +1,45 @@
1
+ function hasControlOrSpace(value) {
2
+ for (let index = 0; index < value.length; index += 1) {
3
+ const code = value.charCodeAt(index);
4
+ if (code <= 0x20 || code === 0x7f) {
5
+ return true;
6
+ }
7
+ }
8
+ return false;
9
+ }
10
+ const DOT_SEGMENT = /^(?:\.|%2e){1,2}$/i;
11
+ function hasDotSegment(path) {
12
+ const end = path.search(/[?#]/);
13
+ return (end === -1 ? path : path.slice(0, end))
14
+ .split("/")
15
+ .some((segment) => DOT_SEGMENT.test(segment));
16
+ }
17
+ export function isAccessUrl(value) {
18
+ if (typeof value !== "string" ||
19
+ value.includes("\\") ||
20
+ hasControlOrSpace(value)) {
21
+ return false;
22
+ }
23
+ if (value.startsWith("/")) {
24
+ return value !== "/" && !value.startsWith("//") && !hasDotSegment(value);
25
+ }
26
+ const authority = /^[a-z][a-z0-9+.-]*:\/\/[^/?#]*/i.exec(value)?.[0];
27
+ if (authority === undefined || hasDotSegment(value.slice(authority.length))) {
28
+ return false;
29
+ }
30
+ try {
31
+ const { protocol } = new URL(value);
32
+ return protocol === "https:" || protocol === "http:";
33
+ }
34
+ catch {
35
+ return false;
36
+ }
37
+ }
38
+ export function isAccessPath(value) {
39
+ return (typeof value === "string" &&
40
+ value.startsWith("/") &&
41
+ !value.startsWith("//") &&
42
+ !value.includes("\\") &&
43
+ !hasControlOrSpace(value) &&
44
+ !hasDotSegment(value));
45
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * The canonical JSON text (RFC 8785) of a JSON value: an object's keys in
3
+ * UTF-16 code-unit order, a member holding `undefined` left out, nothing but
4
+ * `null`, booleans, finite numbers, strings, arrays and plain objects. Throws a
5
+ * `TypeError` for anything else, a lone surrogate in a string or key included.
6
+ */
7
+ export declare function canonicalJson(value: unknown): string;
@@ -0,0 +1,55 @@
1
+ export function canonicalJson(value) {
2
+ const LONE_SURROGATE = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/;
3
+ const text = (string) => {
4
+ if (LONE_SURROGATE.test(string)) {
5
+ throw new TypeError("Canonical JSON cannot write a lone surrogate.");
6
+ }
7
+ return JSON.stringify(string);
8
+ };
9
+ const write = (current, ancestors) => {
10
+ if (current === null) {
11
+ return "null";
12
+ }
13
+ switch (typeof current) {
14
+ case "boolean":
15
+ return current ? "true" : "false";
16
+ case "number":
17
+ if (!Number.isFinite(current)) {
18
+ throw new TypeError("Canonical JSON cannot write a non-finite number.");
19
+ }
20
+ return JSON.stringify(current);
21
+ case "string":
22
+ return text(current);
23
+ case "object":
24
+ break;
25
+ default:
26
+ throw new TypeError(`Canonical JSON cannot write a ${typeof current}.`);
27
+ }
28
+ const container = current;
29
+ if (ancestors.includes(container)) {
30
+ throw new TypeError("Canonical JSON cannot write a cycle.");
31
+ }
32
+ const path = [...ancestors, container];
33
+ if (Array.isArray(container)) {
34
+ const items = [];
35
+ for (let index = 0; index < container.length; index += 1) {
36
+ items.push(write(container[index] ?? null, path));
37
+ }
38
+ return `[${items.join(",")}]`;
39
+ }
40
+ const prototype = Object.getPrototypeOf(container);
41
+ if (prototype !== Object.prototype && prototype !== null) {
42
+ throw new TypeError("Canonical JSON writes plain objects only.");
43
+ }
44
+ const record = container;
45
+ const members = [];
46
+ for (const key of Object.keys(record).sort((left, right) => left < right ? -1 : left > right ? 1 : 0)) {
47
+ const member = record[key];
48
+ if (member !== undefined) {
49
+ members.push(`${text(key)}:${write(member, path)}`);
50
+ }
51
+ }
52
+ return `{${members.join(",")}}`;
53
+ };
54
+ return write(value, []);
55
+ }
@@ -1,11 +1,36 @@
1
1
  /** The operators a scalar field can be filtered with. */
2
2
  export type AvScalarFilterOperator = "equals" | "not" | "in" | "notIn" | "lt" | "lte" | "gt" | "gte" | "contains" | "startsWith" | "endsWith" | "mode" | "has" | "hasEvery" | "hasSome" | "isEmpty" | "path" | "stringContains" | "stringStartsWith" | "stringEndsWith" | "arrayContains" | "arrayStartsWith" | "arrayEndsWith";
3
+ /**
4
+ * The case-sensitivity a text filter's `mode` asks for. `"default"` is whatever
5
+ * the database's own comparison does and is always available; `"sensitive"` and
6
+ * `"insensitive"` are an explicit promise, available on a field only where its
7
+ * `filterModes` lists them.
8
+ */
9
+ export declare const FILTER_MODES: readonly ["default", "sensitive", "insensitive"];
10
+ /** @see FILTER_MODES, the axis this union is derived from. */
11
+ export type ScalarFilterMode = (typeof FILTER_MODES)[number];
3
12
  /** What an update can do to a scalar value besides setting it. */
4
13
  export type AvScalarMutationDirective = "$increment" | "$decrement" | "$multiply" | "$divide" | "$push" | "$unset";
5
14
  /** How a relation can be filtered on. */
6
15
  export type AvRelationFilterCapability = "nested" | "match" | "null" | "some" | "every" | "none";
7
16
  /** What a write can do to a relation: `$create`, `$connect` and the rest. */
8
17
  export type AvRelationMutationDirective = "$create" | "$connect" | "$connectOrCreate" | "$disconnect" | "$set" | "$update" | "$delete" | "$upsert";
18
+ /** The to-one directives that change which row the relation links. */
19
+ export declare const TO_ONE_RELINK_DIRECTIVES: readonly ["$connect", "$connectOrCreate", "$create", "$set", "$disconnect"];
20
+ /** The to-one directives that write the row the relation links. */
21
+ export declare const TO_ONE_REWRITE_DIRECTIVES: readonly ["$update", "$upsert"];
22
+ /** @see TO_ONE_RELINK_DIRECTIVES */
23
+ export type ToOneRelinkDirective = (typeof TO_ONE_RELINK_DIRECTIVES)[number];
24
+ /** @see TO_ONE_REWRITE_DIRECTIVES */
25
+ export type ToOneRewriteDirective = (typeof TO_ONE_REWRITE_DIRECTIVES)[number];
26
+ /**
27
+ * A to-one operand's directives that both relink the relation and write the
28
+ * linked row, or `undefined` when it does not pair them.
29
+ */
30
+ export declare function toOneRelinkWithRewrite(operand: Readonly<Record<string, unknown>>): {
31
+ readonly rewrite: readonly ToOneRewriteDirective[];
32
+ readonly relink: readonly ToOneRelinkDirective[];
33
+ } | undefined;
9
34
  /** How a list of related rows can be paginated. */
10
35
  export type AvPaginationCapability = "limit" | "offset" | "cursor";
11
36
  /** What a projection can compute over a to-many relation. */
@@ -24,6 +49,6 @@ export type AvProjectionScope = (typeof PROJECTION_SCOPES)[number];
24
49
  * not the operation that carries it. The write counterpart of
25
50
  * {@link AvProjectionScope}.
26
51
  */
27
- export declare const WRITE_SCOPES: readonly ["nested", "bulkWrite"];
52
+ export declare const WRITE_SCOPES: readonly ["nested", "bulkWrite", "loopback"];
28
53
  /** @see WRITE_SCOPES, the axis this union is derived from. */
29
54
  export type AvWriteScope = (typeof WRITE_SCOPES)[number];
@@ -1,3 +1,22 @@
1
+ export const FILTER_MODES = ["default", "sensitive", "insensitive"];
2
+ export const TO_ONE_RELINK_DIRECTIVES = [
3
+ "$connect",
4
+ "$connectOrCreate",
5
+ "$create",
6
+ "$set",
7
+ "$disconnect",
8
+ ];
9
+ export const TO_ONE_REWRITE_DIRECTIVES = [
10
+ "$update",
11
+ "$upsert",
12
+ ];
13
+ export function toOneRelinkWithRewrite(operand) {
14
+ const rewrite = TO_ONE_REWRITE_DIRECTIVES.filter((key) => Object.hasOwn(operand, key));
15
+ const relink = TO_ONE_RELINK_DIRECTIVES.filter((key) => Object.hasOwn(operand, key));
16
+ return rewrite.length === 0 || relink.length === 0
17
+ ? undefined
18
+ : { rewrite, relink };
19
+ }
1
20
  export const PROJECTION_SCOPES = [
2
21
  "record",
3
22
  "bulkWrite",
@@ -5,4 +24,5 @@ export const PROJECTION_SCOPES = [
5
24
  export const WRITE_SCOPES = [
6
25
  "nested",
7
26
  "bulkWrite",
27
+ "loopback",
8
28
  ];