@aventara/core 1.0.0-rc.0 → 1.0.0-rc.2

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 (267) hide show
  1. package/CHANGELOG.md +1434 -0
  2. package/ERRORS.md +142 -0
  3. package/README.md +247 -57
  4. package/dist/adapters/adapter-discovery-diagnostic.d.ts +4 -4
  5. package/dist/adapters/adapter-discovery-diagnostic.guidance.d.ts +6 -0
  6. package/dist/adapters/adapter-discovery-diagnostic.guidance.js +7 -0
  7. package/dist/adapters/adapter-field.d.ts +25 -11
  8. package/dist/adapters/adapter-identifier.d.ts +6 -6
  9. package/dist/adapters/adapter-model.d.ts +18 -9
  10. package/dist/adapters/adapter-operation-executor.interface.d.ts +4 -4
  11. package/dist/adapters/adapter-operation.d.ts +3 -3
  12. package/dist/adapters/adapter-resource.d.ts +18 -9
  13. package/dist/adapters/adapter-sql-statement.d.ts +19 -0
  14. package/dist/adapters/adapter-transaction-executor.interface.d.ts +19 -0
  15. package/dist/adapters/adapter.interface.d.ts +59 -29
  16. package/dist/avz/avz-check.factory.d.ts +83 -0
  17. package/dist/avz/avz-check.factory.js +116 -0
  18. package/dist/avz/avz-check.registry.d.ts +35 -0
  19. package/dist/avz/avz-check.registry.js +9 -0
  20. package/dist/avz/avz.d.ts +203 -0
  21. package/dist/{json → avz}/avz.js +150 -8
  22. package/dist/{json → avz}/index.d.ts +2 -1
  23. package/dist/{json → avz}/json-shape.registry.d.ts +7 -7
  24. package/dist/{json → avz}/zod-issue.translator.d.ts +8 -2
  25. package/dist/{json → avz}/zod-issue.translator.js +7 -0
  26. package/dist/compiler/contract-compiler-diagnostic.d.ts +31 -5
  27. package/dist/compiler/contract-compiler-diagnostic.guidance.d.ts +6 -0
  28. package/dist/compiler/contract-compiler-diagnostic.guidance.js +97 -0
  29. package/dist/compiler/contract.compiler.d.ts +18 -18
  30. package/dist/compiler/contract.compiler.js +637 -442
  31. package/dist/compiler/create-requirements.projector.d.ts +49 -0
  32. package/dist/compiler/create-requirements.projector.js +423 -0
  33. package/dist/compiler/field-validator.compiler.d.ts +47 -0
  34. package/dist/compiler/field-validator.compiler.js +238 -0
  35. package/dist/config/any-framework-config.d.ts +19 -12
  36. package/dist/config/computed-fields.d.ts +62 -0
  37. package/dist/config/computed-fields.js +80 -0
  38. package/dist/config/config-diagnostic.d.ts +11 -4
  39. package/dist/config/config-diagnostic.guidance.d.ts +6 -0
  40. package/dist/config/config-diagnostic.guidance.js +32 -0
  41. package/dist/config/config-layer.d.ts +15 -6
  42. package/dist/config/config.resolver.d.ts +74 -31
  43. package/dist/config/config.resolver.js +108 -44
  44. package/dist/config/config.validator.d.ts +7 -7
  45. package/dist/config/config.validator.js +581 -72
  46. package/dist/config/define-resource.d.ts +57 -0
  47. package/dist/config/define-resource.js +14 -0
  48. package/dist/config/effective-fields.d.ts +19 -23
  49. package/dist/config/entrypoint.normalizer.d.ts +1 -1
  50. package/dist/config/exact-framework-config.d.ts +308 -0
  51. package/dist/config/field-compute.resolver.d.ts +21 -0
  52. package/dist/config/field-compute.resolver.js +123 -0
  53. package/dist/config/field-pipeline-config.d.ts +47 -0
  54. package/dist/config/forced-operation.validator.d.ts +10 -0
  55. package/dist/config/forced-operation.validator.js +66 -0
  56. package/dist/config/framework-config.d.ts +111 -39
  57. package/dist/config/framework-exemptions-config.d.ts +91 -0
  58. package/dist/config/framework-exemptions-config.js +1 -0
  59. package/dist/config/framework-field-definition.d.ts +78 -0
  60. package/dist/config/framework-field-definition.js +28 -0
  61. package/dist/config/framework-resources-config.d.ts +122 -0
  62. package/dist/config/framework-resources-config.js +1 -0
  63. package/dist/config/pipeline-config.d.ts +56 -20
  64. package/dist/config/pipeline-tree.resolver.d.ts +79 -0
  65. package/dist/config/pipeline-tree.resolver.js +220 -0
  66. package/dist/config/stage-type.eraser.d.ts +65 -0
  67. package/dist/config/stage-type.eraser.js +1 -0
  68. package/dist/contracts/capability.d.ts +21 -12
  69. package/dist/contracts/capability.js +2 -0
  70. package/dist/contracts/client-contract-structure.validator.d.ts +388 -63
  71. package/dist/contracts/client-contract-structure.validator.js +156 -10
  72. package/dist/contracts/contract-canonicalizer.d.ts +26 -3
  73. package/dist/contracts/contract-canonicalizer.js +156 -29
  74. package/dist/contracts/contract-hash.d.ts +12 -7
  75. package/dist/contracts/contract-hash.js +3 -2
  76. package/dist/contracts/contract-limits.d.ts +4 -1
  77. package/dist/contracts/contract-limits.js +1 -0
  78. package/dist/contracts/contract-lookup.d.ts +5 -5
  79. package/dist/contracts/contract-protocol.d.ts +4 -4
  80. package/dist/contracts/contract.d.ts +24 -16
  81. package/dist/contracts/create-requirements.d.ts +35 -0
  82. package/dist/contracts/create-requirements.js +1 -0
  83. package/dist/contracts/enum-definition.d.ts +1 -1
  84. package/dist/contracts/field-check.d.ts +101 -0
  85. package/dist/contracts/field-check.js +1 -0
  86. package/dist/contracts/field.d.ts +81 -42
  87. package/dist/contracts/identifier.d.ts +4 -4
  88. package/dist/contracts/json-shape.d.ts +12 -1
  89. package/dist/contracts/lifecycle-trait.d.ts +2 -2
  90. package/dist/contracts/resource-operations.d.ts +28 -28
  91. package/dist/contracts/resource.d.ts +15 -9
  92. package/dist/contracts/scalar-value-type.d.ts +15 -15
  93. package/dist/contracts/scalar.d.ts +3 -3
  94. package/dist/contracts/transaction-capability.d.ts +1 -1
  95. package/dist/contracts/wire-scalar-format.d.ts +4 -4
  96. package/dist/framework/contract-view.d.ts +213 -147
  97. package/dist/framework/framework-construction.error.d.ts +19 -10
  98. package/dist/framework/framework-construction.error.js +7 -3
  99. package/dist/framework/framework.d.ts +47 -23
  100. package/dist/framework/framework.factory.d.ts +8 -6
  101. package/dist/framework/framework.factory.js +49 -22
  102. package/dist/framework/operation-facade.d.ts +123 -52
  103. package/dist/framework/operation-facade.js +9 -1
  104. package/dist/index.d.ts +57 -50
  105. package/dist/index.js +7 -6
  106. package/dist/internal.d.ts +17 -10
  107. package/dist/internal.js +4 -1
  108. package/dist/operations/database-refusal.d.ts +51 -0
  109. package/dist/operations/database-refusal.js +45 -0
  110. package/dist/operations/operation-arguments.d.ts +343 -207
  111. package/dist/operations/operation-call.d.ts +27 -28
  112. package/dist/operations/operation-identity.d.ts +10 -10
  113. package/dist/operations/operation-result.d.ts +21 -21
  114. package/dist/operations/operation-validator-core.d.ts +6 -6
  115. package/dist/operations/operation-validator-core.js +99 -6
  116. package/dist/operations/operation-validator.d.ts +9 -9
  117. package/dist/operations/projection-scope.resolver.d.ts +6 -6
  118. package/dist/operations/structural-limits.walker.d.ts +6 -6
  119. package/dist/operations/structural-limits.walker.js +145 -0
  120. package/dist/operations/validation-code.d.ts +11 -6
  121. package/dist/operations/validation-code.guidance.d.ts +6 -0
  122. package/dist/operations/validation-code.guidance.js +90 -0
  123. package/dist/operations/validation-code.js +4 -0
  124. package/dist/operations/write-scope.resolver.d.ts +10 -6
  125. package/dist/operations/write-scope.resolver.js +2 -0
  126. package/dist/protocol/absent-route.responder.d.ts +13 -12
  127. package/dist/protocol/absent-route.responder.js +19 -19
  128. package/dist/protocol/contract-document.responder.d.ts +3 -3
  129. package/dist/protocol/contract-document.responder.js +2 -2
  130. package/dist/protocol/http-request.decoder.d.ts +17 -13
  131. package/dist/protocol/http-request.decoder.js +10 -10
  132. package/dist/protocol/http-request.reader.d.ts +3 -3
  133. package/dist/protocol/http-response.encoder.d.ts +4 -4
  134. package/dist/protocol/http-response.encoder.js +94 -55
  135. package/dist/protocol/http-status.table.d.ts +2 -2
  136. package/dist/protocol/operation-response.guard.d.ts +2 -2
  137. package/dist/protocol/protocol-surface.d.ts +4 -4
  138. package/dist/protocol/protocol.binder.d.ts +50 -27
  139. package/dist/protocol/protocol.binder.js +12 -9
  140. package/dist/protocol/protocol.handler.d.ts +22 -13
  141. package/dist/protocol/protocol.handler.js +91 -17
  142. package/dist/protocol/unmounted-route.error.d.ts +4 -4
  143. package/dist/protocol/unmounted-route.error.js +2 -2
  144. package/dist/runtime/caller-data.copier.d.ts +22 -5
  145. package/dist/runtime/caller-data.copier.js +31 -14
  146. package/dist/runtime/caller-data.door.d.ts +17 -11
  147. package/dist/runtime/caller-data.door.js +6 -4
  148. package/dist/runtime/computed-read-runtime.d.ts +7 -6
  149. package/dist/runtime/computed-read-runtime.js +76 -50
  150. package/dist/runtime/computed-value.error.d.ts +7 -6
  151. package/dist/runtime/computed-value.error.js +5 -4
  152. package/dist/runtime/context-executor.runtime.d.ts +59 -0
  153. package/dist/runtime/context-executor.runtime.js +275 -0
  154. package/dist/runtime/create-requirement.d.ts +44 -79
  155. package/dist/runtime/create-requirement.js +213 -73
  156. package/dist/runtime/decimal.d.ts +2 -2
  157. package/dist/runtime/decimal.js +1 -1
  158. package/dist/runtime/diagnostics-reporter.d.ts +54 -27
  159. package/dist/runtime/diagnostics-reporter.js +24 -0
  160. package/dist/runtime/error-boundary.d.ts +65 -8
  161. package/dist/runtime/error-boundary.js +49 -19
  162. package/dist/runtime/error-guidance.d.ts +12 -0
  163. package/dist/runtime/error-guidance.js +1 -0
  164. package/dist/runtime/error.catalog.d.ts +49 -0
  165. package/dist/runtime/error.catalog.js +49 -0
  166. package/dist/runtime/execution-options.d.ts +10 -2
  167. package/dist/runtime/field-check.evaluator.d.ts +29 -0
  168. package/dist/runtime/field-check.evaluator.js +521 -0
  169. package/dist/runtime/field-compute.d.ts +64 -0
  170. package/dist/runtime/field-compute.js +1 -0
  171. package/dist/runtime/field-stage.plan.d.ts +15 -0
  172. package/dist/runtime/field-stage.plan.js +27 -0
  173. package/dist/runtime/field-stage.runtime.d.ts +37 -0
  174. package/dist/runtime/field-stage.runtime.js +147 -0
  175. package/dist/runtime/field-validator.runtime.d.ts +19 -0
  176. package/dist/runtime/field-validator.runtime.js +92 -0
  177. package/dist/runtime/framework-error-class.table.d.ts +33 -0
  178. package/dist/runtime/framework-error-class.table.js +25 -0
  179. package/dist/runtime/framework-error.d.ts +68 -8
  180. package/dist/runtime/framework-error.factory.d.ts +4 -0
  181. package/dist/runtime/framework-error.factory.js +15 -0
  182. package/dist/runtime/framework-error.js +23 -2
  183. package/dist/runtime/interceptor-next.error.d.ts +5 -0
  184. package/dist/runtime/interceptor-next.error.js +6 -0
  185. package/dist/runtime/json-value.d.ts +11 -6
  186. package/dist/runtime/level-lifecycle.runtime.d.ts +25 -0
  187. package/dist/runtime/level-lifecycle.runtime.js +39 -0
  188. package/dist/runtime/misuse-reporter.d.ts +12 -12
  189. package/dist/runtime/mutation-planner.d.ts +19 -10
  190. package/dist/runtime/mutation-planner.js +48 -35
  191. package/dist/runtime/nested-write.walker.d.ts +32 -0
  192. package/dist/runtime/nested-write.walker.js +73 -0
  193. package/dist/runtime/operation-code.guidance.d.ts +6 -0
  194. package/dist/runtime/operation-code.guidance.js +167 -0
  195. package/dist/runtime/operation-request.d.ts +33 -6
  196. package/dist/runtime/operation-response.d.ts +17 -17
  197. package/dist/runtime/operation-runtime.d.ts +127 -25
  198. package/dist/runtime/operation-runtime.js +441 -78
  199. package/dist/runtime/outcome-mapper.d.ts +16 -5
  200. package/dist/runtime/outcome-mapper.js +23 -6
  201. package/dist/runtime/output-validator.d.ts +10 -10
  202. package/dist/runtime/output-validator.js +3 -3
  203. package/dist/runtime/owned-execution.registry.d.ts +16 -6
  204. package/dist/runtime/pipe-output.validator.d.ts +43 -18
  205. package/dist/runtime/pipe-output.validator.js +15 -13
  206. package/dist/runtime/pipeline.d.ts +223 -34
  207. package/dist/runtime/readonly-value.d.ts +43 -0
  208. package/dist/runtime/readonly-value.js +150 -0
  209. package/dist/runtime/request-envelope.validator.d.ts +3 -3
  210. package/dist/runtime/request-envelope.validator.js +12 -7
  211. package/dist/runtime/request-id.d.ts +1 -1
  212. package/dist/runtime/request-state.d.ts +14 -0
  213. package/dist/runtime/request-state.js +1 -0
  214. package/dist/runtime/request-state.resolver.d.ts +12 -0
  215. package/dist/runtime/request-state.resolver.js +20 -0
  216. package/dist/runtime/scalar-runtime.d.ts +35 -16
  217. package/dist/runtime/scalar-runtime.js +102 -34
  218. package/dist/runtime/unsent-value.normalizer.d.ts +15 -0
  219. package/dist/runtime/unsent-value.normalizer.js +128 -0
  220. package/dist/transactions/deferred-operation.d.ts +35 -20
  221. package/dist/transactions/operation-arguments-encoder.d.ts +3 -3
  222. package/dist/transactions/operation-arguments-encoder.js +2 -2
  223. package/dist/transactions/operation-fingerprint.js +2 -2
  224. package/dist/transactions/sql-statement.d.ts +85 -0
  225. package/dist/transactions/sql-statement.js +47 -0
  226. package/dist/transactions/sql-statement.validator.d.ts +44 -0
  227. package/dist/transactions/sql-statement.validator.js +167 -0
  228. package/dist/transactions/transaction-envelope.d.ts +4 -4
  229. package/dist/transactions/transaction-integrity-error.d.ts +6 -6
  230. package/dist/transactions/transaction-integrity-error.js +5 -2
  231. package/dist/transactions/transaction-plan-assembler.d.ts +21 -11
  232. package/dist/transactions/transaction-plan-assembler.js +169 -32
  233. package/dist/transactions/transaction-plan-validator.d.ts +45 -20
  234. package/dist/transactions/transaction-plan-validator.js +96 -38
  235. package/dist/transactions/transaction-reference-collector.d.ts +5 -5
  236. package/dist/transactions/transaction-reference-resolver.d.ts +19 -2
  237. package/dist/transactions/transaction-reference-resolver.js +26 -14
  238. package/dist/transactions/transaction-reference-validator.d.ts +76 -4
  239. package/dist/transactions/transaction-reference-validator.js +129 -71
  240. package/dist/transactions/transaction-reference.d.ts +13 -13
  241. package/dist/transactions/transaction-reference.js +5 -0
  242. package/dist/transactions/transaction-request.d.ts +18 -5
  243. package/dist/transactions/transaction-response.d.ts +6 -6
  244. package/dist/transactions/transaction-runtime.d.ts +8 -7
  245. package/dist/transactions/transaction-runtime.js +191 -50
  246. package/dist/transactions/transaction-settlement.runtime.d.ts +51 -0
  247. package/dist/transactions/transaction-settlement.runtime.js +120 -0
  248. package/dist/transactions/transaction-slot-path-error.d.ts +4 -4
  249. package/dist/transactions/transaction-slot-path-error.js +2 -2
  250. package/dist/transactions/transaction-slot-writer.js +2 -2
  251. package/dist/transactions/transaction-stage.runtime.d.ts +82 -0
  252. package/dist/transactions/transaction-stage.runtime.js +126 -0
  253. package/package.json +9 -7
  254. package/src/runtime/field-check.evaluator.ts +720 -0
  255. package/dist/config/define-fields.d.ts +0 -42
  256. package/dist/config/define-fields.js +0 -3
  257. package/dist/config/framework-behaviors-config.d.ts +0 -30
  258. package/dist/config/framework-fields-config.d.ts +0 -42
  259. package/dist/config/framework-restrictions-config.d.ts +0 -142
  260. package/dist/json/avz.d.ts +0 -96
  261. package/dist/runtime/field-behavior.d.ts +0 -48
  262. /package/dist/{config/framework-behaviors-config.js → adapters/adapter-sql-statement.js} +0 -0
  263. /package/dist/{config/framework-fields-config.js → adapters/adapter-transaction-executor.interface.js} +0 -0
  264. /package/dist/{json → avz}/index.js +0 -0
  265. /package/dist/{json → avz}/json-shape.registry.js +0 -0
  266. /package/dist/config/{framework-restrictions-config.js → exact-framework-config.js} +0 -0
  267. /package/dist/{runtime/field-behavior.js → config/field-pipeline-config.js} +0 -0
