@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
@@ -21,6 +21,11 @@ export type PlannedReadOperation = {
21
21
  readonly projection: ReadProjectionPlan | undefined;
22
22
  readonly materialize: boolean;
23
23
  };
24
+ /**
25
+ * The fields a level returns when it states no projection: every scalar of the
26
+ * active Contract whose `select` is `true` and that is not governed.
27
+ */
28
+ export declare function defaultProjectionFields(active: AvContract, resourceName: string): readonly string[];
24
29
  /**
25
30
  * Clone the caller projection into the internal Adapter projection: the read
26
31
  * set the Adapter is asked for, always explicit for a projecting variant, plus
@@ -33,5 +38,5 @@ export declare function planReadOperation(core: AvContractCore, model: AvAdapter
33
38
  * Materialize computed scalar reads and remove internal dependency fields,
34
39
  * against `active` — the Contract `planReadOperation` was given as `active`.
35
40
  */
36
- export declare function materializeReadOperation(active: AvContract, compute: ResolvedComputeConfig | undefined, request: OperationExecutionRequest, plan: PlannedReadOperation, value: unknown, contextFactory: ContextFactory): Promise<unknown>;
41
+ export declare function materializeReadOperation(active: AvContract, compute: ResolvedComputeConfig | undefined, _request: OperationExecutionRequest, plan: PlannedReadOperation, value: unknown, contextFactory: ContextFactory): Promise<unknown>;
37
42
  export {};
@@ -1,9 +1,10 @@
1
+ import { adapterPrimaryIdentifier } from "../adapters/adapter-identifier.js";
1
2
  import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
2
3
  import { AvComputedValueError } from "./computed-value.error.js";
4
+ import { frozenCopy } from "./readonly-value.js";
5
+ import { isRecord } from "./record.guard.js";
3
6
  import { normalizeScalarFieldValue } from "./scalar-runtime.js";