@@ -21,18 +21,26 @@ function outcomeRule(operation) {
21
21
  const table = OUTCOME_TABLE;
22
22
  return table[`${operation.family}.${operation.variant}`];
23
23
  }
24
+ function notFound() {
25
+ return operationFailure("A2003", {
26
+ message: "No record matched the unique selector.",
27
+ });
28
+ }
24
29
  function absenceOutcome(absence) {
25
30
  switch (absence) {
26
31
  case "no-match":
27
32
  return operationNoMatch();
28
33
  case "not-found":
29
- return operationFailure("A2003", {
30
- message: "No record matched the unique selector.",
31
- });
34
+ return notFound();
32
35
  case undefined:
33
36
  return internalFailure();
34
37
  }
35
38
  }
39
+ export function uniqueMissFailure(operation, data) {
40
+ return data === null && outcomeRule(operation)?.absence === "not-found"
41
+ ? notFound()
42
+ : undefined;
43
+ }
36
44
  export function mapOperationOutcome(operation, data) {
37
45
  const rule = outcomeRule(operation);
38
46
  if (rule === undefined) {
@@ -52,6 +60,13 @@ function namesUnavailableOperation(issue) {
52
60
  const head = stepRelativeHead(issue);
53
61
  return issue.code === "V1006" && (head === "family" || head === "variant");
54
62
  }
63
+ export const VALIDATION_OUTCOME_MESSAGES = {
64
+ A2001: "The requested Resource is not available.",
65
+ A2002: "The requested operation is not available on this Resource.",
66
+ A2004: "Operation arguments failed framework validation.",
67
+ A2007: "Operation arguments failed framework validation.",
68
+ A2009: "Operation arguments failed framework validation.",
69
+ };
55
70
  function validationCode(issues) {
56
71
  if (issues.some((issue) => issue.code !== "V1019" && stepRelativeHead(issue) === "resource")) {
57
72
  return "A2001";
@@ -68,14 +83,16 @@ function validationCode(issues) {
68
83
  }
69
84
  if (issues.some((issue) => issue.code === "V1013" ||
70
85
  issue.code === "V1014" ||
71
- issue.code === "V1015")) {
86
+ issue.code === "V1015" ||
87
+ issue.code === "V1021")) {
72
88
  return "A2009";
73
89
  }
74
90
  return "A2004";
75
91
  }
76
92
  export function mapValidationOutcome(issues) {
77
- return operationFailure(validationCode(issues), {
78
- message: "Operation arguments failed framework validation.",
93
+ const code = validationCode(issues);
94
+ return operationFailure(code, {
95
+ message: VALIDATION_OUTCOME_MESSAGES[code],
79
96
  issues,
80
97
  });
81
98
  }
@@ -1,14 +1,14 @@
1
- import type { Contract } from "../contracts/contract.js";
2
- import type { OperationIdentity } from "../operations/operation-identity.js";
3
- import type { ValidationIssue } from "../operations/validation-code.js";
1
+ import type { AvContract } from "../contracts/contract.js";
2
+ import type { AvOperationIdentity } from "../operations/operation-identity.js";
3
+ import type { AvValidationIssue } from "../operations/validation-code.js";
4
4
  import type { ReadProjectionPlan } from "./computed-read-runtime.js";
5
5
  export type OutputValidationResult = {
6
6
  readonly ok: true;
7
7
  } | {
8
8
  readonly ok: false;
9
- readonly issues: readonly ValidationIssue[];
9
+ readonly issues: readonly AvValidationIssue[];
10
10
  };
11
- type OutputOperation = OperationIdentity & {
11
+ type OutputOperation = AvOperationIdentity & {
12
12
  readonly resource: string;
13
13
  };
14
14
  /**
@@ -16,11 +16,11 @@ type OutputOperation = OperationIdentity & {
16
16
  * validation: whose result it was and what the validator found. The caller
17
17
  * receives the generic `A3000` and never this.
18
18
  */
19
- export declare class OutputValidationError extends Error {
20
- readonly issues: readonly ValidationIssue[];
21
- readonly name = "OutputValidationError";
22
- constructor(operation: OutputOperation, issues: readonly ValidationIssue[]);
19
+ export declare class AvOutputValidationError extends Error {
20
+ readonly issues: readonly AvValidationIssue[];
21
+ readonly name = "AvOutputValidationError";
22
+ constructor(operation: OutputOperation, issues: readonly AvValidationIssue[]);
23
23
  }
24
24
  /** Validate final operation output against fixed cardinality and executed projection. */
25
- export declare function validateOperationOutput(contract: Contract, operation: OutputOperation, projection: ReadProjectionPlan | undefined, value: unknown): OutputValidationResult;
25
+ export declare function validateOperationOutput(contract: AvContract, operation: OutputOperation, projection: ReadProjectionPlan | undefined, value: unknown): OutputValidationResult;
26
26
  export {};
@@ -1,5 +1,5 @@
1
1
  import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
2
- import { advertisedReducers } from "../contracts/field.js";
2
+ import { advertisedReducers, } from "../contracts/field.js";
3
3
  import { normalizeScalarFieldValue } from "./scalar-runtime.js";
4
4
  function issue(message, path = ["data"]) {
5
5
  return { ok: false, issues: [{ path, code: "V1001", message }] };
@@ -168,9 +168,9 @@ function validateProjection(contract, operation, projection, value) {
168
168
  ? validateExactRecord(contract, value, projection, ["data"])
169
169
  : { ok: true };
170
170
  }
171
- export class OutputValidationError extends Error {
171
+ export class AvOutputValidationError extends Error {
172
172
  issues;
173
- name = "OutputValidationError";
173
+ name = "AvOutputValidationError";
174
174
  constructor(operation, issues) {
175
175
  const [first] = issues;
176
176
  super(`The result of ${operation.resource}.${operation.family}.${operation.variant} does not satisfy its Contract${first === undefined
@@ -1,11 +1,21 @@
1
- import type { ClientTransactionRequest } from "../transactions/transaction-request.js";
2
- import type { TransactionResponse } from "../transactions/transaction-response.js";
3
- import type { ClientOperationRequest } from "./operation-request.js";
4
- import type { OperationResponse } from "./operation-response.js";
1
+ import type { AgentTransactionRequest, ClientTransactionRequest } from "../transactions/transaction-request.js";
2
+ import type { AvTransactionResponse } from "../transactions/transaction-response.js";
3
+ import type { AvCallerDataError } from "./caller-data.copier.js";
4
+ import type { RemoteOperationRequest } from "./operation-request.js";
5
+ import type { AvOperationResponse } from "./operation-response.js";
5
6
  /** The two entries that run a request the protocol decoded itself, uncopied. */
6
7
  export type OwnedExecution = {
7
- readonly execute: (request: ClientOperationRequest) => Promise<OperationResponse>;
8
- readonly executeTransaction: (request: ClientTransactionRequest) => Promise<TransactionResponse>;
8
+ /**
9
+ * Runs `request` uncopied; with `refused`, its arguments are a host's parsed body
10
+ * whose copy at the call failed, answered as the door answers that failure.
11
+ */
12
+ readonly execute: (request: RemoteOperationRequest, refused?: AvCallerDataError) => Promise<AvOperationResponse>;
13
+ /**
14
+ * Runs `request` uncopied; with `refused`, its plan is a host's parsed plan taken
15
+ * at the call, and these steps' arguments could not be copied there: each is
16
+ * answered at its turn as the door answers that failure.
17
+ */
18
+ readonly executeTransaction: (request: ClientTransactionRequest | AgentTransactionRequest, refused?: ReadonlyMap<number, AvCallerDataError>) => Promise<AvTransactionResponse>;
9
19
  };
10
20
  /** Records `framework`'s owned entries; called once, at construction. */
11
21
  export declare function recordOwnedExecution(framework: object, execution: OwnedExecution): void;
@@ -1,7 +1,8 @@
1
- import type { Contract, CoreContract } from "../contracts/contract.js";
2
- import type { OperationIdentity } from "../operations/operation-identity.js";
3
- import type { ValidationIssue } from "../operations/validation-code.js";
4
- import type { OperationFailureResponse } from "./operation-response.js";
1
+ import type { AvContract, AvContractCore } from "../contracts/contract.js";
2
+ import type { AvOperationIdentity } from "../operations/operation-identity.js";
3
+ import type { OperationValidationOptions } from "../operations/operation-validator.js";
4
+ import type { AvValidationIssue } from "../operations/validation-code.js";
5
+ import type { AvOperationFailureResponse } from "./operation-response.js";
5
6
  /**
6
7
  * The check a pipe's output passes before it can reach the Adapter.
7
8
  *
@@ -12,37 +13,61 @@ import type { OperationFailureResponse } from "./operation-response.js";
12
13
  * are held to the **server's** rules — the Core Contract, plus the fields the
13
14
  * active scope itself adds (they are virtual: computed, then stripped before
14
15
  * the Adapter call) — in the values' runtime forms (`bigint`, `Date`,
15
- * `Decimal`, `Uint8Array`), which is what every pipe receives.
16
+ * `AvDecimal`, `Uint8Array`), which is what every pipe receives.
16
17
  *
17
18
  * A refusal is the server's defect, not the caller's: `A3004
18
19
  * PIPE_OUTPUT_INVALID`, a 500 that tells the caller no more than any internal
19
20
  * failure does — {@link PIPE_OUTPUT_FAILURE_MESSAGE}, and the step in a plan.
20
21
  * The pipe, the operation, the first offending field and its V-code go to the
21
- * diagnostics channel only, as a {@link PipeOutputError}: they name server
22
+ * diagnostics channel only, as a {@link AvPipeOutputError}: they name server
22
23
  * internals — a pipe's function name, a field the caller's Contract hides.
23
24
  */
24
25
  /** The one text every `A3004` carries on the wire. */
25
26
  export declare const PIPE_OUTPUT_FAILURE_MESSAGE = "A server pipeline produced invalid arguments.";
27
+ /** The Contract a stage's output is held to: Core's Resources plus what `active` adds. */
28
+ export declare function serverContractFor(core: AvContractCore, active: AvContract): AvContract;
26
29
  /** The error the diagnostics channel receives for a refused pipe output. */
27
- export declare class PipeOutputError extends Error {
28
- readonly issues: readonly ValidationIssue[];
29
- readonly name = "PipeOutputError";
30
- constructor(message: string, issues: readonly ValidationIssue[]);
30
+ export declare class AvPipeOutputError extends Error {
31
+ readonly issues: readonly AvValidationIssue[];
32
+ readonly name = "AvPipeOutputError";
33
+ constructor(message: string, issues: readonly AvValidationIssue[]);
31
34
  }
35
+ /** A refused stage output: the `A3004` answer and what diagnostics are told. */
36
+ export type RefusedStageOutput = {
37
+ readonly response: AvOperationFailureResponse;
38
+ readonly error: AvPipeOutputError;
39
+ };
32
40
  /**
33
41
  * `undefined` when the pipe's output passes the server's rules; otherwise the
34
42
  * `A3004` failure, and the error the diagnostics channel is told.
35
43
  */
36
44
  export declare function refusePipeOutput(contracts: {
37
- readonly core: CoreContract;
38
- readonly active: Contract;
39
- }, request: OperationIdentity & {
45
+ readonly core: AvContractCore;
46
+ readonly active: AvContract;
47
+ }, request: AvOperationIdentity & {
40
48
  readonly resource: string;
41
49
  }, args: unknown,
42
50
  /** The pipe that produced `args`, named in the message by its function name. */
43
51
  pipe: unknown,
44
- /** Its position in the effective pipe list (root pipes first). */
45
- index: number): {
46
- readonly response: OperationFailureResponse;
47
- readonly error: PipeOutputError;
48
- } | undefined;
52
+ /** Its position in the effective pipe list (outer levels first). */
53
+ index: number,
54
+ /** A plan step's pipes run before BEGIN, its `$ref` slots unresolved: these admit them. */
55
+ options?: OperationValidationOptions): RefusedStageOutput | undefined;
56
+ /**
57
+ * {@link refusePipeOutput} for any stage that changed the arguments; `subject`
58
+ * names it in the diagnostic (`Field pipes`, `Transaction pipes`).
59
+ */
60
+ export declare function refuseStageOutput(contracts: {
61
+ readonly core: AvContractCore;
62
+ readonly active: AvContract;
63
+ }, request: AvOperationIdentity & {
64
+ readonly resource: string;
65
+ }, args: unknown, subject: string, options?: OperationValidationOptions): RefusedStageOutput | undefined;
66
+ /**
67
+ * The `A3004` for a stage output the server's rules raised `issues` against
68
+ * (paths under `["arguments", …]`), the first named in the diagnostic;
69
+ * `undefined` when there are none.
70
+ */
71
+ export declare function refusedStageOutput(request: AvOperationIdentity & {
72
+ readonly resource: string;
73
+ }, issues: readonly AvValidationIssue[], subject: string): RefusedStageOutput | undefined;
@@ -19,7 +19,7 @@ function serverContract(core, active) {
19
19
  return { ...core, resources };
20
20
  }
21
21
  const SERVER_VIEWS = new WeakMap();
22
- function serverContractFor(core, active) {
22
+ export function serverContractFor(core, active) {
23
23
  let view = SERVER_VIEWS.get(active);
24
24
  if (view === undefined) {
25
25
  view = serverContract(core, active);
@@ -27,15 +27,12 @@ function serverContractFor(core, active) {
27
27
  }
28
28
  return view;
29
29
  }
30
- function serverIssues(contract, request, args) {
31
- const validation = validateOperationArguments(contract, {
32
- ...request,
33
- arguments: args,
34
- });
30
+ function serverIssues(contract, request, args, options) {
31
+ const validation = validateOperationArguments(contract, { ...request, arguments: args }, options);
35
32
  if (!validation.ok) {
36
33
  return validation.issues;
37
34
  }
38
- const normalization = normalizeOperationScalarValues(contract, { ...request, arguments: validation.arguments }, "application");
35
+ const normalization = normalizeOperationScalarValues(contract, { ...request, arguments: validation.arguments }, "application", options);
39
36
  return normalization.ok ? [] : normalization.issues;
40
37
  }
41
38
  function pipeLabel(pipe, index) {
@@ -55,25 +52,30 @@ function fieldOf(issue) {
55
52
  const relative = path[0] === "arguments" ? path.slice(1) : path;
56
53
  return relative.length === 0 ? "(arguments)" : relative.join(".");
57
54
  }
58
- export class PipeOutputError extends Error {
55
+ export class AvPipeOutputError extends Error {
59
56
  issues;
60
- name = "PipeOutputError";
57
+ name = "AvPipeOutputError";
61
58
  constructor(message, issues) {
62
59
  super(message);
63
60
  this.issues = issues;
64
61
  }
65
62
  }
66
- export function refusePipeOutput(contracts, request, args, pipe, index) {
67
- const issues = serverIssues(serverContractFor(contracts.core, contracts.active), request, args);
63
+ export function refusePipeOutput(contracts, request, args, pipe, index, options) {
64
+ return refuseStageOutput(contracts, request, args, `Pipe ${pipeLabel(pipe, index)}`, options);
65
+ }
66
+ export function refuseStageOutput(contracts, request, args, subject, options) {
67
+ return refusedStageOutput(request, serverIssues(serverContractFor(contracts.core, contracts.active), request, args, options), subject);
68
+ }
69
+ export function refusedStageOutput(request, issues, subject) {
68
70
  const [first] = issues;
69
71
  if (first === undefined) {
70
72
  return undefined;
71
73
  }
72
- const message = `Pipe ${pipeLabel(pipe, index)} returned arguments for ${request.resource}.${request.family}.${request.variant} that the server contract refuses at "${fieldOf(first)}" (${first.code}: ${first.message})`;
74
+ const message = `${subject} returned arguments for ${request.resource}.${request.family}.${request.variant} that the server contract refuses at "${fieldOf(first)}" (${first.code}: ${first.message})`;
73
75
  return {
74
76
  response: operationFailure("A3004", {
75
77
  message: PIPE_OUTPUT_FAILURE_MESSAGE,
76
78
  }),
77
- error: new PipeOutputError(message, issues),
79
+ error: new AvPipeOutputError(message, issues),
78
80
  };
79
81
  }
@@ -1,54 +1,243 @@
1
- import type { AdapterModel } from "../adapters/adapter-model.js";
2
- import type { RequestOrigin } from "../config/config-layer.js";
3
- import type { FrameworkResourceKey } from "../config/framework-fields-config.js";
4
- import type { Contract } from "../contracts/contract.js";
5
- import type { OperationFamily } from "../operations/operation-identity.js";
6
- import type { FrameworkError } from "./framework-error.js";
1
+ import type { AvAdapterModel } from "../adapters/adapter-model.js";
2
+ import type { AvAdapterSqlValue } from "../adapters/adapter-sql-statement.js";
3
+ import type { AvPreComputeLift } from "../config/computed-fields.js";
4
+ import type { AvRequestOrigin } from "../config/config-layer.js";
5
+ import type { AvConfigResourceKey } from "../config/framework-field-definition.js";
6
+ import type { AvContract } from "../contracts/contract.js";
7
+ import type { AvApplicationScalarForms } from "../contracts/scalar-value-type.js";
8
+ import type { AvContractApplicationView, RequirementsLessComputed } from "../framework/contract-view.js";
9
+ import type { AvContextOperations } from "../framework/operation-facade.js";
10
+ import type { AvOperationArgumentsFor, AvResourceKey } from "../operations/operation-arguments.js";
11
+ import type { AvOperationFamily, AvOperationIdentity } from "../operations/operation-identity.js";
12
+ import type { AvTransactionReference } from "../transactions/transaction-reference.js";
13
+ import type { AvError } from "./framework-error.js";
14
+ import type { ArrayForm, AvDeepReadonly, AvDeepReadonlyLeaf } from "./readonly-value.js";
15
+ import type { AvState } from "./request-state.js";
7
16
  /**
8
17
  * What a pipeline is told about the HTTP request a client-origin operation arrived on.
9
18
  */
10
- export type PipelineTransportContext = {
19
+ export type AvTransportContext = {
11
20
  readonly method: "POST";
12
21
  readonly headers: Readonly<Record<string, string>>;
13
22
  };
14
- /** What a pipeline callback is told about the operation it is wrapping. */
15
- export type PipelineContext<M extends AdapterModel = AdapterModel> = {
16
- readonly contract: Contract;
17
- readonly origin: RequestOrigin;
18
- readonly resource: FrameworkResourceKey<M>;
19
- readonly family: OperationFamily;
20
- readonly variant: string;
21
- readonly args: unknown;
22
- readonly requestId: string;
23
- readonly transport?: PipelineTransportContext;
23
+ /** What a pipeline ctx states about the request, whatever the stage. */
24
+ type AvContextFacts = {
25
+ /** `"application"` for server code and ctx calls, `"client"` for a remote caller. */
26
+ readonly $origin: AvRequestOrigin;
27
+ readonly $requestId: string;
28
+ /** The HTTP request a client-origin operation arrived on, when it did. */
29
+ readonly $transport?: AvTransportContext;
30
+ /** The active Contract: the Application or the Client Contract. */
31
+ readonly $contract: AvContract;
32
+ /**
33
+ * The request's state: the one writable per-request space. Every stage of the
34
+ * request, a transaction's steps and transaction stages, and the ctx calls they
35
+ * make share this object. Seeded by the caller or the host; `{}` otherwise. Its
36
+ * members are the application's, declared by augmenting {@link AvState}.
37
+ */
38
+ readonly $state: AvState;
39
+ };
40
+ /**
41
+ * `ctx.$sql`: a developer SQL statement, written only as a tagged template —
42
+ * ``await ctx.$sql<Row>`insert into audit (actor) values (${actorId})` `` — run at
43
+ * once. Every interpolated value is bound as a parameter, never spliced into the
44
+ * text. It runs in the current transaction; outside one, as a plain statement,
45
+ * with no transaction opened around it. Resolves the rows the statement returned.
46
+ */
47
+ export type AvContextSql = <Row = unknown>(strings: TemplateStringsArray, ...values: readonly AvAdapterSqlValue[]) => Promise<Row[]>;
48
+ /**
49
+ * The arguments a variant-level stage is told: the operation's arguments under
50
+ * the model's Application Contract view, in the application forms, a reference
51
+ * position admitting an unresolved `$ref`. `unknown` for a model whose Resource
52
+ * names are not literal.
53
+ */
54
+ export type AvStageArguments<M extends AvAdapterModel, R extends string, F extends AvOperationFamily, V extends string> = StageArgumentsOf<AvContractApplicationView<M>, R, F, V>;
55
+ /** The arguments of operation `F`.`V` on `R` under the Contract view `C`. */
56
+ type StageArgumentsOf<C extends AvContract, R extends string, F extends AvOperationFamily, V extends string> = string extends R ? unknown : R extends AvResourceKey<C> ? AvOperationArgumentsFor<C, R, Extract<AvOperationIdentity, {
57
+ readonly family: F;
58
+ readonly variant: V;
59
+ }>, AvApplicationScalarForms, AvApplicationScalarForms> : unknown;
60
+ /**
61
+ * The arguments a variant's guards, pipes and filters are told: the operation's
62
+ * arguments before write compute has run, so a create need not hold a field
63
+ * `compute.create` fills (`Lift`, as `"<Resource>.<field>"`; `string`: any).
64
+ */
65
+ export type AvPreComputeStageArguments<M extends AvAdapterModel, R extends string, F extends AvOperationFamily, V extends string, Lift extends string = AvPreComputeLift<M, "root">> = F extends "find" | "delete" ? AvStageArguments<M, R, F, V> : [Lift] extends [never] ? AvStageArguments<M, R, F, V> : StageArgumentsOf<PreComputeView<AvContractApplicationView<M>, Lift>, R, F, V>;
66
+ /** A Contract view with the create requirements `Lift` names lifted. */
67
+ type PreComputeView<C, Lift extends string> = Extract<{
68
+ readonly [P in keyof C]: P extends "resources" ? string extends Lift ? {
69
+ readonly [R in keyof C[P]]: Omit<C[P][R], "createRequirements">;
70
+ } : {
71
+ readonly [R in keyof C[P]]: LiftedResource<C[P][R], LiftedFieldOf<Lift, R>>;
72
+ } : C[P];
73
+ }, AvContract>;
74
+ /** The fields of Resource `R` that `Lift` names. */
75
+ type LiftedFieldOf<Lift extends string, R> = Lift extends `${R & string}.${infer Field}` ? Field : never;
76
+ /** One Resource with the create requirements on `Fields` lifted; itself when none. */
77
+ type LiftedResource<Resource, Fields> = [Fields] extends [never] ? Resource : {
78
+ readonly [P in keyof Resource]: P extends "createRequirements" ? RequirementsLessComputed<Exclude<Resource[P], undefined>, Fields> : Resource[P];
79
+ };
80
+ /**
81
+ * What a pipeline callback is told about the operation it is wrapping, and the
82
+ * framework's executor: `ctx.<Resource>.<family>.<variant>(args)`, `ctx.$sql` and
83
+ * `ctx.$transaction`. Every framework member is `$`-prefixed.
84
+ *
85
+ * A ctx call is raw and application-origin: it runs the Framework Validation
86
+ * Layer, field pipes, field validators and compute, and no developer stage
87
+ * (guards, pipes, hooks, interceptors, filters, field write guards, transaction
88
+ * stages), so a hook's call never re-enters the hook. It joins the current
89
+ * transaction when there is one, and resolves the operation's data or throws an
90
+ * `AvError`.
91
+ */
92
+ export type AvContext<M extends AvAdapterModel = AvAdapterModel, R extends string = AvConfigResourceKey<M>, F extends AvOperationFamily = AvOperationFamily, V extends string = string, A = unknown> = AvContextOperations<M> & AvContextFacts & {
93
+ /**
94
+ * The operation the stage wraps. For a nested write's target `resource` is the
95
+ * target, `family` the family its directive maps to, `variant` is `"one"` and
96
+ * `nested` is `true`.
97
+ */
98
+ readonly $operation: {
99
+ readonly resource: R;
100
+ readonly family: F;
101
+ readonly variant: V;
102
+ readonly nested?: true;
103
+ };
104
+ /**
105
+ * The arguments, deep-frozen: as the caller sent them in a guard, as the pipes
106
+ * returned them in a pipe, and the validated arguments the operation executes in
107
+ * an interceptor, a hook or a filter. Only a pipe changes them, by returning new
108
+ * ones; writing to them throws a `TypeError`. At a variant, typed as that
109
+ * operation's arguments ({@link AvStageArguments}), deep read-only; in a guard or
110
+ * a filter a create may lack the fields `compute.create` fills ({@link
111
+ * AvPreComputeStageArguments}: write compute has not run); above it, `unknown`.
112
+ */
113
+ readonly $args: AvDeepReadonly<A>;
114
+ readonly $sql: AvContextSql;
115
+ /**
116
+ * Runs `work` in a transaction, `tx` being this ctx bound to it, and resolves
117
+ * what `work` resolved; a throw rolls it back. Inside an open transaction it
118
+ * opens nothing and joins it.
119
+ */
120
+ $transaction<T>(work: (tx: AvContext<M, R, F, V, A>) => Promise<T>): Promise<T>;
24
121
  };
25
122
  /** Allows or denies an operation; returning `false` answers `A4001`. */
26
- export type Guard<M extends AdapterModel = AdapterModel> = {
27
- guard(context: PipelineContext<M>): boolean | undefined | Promise<boolean | undefined>;
123
+ export type AvGuard<M extends AvAdapterModel = AvAdapterModel, R extends string = AvConfigResourceKey<M>, F extends AvOperationFamily = AvOperationFamily, V extends string = string, A = unknown> = {
124
+ guard(context: AvContext<M, R, F, V, A>): boolean | undefined | Promise<boolean | undefined>;
28
125
  }["guard"];
29
126
  /**
30
- * Transforms the arguments before the operation runs; returning `undefined`
31
- * keeps them as they are.
127
+ * Transforms the arguments before the validators judge them: the only stage
128
+ * that changes them. `args` is deep-frozen, so a pipe returns new arguments;
129
+ * returning `undefined` keeps them as they are. At a variant, `args` and the
130
+ * return are typed as that operation's arguments before write compute runs
131
+ * ({@link AvPreComputeStageArguments}: a create may lack the fields
132
+ * `compute.create` fills), `args` deep read-only.
32
133
  */
33
- export type Pipe<M extends AdapterModel = AdapterModel> = {
34
- pipe(args: unknown, context: PipelineContext<M>): unknown | Promise<unknown>;
134
+ export type AvPipe<M extends AvAdapterModel = AvAdapterModel, R extends string = AvConfigResourceKey<M>, F extends AvOperationFamily = AvOperationFamily, V extends string = string, A = unknown> = {
135
+ pipe(args: PipeArguments<A>, context: AvContext<M, R, F, V, A>): PipeResult<PipeArguments<A>>;
35
136
  }["pipe"];
36
- /** Runs just before the operation executes. */
37
- export type BeforeHook<M extends AdapterModel = AdapterModel> = {
38
- before(context: PipelineContext<M>): void | Promise<void>;
137
+ /**
138
+ * A variant pipe's arguments and return: the operation's arguments, deep
139
+ * read-only, each member closed to inference.
140
+ */
141
+ type PipeArguments<T> = T extends AvDeepReadonlyLeaf | AvTransactionReference ? T : T extends readonly unknown[] ? ArrayForm<T> extends "array" ? readonly NoInfer<PipeArguments<Exclude<T[number], undefined>>>[] : {
142
+ readonly [K in keyof T]: NoInfer<PipeArguments<Exclude<T[K], undefined>>>;
143
+ } : T extends object ? {
144
+ readonly [K in keyof T]: NoInfer<PipeArguments<Exclude<T[K], undefined>>>;
145
+ } : T;
146
+ /** What a pipe returns: arguments of type `A`, or `undefined` to keep them. */
147
+ type PipeResult<A> = unknown extends A ? any : // biome-ignore lint/suspicious/noConfusingVoidType: a pipe written as `() => void sideEffect()` keeps the arguments, as `undefined` does
148
+ A | undefined | void | Promise<A | undefined | void>;
149
+ /** Runs just before the operation executes, inside every interceptor; `ctx.$args` is deep-frozen. */
150
+ export type AvBeforeHook<M extends AvAdapterModel = AvAdapterModel, R extends string = AvConfigResourceKey<M>, F extends AvOperationFamily = AvOperationFamily, V extends string = string, A = unknown> = {
151
+ before(context: AvContext<M, R, F, V, A>): void | Promise<void>;
39
152
  }["before"];
40
- /** Runs after the operation succeeds, with its result. */
41
- export type AfterHook<M extends AdapterModel = AdapterModel> = {
42
- after(result: unknown, context: PipelineContext<M>): void | Promise<void>;
153
+ /**
154
+ * Runs after the operation succeeds, with its result, deep-frozen; an
155
+ * interceptor may still answer a different one.
156
+ */
157
+ export type AvAfterHook<M extends AvAdapterModel = AvAdapterModel, R extends string = AvConfigResourceKey<M>, F extends AvOperationFamily = AvOperationFamily, V extends string = string, A = unknown> = {
158
+ after(result: unknown, context: AvContext<M, R, F, V, A>): void | Promise<void>;
43
159
  }["after"];
44
160
  /** Wraps the operation's execution; call `next()` to run it and get its result. */
45
- export type Interceptor<M extends AdapterModel = AdapterModel> = {
46
- intercept(context: PipelineContext<M>, next: () => Promise<unknown>): Promise<unknown>;
161
+ export type AvInterceptor<M extends AvAdapterModel = AvAdapterModel, R extends string = AvConfigResourceKey<M>, F extends AvOperationFamily = AvOperationFamily, V extends string = string, A = unknown> = {
162
+ intercept(context: AvContext<M, R, F, V, A>, next: () => Promise<unknown>): Promise<unknown>;
47
163
  }["intercept"];
48
164
  /**
49
- * Turns a thrown error into a {@link FrameworkError} to answer with; returning
165
+ * Turns a thrown error into a {@link AvError} to answer with; returning
50
166
  * `undefined` passes the error on.
51
167
  */
52
- export type Filter<M extends AdapterModel = AdapterModel> = {
53
- filter(error: unknown, context: PipelineContext<M>): FrameworkError | undefined | Promise<FrameworkError | undefined>;
168
+ export type AvFilter<M extends AvAdapterModel = AvAdapterModel, R extends string = AvConfigResourceKey<M>, F extends AvOperationFamily = AvOperationFamily, V extends string = string, A = unknown> = {
169
+ filter(error: unknown, context: AvContext<M, R, F, V, A>): AvError | undefined | Promise<AvError | undefined>;
170
+ }["filter"];
171
+ /**
172
+ * A pure transform of the value the caller sent for one scalar field: value in,
173
+ * value out, no context. Returning `undefined` keeps the value.
174
+ */
175
+ export type AvFieldPipe = (value: unknown) => unknown | Promise<unknown>;
176
+ /**
177
+ * Write-only admission for one field: refuses the operation when the caller sends
178
+ * the field. Returning `false` answers `A4001`.
179
+ */
180
+ export type AvFieldGuard<M extends AvAdapterModel = AvAdapterModel, R extends string = AvConfigResourceKey<M>> = {
181
+ guard(value: unknown, context: AvContext<M, R, "create" | "update" | "upsert">): boolean | undefined | Promise<boolean | undefined>;
182
+ }["guard"];
183
+ /**
184
+ * One plan step as a transaction stage reads it: an operation step with its
185
+ * `$ref`s unresolved, or a SQL step, which names no Resource.
186
+ */
187
+ export type AvTransactionStep<M extends AvAdapterModel = AvAdapterModel> = {
188
+ readonly resource: AvConfigResourceKey<M>;
189
+ readonly family: AvOperationFamily;
190
+ readonly variant: string;
191
+ readonly args: unknown;
192
+ readonly sql?: never;
193
+ } | {
194
+ readonly sql: {
195
+ readonly strings: readonly string[] | undefined;
196
+ readonly values: readonly unknown[];
197
+ };
198
+ readonly resource?: never;
199
+ readonly family?: never;
200
+ readonly variant?: never;
201
+ readonly args?: never;
202
+ };
203
+ /**
204
+ * What a Resource's transaction stage is told: the plan, not one operation
205
+ * (`$operation` is absent), and the executor, bound to the transaction.
206
+ */
207
+ export type AvTransactionContext<M extends AvAdapterModel = AvAdapterModel> = AvContextOperations<M> & AvContextFacts & {
208
+ /** The plan, in step order, `$ref`s unresolved, deep-frozen. */
209
+ readonly $args: readonly AvTransactionStep<M>[];
210
+ readonly $sql: AvContextSql;
211
+ /** Runs `work` inside this transaction (it opens nothing): `tx` is this ctx. */
212
+ $transaction<T>(work: (tx: AvTransactionContext<M>) => Promise<T>): Promise<T>;
213
+ };
214
+ /** Allows or denies a whole transaction; returning `false` answers `A4001`. */
215
+ export type AvTransactionGuard<M extends AvAdapterModel = AvAdapterModel> = {
216
+ guard(context: AvTransactionContext<M>): boolean | undefined | Promise<boolean | undefined>;
217
+ }["guard"];
218
+ /**
219
+ * Transforms the plan before any step runs; returning `undefined` keeps it. The
220
+ * plan it is given is deep-frozen, so it returns a new one. A
221
+ * returned plan keeps its steps (the same number, each on the same operation,
222
+ * each SQL step as it was); only an operation step's `args` may change.
223
+ */
224
+ export type AvTransactionPipe<M extends AvAdapterModel = AvAdapterModel> = {
225
+ pipe(plan: readonly AvTransactionStep<M>[], context: AvTransactionContext<M>): readonly AvTransactionStep[] | undefined | Promise<readonly AvTransactionStep[] | undefined>;
226
+ }["pipe"];
227
+ /** Runs inside the transaction before its steps. */
228
+ export type AvTransactionBeforeHook<M extends AvAdapterModel = AvAdapterModel> = {
229
+ before(context: AvTransactionContext<M>): void | Promise<void>;
230
+ }["before"];
231
+ /** Runs inside the transaction after its steps, with every step's result, deep-frozen. */
232
+ export type AvTransactionAfterHook<M extends AvAdapterModel = AvAdapterModel> = {
233
+ after(results: unknown, context: AvTransactionContext<M>): void | Promise<void>;
234
+ }["after"];
235
+ /** Wraps the transaction's steps; call `next()` to run them. */
236
+ export type AvTransactionInterceptor<M extends AvAdapterModel = AvAdapterModel> = {
237
+ intercept(context: AvTransactionContext<M>, next: () => Promise<unknown>): Promise<unknown>;
238
+ }["intercept"];
239
+ /** Turns an error thrown inside the transaction into a {@link AvError}. */
240
+ export type AvTransactionFilter<M extends AvAdapterModel = AvAdapterModel> = {
241
+ filter(error: unknown, context: AvTransactionContext<M>): AvError | undefined | Promise<AvError | undefined>;
54
242
  }["filter"];
243
+ export {};
@@ -0,0 +1,43 @@
1
+ import { AvDecimal } from "./decimal.js";
2
+ /** A value `AvDeepReadonly` leaves as it is: a primitive, a function, or a scalar instance. */
3
+ export type AvDeepReadonlyLeaf = string | number | boolean | bigint | symbol | null | undefined | Date | Uint8Array | AvDecimal | ((...args: never[]) => unknown);
4
+ /**
5
+ * Whether array type `T` is an open array (every length: `"array"`) or a tuple
6
+ * (`"tuple"`). A tuple whose only fixed positions are optional ones before a rest
7
+ * element (`[a?, ...b[]]`) has every length too and reads as an array.
8
+ */
9
+ export type ArrayForm<T extends readonly unknown[]> = T extends readonly [] | readonly [unknown, ...unknown[]] | readonly [...unknown[], unknown] ? "tuple" : T extends {
10
+ readonly length: infer Length;
11
+ } ? number extends Length ? "array" : "tuple" : "tuple";
12
+ /**
13
+ * `T` with every property, element and nested property read-only: what a stage
14
+ * that only reads is told. Arrays become read-only arrays, tuples read-only
15
+ * tuples; a `Date`, a `Uint8Array`, an `AvDecimal` and functions are left as
16
+ * they are.
17
+ */
18
+ export type AvDeepReadonly<T> = T extends AvDeepReadonlyLeaf ? T : T extends readonly unknown[] ? ArrayForm<T> extends "array" ? readonly AvDeepReadonly<T[number]>[] : {
19
+ readonly [K in keyof T]: AvDeepReadonly<T[K]>;
20
+ } : T extends object ? {
21
+ readonly [K in keyof T]: AvDeepReadonly<T[K]>;
22
+ } : T;
23
+ /**
24
+ * Freezes `value` in place, every nested plain object and array included, and
25
+ * returns it. Accessor properties are not read. For data the framework owns: the
26
+ * copy taken at the door, a body parsed for this request alone, a pipe's output.
27
+ */
28
+ export declare function deepFreeze<T>(value: T): T;
29
+ /**
30
+ * A deep-frozen copy of `value`'s plain objects and arrays, every `Date` and
31
+ * `Uint8Array` in it copied too, the original left as it is: what a stage that
32
+ * only reads is told — the validated arguments after validation, a result in an
33
+ * after hook — so neither what is written nor the result the caller receives can
34
+ * be changed through it.
35
+ */
36
+ export declare function frozenCopy<T>(value: T): AvDeepReadonly<T>;
37
+ /**
38
+ * A read-only view of `value`: reads see the live value, nested plain objects
39
+ * and arrays as views too, and any write, definition or deletion throws a
40
+ * `TypeError` naming `subject` (one subject per value: the first view's). The
41
+ * value itself stays writable for its owner.
42
+ */
43
+ export declare function readonlyView<T>(value: T, subject: string): AvDeepReadonly<T>;