4
- function isRecord(value) {
5
- return value !== null && typeof value === "object" && !Array.isArray(value);
6
- }
7
+ import { isThenable } from "./thenable.guard.js";
7
8
  function readCompute(value) {
8
9
  if (typeof value === "function") {
9
10
  return { compute: value, dependsOn: [] };
@@ -51,6 +52,11 @@ function addScalarProjection(core, model, active, compute, resourceName, fieldNa
51
52
  const stage = readCompute(compute?.[resourceName]?.[fieldName]?.read);
52
53
  if (stage !== undefined) {
53
54
  appendUnique(computed, fieldName);
55
+ if (stage.dependsOn.length === 0) {
56
+ for (const member of adapterPrimaryIdentifier(model, resourceName)) {
57
+ appendUniqueProjection(adapterSelect, member);
58
+ }
59
+ }
54
60
  for (const dependency of stage.dependsOn) {
55
61
  if (storedScalar(model, resourceName, dependency)) {
56
62
  appendUniqueProjection(adapterSelect, dependency);
@@ -77,18 +83,27 @@ function projectionEntry(entry) {
77
83
  function withoutProjectionChoice(value) {
78
84
  return Object.fromEntries(Object.entries(value).filter(([key]) => key !== "select" && key !== "include"));
79
85
  }
80
- function defaultProjectionLevel(core, model, active, compute, resourceName) {
86
+ export function defaultProjectionFields(active, resourceName) {
81
87
  const activeResource = lookupResource(active, resourceName);
88
+ if (activeResource === undefined) {
89
+ return [];
90
+ }
91
+ const fields = [];
92
+ for (const [fieldName, field] of Object.entries(activeResource.fields)) {
93
+ if (field.kind === "scalar" &&
94
+ field.capabilities.select === true &&
95
+ field.governed !== true) {
96
+ fields.push(fieldName);
97
+ }
98
+ }
99
+ return fields;
100
+ }
101
+ function defaultProjectionLevel(core, model, active, compute, resourceName) {
82
102
  const adapterSelect = [];
83
103
  const requested = [];
84
104
  const computed = [];
85
- if (activeResource !== undefined) {
86
- for (const [fieldName, field] of Object.entries(activeResource.fields)) {
87
- if (field.kind !== "scalar" || field.capabilities.select !== true) {
88
- continue;
89
- }
90
- addScalarProjection(core, model, active, compute, resourceName, fieldName, adapterSelect, requested, computed);
91
- }
105
+ for (const fieldName of defaultProjectionFields(active, resourceName)) {
106
+ addScalarProjection(core, model, active, compute, resourceName, fieldName, adapterSelect, requested, computed);
92
107
  }
93
108
  return {
94
109
  select: adapterSelect,
@@ -156,6 +171,12 @@ function planSelectLevel(core, model, active, compute, resourceName, select, col
156
171
  }
157
172
  for (const entry of select) {
158
173
  if (typeof entry === "string") {
174
+ if (entry === "$defaults") {
175
+ for (const fieldName of defaultProjectionFields(active, resourceName)) {
176
+ addScalarProjection(core, model, active, compute, resourceName, fieldName, adapterSelect, requested, computed);
177
+ }
178
+ continue;
179
+ }
159
180
  if (entry === "$count") {
160
181
  adapterSelect.push(entry);
161
182
  if (collectReducers) {
@@ -280,7 +301,170 @@ export function planReadOperation(core, model, active, compute, request, args) {
280
301
  materialize: defaults.plan.computed.length > 0,
281
302
  };
282
303
  }
283
- async function materializeRelation(active, compute, request, relation, value, contextFactory) {
304
+ function resolveReadLevel(active, compute, plan, tail) {
305
+ const resource = lookupResource(active, plan.resource);
306
+ if (resource === undefined) {
307
+ return undefined;
308
+ }
309
+ const stages = [];
310
+ for (const fieldName of plan.computed) {
311
+ const field = lookupField(resource, fieldName);
312
+ const stage = readCompute(compute?.[plan.resource]?.[fieldName]?.read);
313
+ if (field?.kind !== "scalar" || stage === undefined) {
314
+ continue;
315
+ }
316
+ stages.push({
317
+ field: fieldName,
318
+ definition: field,
319
+ compute: stage.compute,
320
+ });
321
+ }
322
+ const relations = [];
323
+ let restFree = true;
324
+ for (const relation of [...plan.relations].reverse()) {
325
+ const level = resolveReadLevel(active, compute, relation.projection, tail && restFree);
326
+ relations.unshift({ relation, level });
327
+ restFree &&= level?.computeFree ?? true;
328
+ }
329
+ return {
330
+ plan,
331
+ stages,
332
+ relations,
333
+ computeFree: stages.length === 0 && restFree,
334
+ atOnce: tail && stages.length <= 1 && restFree,
335
+ plainKeys: plan.requested.every((field) => !(field in Object.prototype)),
336
+ };
337
+ }
338
+ function isNestedContainer(value) {
339
+ return (value !== null &&
340
+ typeof value === "object" &&
341
+ !(value instanceof Date) &&
342
+ !(value instanceof Uint8Array));
343
+ }
344
+ function setOwn(target, key, value) {
345
+ if (key in target) {
346
+ Object.defineProperty(target, key, {
347
+ value,
348
+ writable: true,
349
+ enumerable: true,
350
+ configurable: true,
351
+ });
352
+ return;
353
+ }
354
+ target[key] = value;
355
+ }
356
+ function answerOf(level, record) {
357
+ const answer = {};
358
+ for (const fieldName of level.plan.requested) {
359
+ if (!Object.hasOwn(record, fieldName)) {
360
+ continue;
361
+ }
362
+ if (level.plainKeys) {
363
+ answer[fieldName] = record[fieldName];
364
+ }
365
+ else {
366
+ setOwn(answer, fieldName, record[fieldName]);
367
+ }
368
+ }
369
+ return answer;
370
+ }
371
+ function heldReadValue(active, level, stage, value) {
372
+ const validation = normalizeScalarFieldValue(active, stage.definition, value, "runtime", [
373
+ "resources",
374
+ level.plan.resource,
375
+ "fields",
376
+ stage.field,
377
+ "pipelines",
378
+ "compute",
379
+ "read",
380
+ ]);
381
+ if (!validation.ok) {
382
+ throw new AvComputedValueError(level.plan.resource, stage.field, "read", validation.issues);
383
+ }
384
+ return validation.value;
385
+ }
386
+ function projectedAtOnce(level, value) {
387
+ if (!isRecord(value) || level === undefined) {
388
+ return value;
389
+ }
390
+ const record = { ...value };
391
+ relationsAtOnce(level, record);
392
+ return answerOf(level, record);
393
+ }
394
+ function relationsAtOnce(level, record) {
395
+ for (const { relation, level: nested } of level.relations) {
396
+ if (!Object.hasOwn(record, relation.field)) {
397
+ continue;
398
+ }
399
+ const value = record[relation.field];
400
+ if (value === null || value === undefined) {
401
+ continue;
402
+ }
403
+ if (relation.cardinality === "many") {
404
+ if (Array.isArray(value)) {
405
+ record[relation.field] = Array.from(value, (entry) => projectedAtOnce(nested, entry));
406
+ }
407
+ continue;
408
+ }
409
+ record[relation.field] = projectedAtOnce(nested, value);
410
+ }
411
+ }
412
+ function computedAtOnce(active, level, stage, value, contextFactory) {
413
+ const record = { ...value };
414
+ const view = frozenCopy(record);
415
+ let computedValue;
416
+ try {
417
+ computedValue = stage.compute({
418
+ field: stage.field,
419
+ value: view[stage.field],
420
+ record: view,
421
+ ctx: contextFactory(),
422
+ });
423
+ }
424
+ catch (error) {
425
+ return Promise.reject(error);
426
+ }
427
+ const finish = (returned) => {
428
+ if (returned !== undefined) {
429
+ record[stage.field] = heldReadValue(active, level, stage, returned);
430
+ }
431
+ relationsAtOnce(level, record);
432
+ return answerOf(level, record);
433
+ };
434
+ const later = (error) => Promise.resolve().then(() => {
435
+ throw error;
436
+ });
437
+ let waits;
438
+ try {
439
+ waits = isThenable(computedValue);
440
+ }
441
+ catch (error) {
442
+ return later(error);
443
+ }
444
+ if (waits) {
445
+ const pending = computedValue;
446
+ return (async () => finish(await pending))();
447
+ }
448
+ try {
449
+ return finish(computedValue);
450
+ }
451
+ catch (error) {
452
+ return later(error);
453
+ }
454
+ }
455
+ function materializeRecord(active, level, value, contextFactory) {
456
+ if (level?.atOnce !== true) {
457
+ return materializeInTurn(active, level, value, contextFactory);
458
+ }
459
+ if (!isRecord(value)) {
460
+ return value;
461
+ }
462
+ const [stage] = level.stages;
463
+ return stage === undefined
464
+ ? projectedAtOnce(level, value)
465
+ : computedAtOnce(active, level, stage, value, contextFactory);
466
+ }
467
+ async function materializeRelation(active, level, relation, value, contextFactory) {
284
468
  if (value === null || value === undefined) {
285
469
  return value;
286
470
  }
@@ -288,65 +472,62 @@ async function materializeRelation(active, compute, request, relation, value, co
288
472
  if (!Array.isArray(value)) {
289
473
  return value;
290
474
  }
291
- return Promise.all(value.map((entry) => materializeRecord(active, compute, request, relation.projection, entry, contextFactory)));
475
+ return Promise.all(value.map((entry) => materializeRecord(active, level, entry, contextFactory)));
292
476
  }
293
- return materializeRecord(active, compute, request, relation.projection, value, contextFactory);
477
+ return materializeRecord(active, level, value, contextFactory);
294
478
  }
295
- async function materializeRecord(active, compute, request, plan, value, contextFactory) {
296
- if (!isRecord(value)) {
297
- return value;
298
- }
299
- const resource = lookupResource(active, plan.resource);
300
- if (resource === undefined) {
479
+ async function materializeInTurn(active, level, value, contextFactory) {
480
+ if (!isRecord(value) || level === undefined) {
301
481
  return value;
302
482
  }
483
+ const { stages } = level;
303
484
  const record = { ...value };
304
- for (const fieldName of plan.computed) {
305
- const field = lookupField(resource, fieldName);
306
- const stage = readCompute(compute?.[plan.resource]?.[fieldName]?.read);
307
- if (field?.kind !== "scalar" || stage === undefined) {
308
- continue;
485
+ let told;
486
+ if (stages.length > 1) {
487
+ told = { ...record };
488
+ for (const key of Object.keys(told)) {
489
+ const nested = told[key];
490
+ if (isNestedContainer(nested)) {
491
+ told[key] = frozenCopy(nested, true);
492
+ }
309
493
  }
494
+ }
495
+ for (const stage of stages) {
496
+ const view = frozenCopy(told ?? record);
310
497
  const computedValue = await stage.compute({
311
- field: fieldName,
312
- value: record[fieldName],
313
- record,
498
+ field: stage.field,
499
+ value: view[stage.field],
500
+ record: view,
314
501
  ctx: contextFactory(),
315
502
  });
316
503
  if (computedValue === undefined) {
317
504
  continue;
318
505
  }
319
- const validation = normalizeScalarFieldValue(active, field, computedValue, "runtime", [
320
- "resources",
321
- plan.resource,
322
- "fields",
323
- fieldName,
324
- "pipelines",
325
- "compute",
326
- "read",
327
- ]);
328
- if (!validation.ok) {
329
- throw new AvComputedValueError(plan.resource, fieldName, "read", validation.issues);
506
+ const held = heldReadValue(active, level, stage, computedValue);
507
+ record[stage.field] = held;
508
+ if (told !== undefined) {
509
+ told[stage.field] = held;
330
510
  }
331
- record[fieldName] = validation.value;
332
511
  }
333
- for (const relation of plan.relations) {
512
+ for (const { relation, level: nested } of level.relations) {
334
513
  if (!Object.hasOwn(record, relation.field)) {
335
514
  continue;
336
515
  }
337
- record[relation.field] = await materializeRelation(active, compute, request, relation, record[relation.field], contextFactory);
516
+ record[relation.field] = await materializeRelation(active, nested, relation, record[relation.field], contextFactory);
338
517
  }
339
- return Object.fromEntries(plan.requested
340
- .filter((fieldName) => Object.hasOwn(record, fieldName))
341
- .map((fieldName) => [fieldName, record[fieldName]]));
518
+ return answerOf(level, record);
342
519
  }
343
- export async function materializeReadOperation(active, compute, request, plan, value, contextFactory) {
520
+ export async function materializeReadOperation(active, compute, _request, plan, value, contextFactory) {
344
521
  const projection = plan.projection;
345
522
  if (!plan.materialize || projection === undefined) {
346
523
  return value;
347
524
  }
525
+ const level = resolveReadLevel(active, compute, projection, true);
348
526
  if (Array.isArray(value)) {
349
- return Promise.all(value.map((entry) => materializeRecord(active, compute, request, projection, entry, contextFactory)));
527
+ const rows = value.map((entry) => materializeRecord(active, level, entry, contextFactory));
528
+ return rows.some((row) => row instanceof Promise)
529
+ ? Promise.all(rows)
530
+ : Array.from(rows);
350
531
  }
351
- return materializeRecord(active, compute, request, projection, value, contextFactory);
532
+ return materializeRecord(active, level, value, contextFactory);
352
533
  }
@@ -1,7 +1,8 @@
1
1
  import type { AvValidationIssue } from "../operations/validation-code.js";
2
2
  /**
3
3
  * What the diagnostics channel receives when a computed value — a read or write
4
- * compute stage's return — is one its Contract refuses: the developer's broken code,
4
+ * compute stage's return — is one its Contract refuses, or a `compute.create`
5
+ * stage returned `undefined` for a field a create cannot do without (rc.2): the developer's broken code,
5
6
  * never the caller's. It is thrown, not a deliberate outcome, so the framework's
6
7
  * boundary answers the caller the generic `A3000` and reports this error, with the
7
8
  * issues, exactly once.
@@ -9,5 +10,5 @@ import type { AvValidationIssue } from "../operations/validation-code.js";
9
10
  export declare class AvComputedValueError extends Error {
10
11
  readonly issues: readonly AvValidationIssue[];
11
12
  readonly name = "AvComputedValueError";
12
- constructor(resource: string, field: string, stage: "read" | "create" | "update", issues: readonly AvValidationIssue[]);
13
+ constructor(resource: string, field: string, stage: "read" | "create" | "update", issues: readonly AvValidationIssue[], message?: string);
13
14
  }
@@ -1,9 +1,10 @@
1
1
  export class AvComputedValueError extends Error {
2
2
  issues;
3
3
  name = "AvComputedValueError";
4
- constructor(resource, field, stage, issues) {
4
+ constructor(resource, field, stage, issues, message) {
5
5
  const [first] = issues;
6
- super(`The compute.${stage} stage of ${resource}.${field} returned a value its Contract refuses${first === undefined ? "." : ` (${first.code}: ${first.message})`}`);
6
+ super(message ??
7
+ `The compute.${stage} stage of ${resource}.${field} returned a value its Contract refuses${first === undefined ? "." : ` (${first.code}: ${first.message})`}`);
7
8
  this.issues = issues;
8
9
  }
9
10
  }
@@ -7,7 +7,7 @@ import type { AvOperationFamily } from "../operations/operation-identity.js";
7
7
  import { type AvDiagnosticsSink } from "./diagnostics-reporter.js";
8
8
  import type { AvComputeContext } from "./field-compute.js";
9
9
  import type { MisuseReporter } from "./misuse-reporter.js";
10
- import type { ApplicationOperationRequest } from "./operation-request.js";
10
+ import type { AvApplicationOperationRequest } from "./operation-request.js";
11
11
  import type { AvOperationResponse } from "./operation-response.js";
12
12
  import type { AvContext, AvTransactionContext, AvTransportContext } from "./pipeline.js";
13
13
  import type { AvState } from "./request-state.js";
@@ -35,8 +35,8 @@ export type ContextFacts = {
35
35
  readonly $args: unknown;
36
36
  };
37
37
  /** Runs one raw application-origin call in `transaction`, or standalone. Total. */
38
- export type RawOperationRunner<M extends AvAdapterModel> = (request: ApplicationOperationRequest, transaction: AvAdapterTransactionExecutor<M> | undefined) => Promise<AvOperationResponse>;
39
- export type ContextExecutorDependencies<M extends AvAdapterModel> = {
38
+ type RawOperationRunner<M extends AvAdapterModel> = (request: AvApplicationOperationRequest, transaction: AvAdapterTransactionExecutor<M> | undefined) => Promise<AvOperationResponse>;
39
+ type ContextExecutorDependencies<M extends AvAdapterModel> = {
40
40
  /** The model, as construction read it once: the ctx's Resources. */
41
41
  readonly model: M;
42
42
  readonly adapter: AvAdapter<M>;
@@ -57,3 +57,4 @@ export type ContextExecutor<M extends AvAdapterModel = AvAdapterModel> = {
57
57
  };
58
58
  /** Builds the ctx factory of one Framework over its model. */
59
59
  export declare function createContextExecutor<M extends AvAdapterModel>(dependencies: ContextExecutorDependencies<M>): ContextExecutor<M>;
60
+ export {};
@@ -195,9 +195,10 @@ export function createContextExecutor(dependencies) {
195
195
  const contextOf = (prototype, scope, facts, readOnly = false) => {
196
196
  const context = Object.create(prototype);
197
197
  Object.defineProperty(context, STATE, {
198
- value: { scope, facts, resources: new Map() },
198
+ value: { scope, facts, resources: undefined },
199
199
  });
200
- for (const [key, value] of Object.entries(facts)) {
200
+ for (const key of Object.keys(facts)) {
201
+ const value = facts[key];
201
202
  if (value !== undefined) {
202
203
  Object.defineProperty(context, key, { value, enumerable: true });
203
204
  }
@@ -232,6 +233,7 @@ export function createContextExecutor(dependencies) {
232
233
  Object.defineProperty(prototype, resource, {
233
234
  get() {
234
235
  const state = stateOf(this);
236
+ state.resources ??= new Map();
235
237
  let tree = state.resources.get(resource);
236
238
  if (tree === undefined) {
237
239
  tree = resourceTree(state.scope, resource, readOnly);
@@ -0,0 +1,10 @@
1
+ /** The registered symbol every copy of this major brands class `name` with. */
2
+ export declare function coreBrandOf(name: string): symbol;
3
+ /** Whether `value` carries `brand`, wherever it was made: one `in`. */
4
+ export declare function hasCoreBrand(value: unknown, brand: symbol): boolean;
5
+ /**
6
+ * Brands `type`'s prototype as `name` and makes `instanceof type` read the brand.
7
+ * A developer's own subclass of `type` inherits the static `Symbol.hasInstance`, so
8
+ * on any constructor but `type` itself it answers as `instanceof` always does.
9
+ */
10
+ export declare function brandCoreClass(type: abstract new (...args: never[]) => object, name: string): symbol;
@@ -0,0 +1,21 @@
1
+ import { CORE_VERSION } from "../prebuilt/core-version.generated.js";
2
+ const CORE_MAJOR = CORE_VERSION.slice(0, CORE_VERSION.indexOf("."));
3
+ export function coreBrandOf(name) {
4
+ return Symbol.for(`aventara.core.${name}@${CORE_MAJOR}`);
5
+ }
6
+ export function hasCoreBrand(value, brand) {
7
+ return typeof value === "object" && value !== null && brand in value;
8
+ }
9
+ const ordinaryHasInstance = Function.prototype[Symbol.hasInstance];
10
+ export function brandCoreClass(type, name) {
11
+ const brand = coreBrandOf(name);
12
+ Object.defineProperty(type.prototype, brand, { value: true });
13
+ Object.defineProperty(type, Symbol.hasInstance, {
14
+ value: function hasInstance(value) {
15
+ return this === type
16
+ ? hasCoreBrand(value, brand)
17
+ : ordinaryHasInstance.call(this, value);
18
+ },
19
+ });
20
+ return brand;
21
+ }
@@ -1,20 +1,32 @@
1
1
  import type { AvContract } from "../contracts/contract.js";
2
+ import type { AvCreateRequirements } from "../contracts/create-requirements.js";
2
3
  import type { AvOperationIdentity } from "../operations/operation-identity.js";
3
4
  import type { AvValidationIssue } from "../operations/validation-code.js";
4
5
  import type { ReferentialActionTable } from "./referential-action.js";
5
6
  type Path = readonly (string | number)[];
7
+ /** One required field a `compute.create` stage was to fill and left missing. */
8
+ type ComputedRequirementGap = {
9
+ readonly resource: string;
10
+ readonly field: string;
11
+ readonly issue: AvValidationIssue;
12
+ };
6
13
  /**
7
- * What the Adapter stated beside its model that the check reads: its
8
- * referential edges, for the fields that hold each reference. Read once when
9
- * the Framework is constructed. The requirements themselves are the active
10
- * Contract's.
14
+ * What the Adapter stated that the checks read: its referential edges, for the
15
+ * fields that hold each reference, and its own create requirements per
16
+ * Resource, before any layer projected them (what write compute must not leave
17
+ * missing). Read once when the Framework is constructed. The requirements the
18
+ * caller is held to are the active Contract's.
11
19
  */
12
20
  export type RecordWriteFacts = {
13
21
  readonly references: ReferentialActionTable;
22
+ readonly stated: (resource: string) => AvCreateRequirements | undefined;
14
23
  };
15
24
  /** The facts an Adapter stated, read off it once; an absent table states nothing. */
16
25
  export declare function recordWriteFactsOf(adapter: {
17
26
  readonly referentialActions?: ReferentialActionTable;
27
+ readonly model?: {
28
+ readonly resources: Readonly<Record<string, unknown>>;
29
+ };
18
30
  }): RecordWriteFacts;
19
31
  /**
20
32
  * The `V1000` issues for every create position in one operation's arguments
@@ -24,7 +36,21 @@ export declare function recordWriteFactsOf(adapter: {
24
36
  * reference both, in argument order. Empty when there are none. Total over
25
37
  * malformed input.
26
38
  */
27
- export declare function createRequirementIssues(contract: AvContract, facts: RecordWriteFacts, request: AvOperationIdentity & {
39
+ export declare function createRequirementIssues(contract: AvContract, facts: Pick<RecordWriteFacts, "references">, request: AvOperationIdentity & {
28
40
  readonly resource: string;
29
41
  }, args: unknown, argumentsPath: Path): readonly AvValidationIssue[];
42
+ /**
43
+ * Every required field a `compute.create` stage was to fill and that is still
44
+ * missing after write compute, at every create position of one operation's
45
+ * arguments (`create.*`'s `data`, `upsert`'s `create`, every nested create),
46
+ * in argument order, read against the Adapter's own statement of each
47
+ * Resource's create requirements; `computed` names the fields a Resource's
48
+ * `compute.create` stages fill.
49
+ * A field the parent supplies to a nested create, a group whose relation the
50
+ * record writes, and a value the caller sent are not missing. Empty when
51
+ * nothing is.
52
+ */
53
+ export declare function computedRequirementGapsOf(contract: AvContract, facts: RecordWriteFacts, request: AvOperationIdentity & {
54
+ readonly resource: string;
55
+ }, args: unknown, argumentsPath: Path, computed: (resource: string) => ReadonlySet<string>): readonly ComputedRequirementGap[];
30
56
  export {};