@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
package/ERRORS.md ADDED
@@ -0,0 +1,142 @@
1
+ # Aventara error codes
2
+
3
+ Every code `@aventara/core` 1.0.0-rc.2 answers, reports in a validation issue, or refuses to start with. Generated from `AvErrorCatalog` (exported by `@aventara/core`); do not edit.
4
+
5
+ Branch on the code, never on the message. In code, `AvErrorCatalog[code]` gives the same entry: `{ code, kind, message, cause, fix, docs }`.
6
+
7
+ ## Success codes (A1xxx)
8
+
9
+ An operation's `code` when it succeeded. The generated client resolves for these.
10
+
11
+ | Code | Meaning | Cause | Fix |
12
+ |---|---|---|---|
13
+ | [`A1000`](https://aventara-framework.vercel.app/docs/error-codes#a1000) | Success. | A read, a count or another operation without a more specific success code succeeded. | Nothing: the call succeeded. |
14
+ | [`A1001`](https://aventara-framework.vercel.app/docs/error-codes#a1001) | No match. | A first-style operation (find.first, update.first, delete.first) matched no row; data is null and the generated client resolves null. | Nothing: handle the null result. A unique operation answers A2003 instead. |
15
+ | [`A1002`](https://aventara-framework.vercel.app/docs/error-codes#a1002) | Created. | create.one created a row. | Nothing: the call succeeded. |
16
+ | [`A1003`](https://aventara-framework.vercel.app/docs/error-codes#a1003) | Created many. | create.many or create.count created rows. | Nothing: the call succeeded. |
17
+ | [`A1004`](https://aventara-framework.vercel.app/docs/error-codes#a1004) | Updated. | update.first or update.unique updated a row. | Nothing: the call succeeded. |
18
+ | [`A1005`](https://aventara-framework.vercel.app/docs/error-codes#a1005) | Updated many. | update.many or update.count updated rows. | Nothing: the call succeeded. |
19
+ | [`A1006`](https://aventara-framework.vercel.app/docs/error-codes#a1006) | Deleted. | delete.first or delete.unique deleted a row. | Nothing: the call succeeded. |
20
+ | [`A1007`](https://aventara-framework.vercel.app/docs/error-codes#a1007) | Deleted many. | delete.count deleted rows. | Nothing: the call succeeded. |
21
+ | [`A1008`](https://aventara-framework.vercel.app/docs/error-codes#a1008) | Upserted. | upsert.unique created or updated a row. | Nothing: the call succeeded. |
22
+ | [`A1009`](https://aventara-framework.vercel.app/docs/error-codes#a1009) | Transaction committed. | A whole transaction plan committed; data holds one result per step. | Nothing: the plan committed. |
23
+
24
+ ## Request errors (A2xxx)
25
+
26
+ The caller can fix these. The generated client and server-side calls throw the code's `AvError` subclass.
27
+
28
+ | Code | Meaning | Cause | Fix |
29
+ |---|---|---|---|
30
+ | [`A2000`](https://aventara-framework.vercel.app/docs/error-codes#a2000) | Invalid request. | The HTTP request cannot be interpreted: malformed JSON, a body that is not a JSON object, an unknown `/_*` path, a body that does not decode in its Content-Encoding, or a missing Aventara-Protocol-Version or Aventara-Contract-Hash header (the message names it). | Send a JSON object with both identity headers. The generated client does this for you. |
31
+ | [`A2001`](https://aventara-framework.vercel.app/docs/error-codes#a2001) | Unknown Resource. | The Resource is not in the caller's contract: misspelt, hidden by exposure, or added to the schema after aventara:prepare last ran. cause.message is "The requested Resource is not available." and the issue is V1005 at `["resource"]`. | Use the model's exact name. After a schema change run the adapter's generate step (`npm run aventara:prepare` in a scaffolded project), restart, and regenerate the client. A Resource hidden on purpose is reached from server code (framework.application). |
32
+ | [`A2002`](https://aventara-framework.vercel.app/docs/error-codes#a2002) | Unknown operation. | The operation is not available on that Resource: a typo, removed by exposure, an operation the adapter does not offer (such as delete.many), or a ctx.$sql, appTx.$sql or ctx.$transaction the adapter or the layer cannot run. The issue is V1006 at `["family"]` or `["variant"]`. | Call an operation the contract lists (`GET <api>/_contract`), regenerate a stale client, and check the layer's exemptions and transactionsStyle. |
33
+ | [`A2003`](https://aventara-framework.vercel.app/docs/error-codes#a2003) | Not found. | A unique operation (find.unique, update.unique, delete.unique) matched no row, or a $connect names a record that does not exist. The operation fails, so no after hook runs. | Catch AvNotFoundError, or use a first-style operation, which answers A1001 with null. Check the $connect identifier. |
34
+ | [`A2004`](https://aventara-framework.vercel.app/docs/error-codes#a2004) | Validation failed. | The arguments break a contract rule or a field validator. cause.issues lists each problem by V-code and path; a validator's issue also has check and params. The validators judge the values after the pipes and write compute, so a computed value they refuse is here too, at its field. A required create field left out is here (V1000). So is a value the database itself refused: too long for its column or out of its range (V1004), or holding a character it cannot store or a pattern it cannot read (V1001), with the issue at `["arguments"]` and its message saying what the database refused. So is a record written through a relation that writes that relation, or a field holding its reference, back (V1012, at that field), where the adapter admits no such write. | Fix the argument each issue's path points at, as its V-code says. A field the server must fill takes a compute.create stage. For a value the database refused, send one its column holds. For a nested write that writes its relation back, leave that field out: the parent supplies it. |
35
+ | [`A2005`](https://aventara-framework.vercel.app/docs/error-codes#a2005) | Contract mismatch. | The caller's Aventara-Contract-Hash is not the server's current one: the schema, the configuration, the limits or the exposure changed, or the client targets another deployment. | Regenerate the client against the running server: `npm run avclient:generate`. |
36
+ | [`A2006`](https://aventara-framework.vercel.app/docs/error-codes#a2006) | Protocol mismatch. | Aventara-Protocol-Version is not 1. | Send `Aventara-Protocol-Version: 1`, or upgrade the client. |
37
+ | [`A2007`](https://aventara-framework.vercel.app/docs/error-codes#a2007) | Invalid transaction reference. | A transaction $ref or fingerprint is invalid: the issues are V1010, V1011, V1016, V1017 or V1018, and cause.operation is the step. A $ref with no fingerprint is A2004 / V1000. | Let the generated client or framework.appTx build plans; check the $ref path and that the referenced step comes earlier. |
38
+ | [`A2008`](https://aventara-framework.vercel.app/docs/error-codes#a2008) | Conflict. | A uniqueness or reference constraint failed: a duplicate value, a missing parent, or a $disconnect or $set that would orphan a required child (also through update.first or a developer SQL statement). Sending it again unchanged fails the same way. | Change the data. For a duplicate, update the existing row or use upsert.unique. |
39
+ | [`A2009`](https://aventara-framework.vercel.app/docs/error-codes#a2009) | Limit exceeded. | A contract limit was crossed: nesting depth (V1013), list or plan size (V1014), boolean nodes (V1015) or Json value depth (V1021). | Ask for less (paginate, split the plan), or raise the limit under `limits`. |
40
+ | [`A2010`](https://aventara-framework.vercel.app/docs/error-codes#a2010) | Payload too large. | The decoded request body exceeds maxRequestBytes (default 1048576). | Send less, or raise limits.maxRequestBytes. |
41
+ | [`A2011`](https://aventara-framework.vercel.app/docs/error-codes#a2011) | Unsupported media type. | The body is not application/json, or its Content-Encoding is not gzip, deflate or br. | Send `Content-Type: application/json`. |
42
+ | [`A2012`](https://aventara-framework.vercel.app/docs/error-codes#a2012) | Method not allowed. | The HTTP method does not fit the route; the Allow header names the right one (`POST` on operations and `/_transactions`, `GET` on `/_contract`). | Use the method the Allow header names. |
43
+ | [`A2013`](https://aventara-framework.vercel.app/docs/error-codes#a2013) | Concurrent modification. | A competing writer reached the state first; nothing was written. | Retry. No retry is automatic. |
44
+ | [`A2014`](https://aventara-framework.vercel.app/docs/error-codes#a2014) | Stale selection. | The selected state changed before the write; nothing was written. | Read again, then retry. |
45
+
46
+ ## Server errors (A3xxx)
47
+
48
+ Not caller-actionable: `cause.message` is generic, and the real error goes to the root `diagnostics` sink.
49
+
50
+ | Code | Meaning | Cause | Fix |
51
+ |---|---|---|---|
52
+ | [`A3000`](https://aventara-framework.vercel.app/docs/error-codes#a3000) | Internal error. | An unexpected failure on the server: a stage threw an error that is not an AvError, an interceptor called next() twice, a compute stage reached a write through its read-only ctx, a compute stage returned a value of the wrong type, or a compute.create returned undefined for a required field. cause.message is always "Internal framework error." | Read the real error in the diagnostics sink (the root `diagnostics` key) or the server log line for the request id, and fix that stage. To answer with a code of your choice, throw an AvError. |
53
+ | [`A3001`](https://aventara-framework.vercel.app/docs/error-codes#a3001) | Adapter error. | A database or ORM failure that is not something the caller can fix. cause.message is always "Adapter execution failed." | Read the raw error in the diagnostics sink; check the database, its connection and the migration state. |
54
+ | [`A3002`](https://aventara-framework.vercel.app/docs/error-codes#a3002) | Transaction error. | Transaction infrastructure failed (commit or rollback, or the transaction expired or was closed under a step), or a Resource transaction interceptor called next() twice or resolved without calling it. | Read the diagnostics sink. Call next() exactly once in a transaction interceptor; retry an infrastructure failure. |
55
+ | [`A3003`](https://aventara-framework.vercel.app/docs/error-codes#a3003) | Serialization error. | A result could not be encoded for transport. | Read the diagnostics sink; make compute.read stages and Json values return plain data of the field's type. |
56
+ | [`A3004`](https://aventara-framework.vercel.app/docs/error-codes#a3004) | Pipe output invalid. | A server pipe, field pipe or transaction pipe (or write compute) returned arguments the server's own contract refuses: a field the Resource does not have, a wrong type, a dropped required field, a reference written together with its relation (V1012), or a changed plan. cause.message is always "A server pipeline produced invalid arguments." | Read the server log line, which names the pipe, the operation and the path, and fix the pipe. A pipe returns a new object of the same shape, or undefined to keep the arguments. |
57
+
58
+ ## Authentication and authorization (A4xxx)
59
+
60
+ Produced by your guards; the framework never authenticates by itself.
61
+
62
+ | Code | Meaning | Cause | Fix |
63
+ |---|---|---|---|
64
+ | [`A4000`](https://aventara-framework.vercel.app/docs/error-codes#a4000) | Unauthenticated. | A guard threw new AvError("A4000", ...): authentication is required or failed. The framework never authenticates by itself. | Send the credentials your guards expect, such as the Authorization header. |
65
+ | [`A4001`](https://aventara-framework.vercel.app/docs/error-codes#a4001) | Forbidden. | A guard returned false ("Operation denied by a framework guard."), a field write guard or a nested write's target guard included, or a stage threw A4001. | Call as a caller the guard admits, or stop sending the guarded field. To answer another code, throw an AvError from the guard. |
66
+ | [`A4002`](https://aventara-framework.vercel.app/docs/error-codes#a4002) | Policy denied. | A guard or hook threw new AvError("A4002", ...) with a policy reason of your own. | Read cause.message for the policy's reason. |
67
+
68
+ ## Validation issues (V1xxx)
69
+
70
+ Each entry of `cause.issues[]` under `A2001`, `A2002`, `A2004`, `A2007` or `A2009`: `{ code, path, message }`, plus `check` and `params` for a failed field validator.
71
+
72
+ | Code | Meaning | Cause | Fix |
73
+ |---|---|---|---|
74
+ | [`V1000`](https://aventara-framework.vercel.app/docs/error-codes#v1000) | Required value missing. | A required value is absent: a create leaves out a required field that has no database default and no compute.create (the path names the field), a required relation and its reference field are both missing, a typed Json field lacks a required key, or a $ref has no fingerprint. | Send the value at the issue's path. When the server must fill it, give the field a compute.create stage or a database default; a pipe cannot fill it. |
75
+ | [`V1001`](https://aventara-framework.vercel.app/docs/error-codes#v1001) | Invalid runtime/wire type. | A value of the wrong type: a string where a number is expected, a negative limit, a non-integer id, null given to an operator with no null meaning (gt, contains, in), two directives in one scalar action object (`{ $increment: 1, $decrement: 2 }`), or a server-side value that is not plain data. | Send the type the contract states at that path (the generated client's types say it). |
76
+ | [`V1002`](https://aventara-framework.vercel.app/docs/error-codes#v1002) | Invalid enum value. | A value that is not a member of the enum, or outside a typed Json field's AvZ.enum or AvZ.literal. | Send one of the enum's members. |
77
+ | [`V1003`](https://aventara-framework.vercel.app/docs/error-codes#v1003) | Invalid format (for example UUID/DateTime/base64). | A malformed datetime, decimal, base64 or UUID string, or a failed pattern or format validator (`check: "string_format"`). | Send the canonical encoding (ISO-8601 UTC datetime, decimal string, base64 bytes) and satisfy the validator that check and params name. |
78
+ | [`V1004`](https://aventara-framework.vercel.app/docs/error-codes#v1004) | Value outside accepted range. | A number, length or size outside its range: a failed bound, length or size validator, a BigInt outside signed 64 bits, an AvZ.int() outside the safe integer range, or a transaction with no operations. | Send a value inside the range; check and params name the validator that failed. |
79
+ | [`V1005`](https://aventara-framework.vercel.app/docs/error-codes#v1005) | Unknown or inaccessible field. | A field that does not exist or is hidden in the caller's layer, an unknown Resource (under A2001), or a key a typed Json field's shape does not declare. | Use a field the caller's contract exposes, expose it through exemptions, or make the call from server code. |
80
+ | [`V1006`](https://aventara-framework.vercel.app/docs/error-codes#v1006) | Unsupported filter/order/mutation directive. | An operator, directive or nested write the field does not offer (at any depth, inside not too; a to-many $update's data takes only what a bulk write takes), a mode it does not offer, or an operation that is not available (under A2002). | Use what the contract lists for that field or Resource, or expose it through exemptions. |
81
+ | [`V1007`](https://aventara-framework.vercel.app/docs/error-codes#v1007) | Invalid unique identifier shape. | The where of a unique operation is not exactly one complete identifier. | Pass exactly one identifier: the id, or every field of one @unique or @@unique. |
82
+ | [`V1008`](https://aventara-framework.vercel.app/docs/error-codes#v1008) | Invalid select/include/reducer projection. | Both select and include, a write-only field selected, or a relation that is not selectable there. | Use select or include, not both, and select only readable fields. |
83
+ | [`V1009`](https://aventara-framework.vercel.app/docs/error-codes#v1009) | Invalid or non-deterministic cursor. | A cursor without an explicit orderBy, or cursor keys that do not match the ordered fields. | Give an orderBy and a cursor holding exactly its ordered fields. |
84
+ | [`V1010`](https://aventara-framework.vercel.app/docs/error-codes#v1010) | Invalid transaction reference path. | A $ref path the earlier step does not return, a $ref to a step that is not in the transaction, or to a step with no single row (a many or count step). | Select the referenced field in the earlier step, and reference a single-row step. |
85
+ | [`V1011`](https://aventara-framework.vercel.app/docs/error-codes#v1011) | Transaction reference type mismatch. | The referenced value's type does not fit its target, a nullable source where only a non-null value is accepted included. | Reference a field of the target's type, non-null where the target needs it. |
86
+ | [`V1012`](https://aventara-framework.vercel.app/docs/error-codes#v1012) | Invalid relation action/cardinality. | A nested write that does not fit the relation (a list where one record is expected), a reference field set together with its own relation, one record mixing reference fields and relation writes where the adapter cannot run both, or a record written through a relation that writes that relation (or a field holding its reference) back, where the adapter admits no such write. | Write either the relation or its reference field, in the relation's cardinality. |
87
+ | [`V1013`](https://aventara-framework.vercel.app/docs/error-codes#v1013) | Maximum nesting depth exceeded. | Nested projections, filters or writes deeper than maxNestingDepth. | Nest less, or raise limits.maxNestingDepth. |
88
+ | [`V1014`](https://aventara-framework.vercel.app/docs/error-codes#v1014) | Configured limit exceeded. | A limit above maxListLimit, or more steps than maxTransactionOperations. | Paginate or split the plan, or raise the limit. |
89
+ | [`V1015`](https://aventara-framework.vercel.app/docs/error-codes#v1015) | Boolean/filter node limit exceeded. | A where tree with more nodes than maxBooleanNodes. | Simplify the filter (in instead of many OR clauses), or raise limits.maxBooleanNodes. |
90
+ | [`V1016`](https://aventara-framework.vercel.app/docs/error-codes#v1016) | Invalid transaction reference index. | A $ref to the referencing step itself or a later one, or to an index no step has. | Reference an earlier step only. |
91
+ | [`V1017`](https://aventara-framework.vercel.app/docs/error-codes#v1017) | Transaction fingerprint mismatch. | A hand-written plan whose fingerprint does not match its step. | Let the generated client, framework.appTx or framework.clientTx build the plan. |
92
+ | [`V1018`](https://aventara-framework.vercel.app/docs/error-codes#v1018) | Transaction reference resolved to no value. | The referenced step returned no value at that path, such as a first step that matched no row. | Make sure the earlier step returns a row, or use a unique step, which fails with A2003. |
93
+ | [`V1019`](https://aventara-framework.vercel.app/docs/error-codes#v1019) | Transaction step depends on a row removed by an earlier step's cascade | A later step uses a row that an earlier step's delete removed through a database cascade. | Reorder or drop the dependent step. |
94
+ | [`V1020`](https://aventara-framework.vercel.app/docs/error-codes#v1020) | Transaction mixes application and client steps. | One framework.transaction([...]) list mixes appTx and clientTx steps. | Build every step of a plan from one origin. |
95
+ | [`V1021`](https://aventara-framework.vercel.app/docs/error-codes#v1021) | Json value depth limit exceeded. | A Json field's value nests deeper than maxJsonDepth. | Flatten the value, or raise limits.maxJsonDepth. |
96
+
97
+ ## Startup: configuration
98
+
99
+ `createFramework` (and `AventaraModule`) throws one `AvConstructionError` with `stage: "configuration"`; each diagnostic is `{ code, path, message, docs }`.
100
+
101
+ | Code | Meaning | Cause | Fix |
102
+ |---|---|---|---|
103
+ | [`CONFIG_REQUIRED`](https://aventara-framework.vercel.app/docs/error-codes#config_required) | A required configuration key is missing. | A key that must be present is absent: api, adapter, or an overlay's exposed when the overlay sets exemptions. | Add the key at the diagnostic's path. |
104
+ | [`CONFIG_UNKNOWN_PROPERTY`](https://aventara-framework.vercel.app/docs/error-codes#config_unknown_property) | Unknown configuration key. | A key the configuration does not define at that place: a typo, or a key written at the wrong level of the tree. | Remove it, or move it where it belongs (the configuration reference's "Where a key can go"). |
105
+ | [`CONFIG_INVALID_TYPE`](https://aventara-framework.vercel.app/docs/error-codes#config_invalid_type) | A configuration key has the wrong type. | A value of the wrong type, or a key set to an explicit undefined. | Give the value the type the reference states; leave a key out rather than setting it to undefined. |
106
+ | [`CONFIG_INVALID_VALUE`](https://aventara-framework.vercel.app/docs/error-codes#config_invalid_value) | A configuration value is not allowed. | A malformed api or mcp path, a negative limit, an unknown transactionsStyle, a format that is not a named zod format, or forceTransaction under an effective transactionsStyle "none". | Use a value the message allows. |
107
+ | [`CONFIG_MOVED_PROPERTY`](https://aventara-framework.vercel.app/docs/error-codes#config_moved_property) | A configuration key moved in rc.1. | Configuration written for 1.0.0-rc.0: restrictions, entrypoint, fields, behaviors, transactions or pipelines.before/after. | Move it where the message says: restrictions to exposed + exemptions, entrypoint to api, fields to `resources.<R>.fields.<f>.definition`, transactions to transactionsStyle, before/after to pipelines.hooks. |
108
+ | [`CONFIG_FORBIDDEN_IN_OVERLAY`](https://aventara-framework.vercel.app/docs/error-codes#config_forbidden_in_overlay) | A root-only key is written in an overlay. | A field definition in application, client or agent. | Define the field once at the root (`resources.<R>.fields.<f>.definition`); an overlay only chooses its visibility. |
109
+
110
+ ## Startup: discovery
111
+
112
+ `AvConstructionError` with `stage: "discovery"`: what the adapter reported does not hold together.
113
+
114
+ | Code | Meaning | Cause | Fix |
115
+ |---|---|---|---|
116
+ | [`DISCOVERY_TRANSACTION_CAPABILITY_MISMATCH`](https://aventara-framework.vercel.app/docs/error-codes#discovery_transaction_capability_mismatch) | The adapter's transaction capability does not match it. | The adapter declares interactive transactions but provides no transaction function. | A defect of the adapter: install the adapter release that matches @aventara/core exactly. |
117
+
118
+ ## Startup: contract compilation
119
+
120
+ `AvConstructionError` with `stage: "contract-compilation"`; a diagnostic's `path` starts with its layer (`root.`, `application.`, `client.`, `agent.`).
121
+
122
+ | Code | Meaning | Cause | Fix |
123
+ |---|---|---|---|
124
+ | [`COMPILER_UNKNOWN_RESOURCE`](https://aventara-framework.vercel.app/docs/error-codes#compiler_unknown_resource) | Unknown Resource. | A Resource name the adapter's model does not have, in resources or in exemptions. | Use the model's exact name. After a schema change run `npm run aventara:prepare`. |
125
+ | [`COMPILER_UNKNOWN_FIELD`](https://aventara-framework.vercel.app/docs/error-codes#compiler_unknown_field) | Unknown field. | A field that is neither in the schema nor defined at the root. | Fix the name, run aventara:prepare after a schema change, or add the field with a root definition. |
126
+ | [`COMPILER_RELATION_FIELD_CONFIG_UNSUPPORTED`](https://aventara-framework.vercel.app/docs/error-codes#compiler_relation_field_config_unsupported) | A relation field takes write guards only. | Field pipes or compute on a relation field. | Put the stage on the relation's reference field, or use an operation pipe. |
127
+ | [`COMPILER_INCOMPLETE_FIELD`](https://aventara-framework.vercel.app/docs/error-codes#compiler_incomplete_field) | An added field is incomplete. | A definition that adds a field leaves out type, nullable or list. | Spell out type, nullable and list, with lifecycle: ["VIRTUAL"] for a field that has no column. |
128
+ | [`COMPILER_STRUCTURAL_FIELD_OVERRIDE`](https://aventara-framework.vercel.app/docs/error-codes#compiler_structural_field_override) | A discovered field's structure was redefined. | A definition on a field the adapter discovered changes its type, format or capabilities. | Restate only its type, nullable and list. Change capabilities through exemptions and the column through the schema. |
129
+ | [`COMPILER_MISSING_SCALAR`](https://aventara-framework.vercel.app/docs/error-codes#compiler_missing_scalar) | Unknown scalar type. | A definition names a scalar type that does not exist. | Use a built-in scalar: string, boolean, int, float, bigint, decimal, datetime, bytes or json. |
130
+ | [`COMPILER_MISSING_ENUM`](https://aventara-framework.vercel.app/docs/error-codes#compiler_missing_enum) | Unknown enum. | A definition names an enum the model does not have. | Use an enum of the schema, and run aventara:prepare after adding one. |
131
+ | [`COMPILER_DANGLING_RELATION`](https://aventara-framework.vercel.app/docs/error-codes#compiler_dangling_relation) | A visible relation points at a hidden Resource. | A layer hides a Resource but still exposes a relation field that targets it. | Hide the relation field too (`exemptions.resources.<R>.fields.<relation>: true`), or expose the target. |
132
+ | [`COMPILER_UNAVAILABLE_OPERATION`](https://aventara-framework.vercel.app/docs/error-codes#compiler_unavailable_operation) | Operation not available. | An operation the adapter does not offer (such as delete.many), or an overlay granting one that its parent hid. | Remove it. To reach an operation from one overlay only, expose it at the root and hide it in the other overlay. |
133
+ | [`COMPILER_UNAVAILABLE_CAPABILITY`](https://aventara-framework.vercel.app/docs/error-codes#compiler_unavailable_capability) | Capability not available. | A capability or token the field does not offer, or an overlay (or the agent layer) granting one its parent hid. Overlays only narrow. | Remove it, or expose it in the parent layer and hide it in the layer it must not reach. |
134
+ | [`COMPILER_INVALID_LIFECYCLE`](https://aventara-framework.vercel.app/docs/error-codes#compiler_invalid_lifecycle) | Invalid field lifecycle. | An added field declares a lifecycle other than VIRTUAL, a VIRTUAL field claims a database-generated lifecycle or a provider-side capability, or a definition redefines a discovered field's lifecycle. | Give an added field lifecycle: ["VIRTUAL"] and only the capabilities it can serve; computed lifecycles come from compute stages. |
135
+ | [`COMPILER_MISSING_READ_COMPUTE`](https://aventara-framework.vercel.app/docs/error-codes#compiler_missing_read_compute) | A selectable virtual field has no compute.read. | A VIRTUAL field that can be selected has no pipelines.compute.read stage. | Add a compute.read stage, or make the field write-only with capabilities.select: false. |
136
+ | [`COMPILER_INVALID_COMPUTE_DEPENDENCY`](https://aventara-framework.vercel.app/docs/error-codes#compiler_invalid_compute_dependency) | Invalid compute.read dependency. | A dependsOn entry that is not a stored scalar field of the same Resource. | List only stored scalar fields of the Resource in dependsOn. |
137
+ | [`COMPILER_RESERVED_RESOURCE_NAME`](https://aventara-framework.vercel.app/docs/error-codes#compiler_reserved_resource_name) | Reserved Resource name. | A model name starts with $, which is reserved for the framework's own names (ctx.$sql, $ref). | Rename the model; the table it maps to can keep its name. |
138
+ | [`COMPILER_MISSING_IDENTIFIER`](https://aventara-framework.vercel.app/docs/error-codes#compiler_missing_identifier) | A unique operation has no identifier. | A layer exposes a unique variant (find.unique, update.unique, delete.unique, upsert.unique) and no complete identifier of the Resource: a Pick that did not pick one, or an Omit that hid every one. | Expose an identifier field (id, or every field of one unique), or exempt the unique variants. |
139
+ | [`COMPILER_HIDDEN_REQUIRED_FIELD`](https://aventara-framework.vercel.app/docs/error-codes#compiler_hidden_required_field) | A layer that creates a Resource hides a required field. | A layer still creates the Resource (a create or upsert variant, or a nested create) while a required field, or a required relation's reference field, is hidden or has its create capability exempted, and no compute.create fills it. | Expose the field, give it a compute.create stage, or exempt the layer's create operations. |
140
+ | [`COMPILER_INVALID_VALIDATOR`](https://aventara-framework.vercel.app/docs/error-codes#compiler_invalid_validator) | A field validator cannot apply. | A validator that is not built with AvZ, does not fit the field's type (AvZ.maxLength on an int, AvZ.maxItems on a field that is not a list), or sits on a relation or Json field. | Use an AvZ check that fits the field's type; a Json field's checks go in its json shape. |
141
+ | [`COMPILER_INVALID_JSON_SHAPE`](https://aventara-framework.vercel.app/docs/error-codes#compiler_invalid_json_shape) | A Json shape cannot apply. | A json shape on a field that is not a discovered Json field, a shape not built with AvZ, or one that admits null or absence at its top level. | Put the shape on a Json field, build it with AvZ, and keep its top level non-null (the column's nullability decides null). |
142
+ | [`COMPILER_INVALID_CLIENT_CONTRACT`](https://aventara-framework.vercel.app/docs/error-codes#compiler_invalid_client_contract) | The compiled client contract is invalid. | The finished client contract failed its own structural check: a framework defect. | Report it with the diagnostic's path and message. |
package/README.md CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  The Aventara framework itself: the framework factory (`createFramework`), configuration and its resolution, the
4
4
  adapter interfaces an ORM adapter implements, Contract compilation and identity, validation, operation semantics, the
5
- pipeline runtime, transactions and execution. Its HTTP protocol — passive data and pure functions; it mounts nothing —
6
- is the separate entry point `@aventara/core/protocol`, which hosts such as `@aventara/nest` serve.
5
+ pipeline runtime, transactions and execution. Its HTTP protocol is the separate entry point `@aventara/core/protocol`,
6
+ which hosts such as `@aventara/nest` serve. The protocol is passive data and pure functions, and it mounts nothing.
7
7
 
8
- Core is ORM- and transport-agnostic: it imports neither Prisma nor NestJS. An application uses it through an adapter
9
- (`@aventara/prisma7-adapter`) and a host (`@aventara/nest`), and the usual way to set that up is the CLI.
8
+ Core imports neither Prisma nor NestJS. An application uses it through an adapter (`@aventara/prisma7-adapter`) and a
9
+ host (`@aventara/nest`), and the usual way to set that up is the CLI.
10
10
 
11
11
  ## Install
12
12
 
@@ -20,17 +20,17 @@ Node `^22.18.0 || >=24.2.0`. ES modules, with a CommonJS `default` condition.
20
20
 
21
21
  ## Documentation
22
22
 
23
- Start from the `@aventara/cli` README (what `new` and `init` write), then `@aventara/nest` (mounting a `Framework`)
24
- and `@aventara/prisma7-adapter` (the Prisma 7 adapter and its generate step); each package's README ships in its
23
+ Start from the `@aventara/cli` README (what `new` and `init` write), then `@aventara/nest` (mounting an `AvFramework`)
24
+ and `@aventara/prisma7-adapter` (the Prisma 7 adapter and its generate step). Each package's README ships in its
25
25
  tarball and shows on its npm page.
26
26
 
27
27
  ## Typed Json fields
28
28
 
29
- A `Json` field is any JSON by default. To give it a shape, build one with `AvZ` from `@aventara/core/json` and declare
30
- it on the field in the configuration:
29
+ A `Json` field is any JSON by default. To give it a shape, build one with `AvZ` from `@aventara/core/avz` and declare
30
+ it as the field's `definition.json` in the configuration's `resources` tree:
31
31
 
32
32
  ```ts
33
- import { AvZ } from "@aventara/core/json";
33
+ import { AvZ } from "@aventara/core/avz";
34
34
 
35
35
  const postMeta = AvZ.object({
36
36
  seo: AvZ.object({ title: AvZ.string(), keywords: AvZ.array(AvZ.string()) }),
@@ -42,86 +42,276 @@ const postMeta = AvZ.object({
42
42
  export type PostMeta = AvZ.infer<typeof postMeta>;
43
43
 
44
44
  const framework = await createFramework({
45
- entrypoint: "/api",
45
+ api: "/api",
46
46
  adapter,
47
- fields: { Post: { meta: { json: postMeta } } },
47
+ resources: { Post: { fields: { meta: { definition: { json: postMeta } } } } },
48
48
  });
49
49
  ```
50
50
 
51
- - **Typed.** `framework.application`, `framework.client`, `appTx` and `clientTx` read and write `Post.meta` as
52
- `PostMeta`, not as generic JSON, and so does a client generated with `avclient` (it emits the type; it needs no
53
- Zod).
54
- - **Checked on every write.** A create, update, upsert, nested write or transaction step that writes `meta` — a value
55
- a transaction step takes from an earlier step included — is checked against the shape before the database is
56
- asked. A value out of shape is refused with `A2004`, one issue per problem at its exact path:
51
+ `framework.application`, `framework.client`, `appTx` and `clientTx` read and write `Post.meta` as `PostMeta` instead
52
+ of generic JSON. So does a client generated with `avclient`, which emits the type and needs no Zod.
57
53
 
58
- ```json
59
- { "code": "V1001", "path": ["arguments", "data", "meta", "seo", "title"], "message": "Value must be a string." }
60
- ```
54
+ The shape is also one of `meta`'s validators. Every write of `meta` is checked against it before the database is
55
+ asked: a create, update, upsert, nested write or transaction step, including a value a transaction step takes from an
56
+ earlier step. It is checked where validators run, after every pipe and write compute and before any interceptor or hook, and its issues
57
+ come in field order with the other validators'. A value out of shape is refused with `A2004`, one issue per problem at its
58
+ exact path:
59
+
60
+ ```json
61
+ { "code": "V1001", "path": ["arguments", "data", "meta", "seo", "title"], "message": "Value must be a string." }
62
+ ```
61
63
 
62
- A missing key is `V1000`, a value outside an enum or a literal `V1002`, an integer outside the safe range `V1004`,
63
- and a key the shape does not declare `V1005`, once per key. Reads and filters are never checked against a shape, so
64
- rows written before the shape existed stay readable.
65
- - **Types only.** `AvZ` has `string`, `number`, `int`, `boolean`, `null`, `literal`, `enum`, `object`, `array`,
66
- `tuple`, `record`, `union`, `discriminatedUnion`, `optional` and `nullable` — no lengths, ranges, patterns,
67
- refinements, transforms or defaults. Objects are closed: a key the shape does not declare is refused. `optional`
68
- marks an object key that may be left out.
69
- - **Where it applies.** Only a field the adapter discovered as `Json` takes a shape, and the shape itself cannot admit
70
- `null` or absence at its top level — whether the field may be `null` comes from your schema. A shape is built with
71
- `AvZ` only: a Zod schema is not accepted, as a type error and when the framework starts.
72
- - **In the Contract.** The shape is part of the ClientContract, as JSON Schema; adding or changing one changes the
73
- ClientContract hash, so regenerate the client.
64
+ A missing key is `V1000`, a value outside an enum or a literal `V1002`, an integer outside the safe range `V1004`,
65
+ and a key the shape does not declare `V1005`, once per key. Reads and filters are never checked against a shape, so
66
+ rows written before the shape existed stay readable.
67
+
68
+ `AvZ` has `string`, `number`, `int`, `boolean`, `null`, `literal`, `enum`, `object`, `array`, `tuple`, `record`,
69
+ `union`, `discriminatedUnion`, `optional` and `nullable`. A shape node takes checks with `.check(...)`: a string takes
70
+ length, pattern and format checks, a number or an integer takes bounds and `multipleOf`, and an array takes
71
+ `AvZ.minItems`/`AvZ.maxItems`, as in `AvZ.string().check(AvZ.maxLength(80))`. There are no refinements, transforms or
72
+ defaults. Objects are closed: a key the shape does not declare is refused. `optional` marks an object key that may be
73
+ left out.
74
+
75
+ Only a field the adapter discovered as `Json` takes a shape. The shape cannot admit `null` or absence at its top
76
+ level; whether the field may be `null` comes from your schema. A shape is built with `AvZ` only. A Zod schema is
77
+ refused, both as a type error and when the framework starts.
78
+
79
+ The shape is part of the ClientContract, as JSON Schema. Adding or changing one changes the ClientContract hash, so
80
+ regenerate the client.
74
81
 
75
82
  The shape types `AvZShape`, `AvZObject`, `AvZOptional` and `AvZNullable` are exported so a project that emits
76
83
  declarations can name the shapes it exports.
77
84
 
78
- `@aventara/core/json` is the only entry that loads Zod (`zod/mini`); an application that declares no shape never loads
85
+ `@aventara/core/avz` is the only entry that loads Zod (`zod/mini`); an application that declares no shape never loads
79
86
  it.
80
87
 
88
+ ## Server-side calls resolve their data and throw their failures
89
+
90
+ `framework.application`, `framework.client`, `framework.transaction([...])` and a pipeline's `ctx` calls settle the way
91
+ a generated client does: they resolve the data (a row, a list, a count, `null` for a `first` that matched nothing; a
92
+ committed transaction its steps' results in order) and throw every failure as the `AvError` subclass of its code's
93
+ class, exported from `@aventara/core`:
94
+
95
+ ```ts
96
+ import { AvNotFoundError, AvValidationError } from "@aventara/core";
97
+
98
+ try {
99
+ const post = await framework.application.Post.update.unique({ where: { id }, data: { title } });
100
+ } catch (error) {
101
+ if (error instanceof AvNotFoundError) return null; // A2003
102
+ if (error instanceof AvValidationError) throw badRequest(error.cause.issues);
103
+ throw error;
104
+ }
105
+ ```
106
+
107
+ | Class | Codes |
108
+ | ------------------------- | ------------------------------------------- |
109
+ | `AvProtocolError` | A2000, A2001, A2002, A2006, A2010–A2012 |
110
+ | `AvNotFoundError` | A2003 |
111
+ | `AvValidationError` | A2004, A2007, A2009 |
112
+ | `AvContractMismatchError` | A2005 |
113
+ | `AvConflictError` | A2008, A2013, A2014 |
114
+ | `AvInternalError` | A3000–A3004 |
115
+ | `AvAuthError` | A4000–A4002 |
116
+
117
+ `error.code` and `error.cause` are the envelope's (a transaction's `cause.operation` names the failing step). The
118
+ generated client throws the same classes by the same table. `framework.execute` and `framework.executeTransaction`, the
119
+ entries a transport calls, still answer the envelope.
120
+
121
+ ## Every code, explained
122
+
123
+ `AvErrorCatalog` holds every code this package answers, reports in a validation issue, or refuses to start with: its
124
+ `kind`, `message`, `cause`, `fix` and `docs` URL. The same catalog ships beside `dist` as `ERRORS.md`, and each entry
125
+ of a startup `AvConstructionError`'s `diagnostics` carries its code's `docs` URL.
126
+
127
+ ```ts
128
+ import { AvErrorCatalog } from "@aventara/core";
129
+
130
+ AvErrorCatalog.A2004.fix; // "Fix the argument each issue's path points at, …"
131
+ AvErrorCatalog.V1000.docs; // "https://aventara-framework.vercel.app/docs/error-codes#v1000"
132
+ ```
133
+
134
+ ## Required create fields are typed
135
+
136
+ Each Resource's Contract states what a create cannot do without (`createRequirements`), as the adapter reads it off
137
+ the database schema: the fields every create must write, and each required relation, which a create writes either as
138
+ the relation or through the fields that hold its reference, never both. The façades, `appTx`/`clientTx`, a stage's
139
+ `ctx` and the generated client type every create payload by it:
140
+
141
+ ```ts
142
+ await framework.application.Post.create.one({ data: { title: "Hi", authorId } }); // ok
143
+ await framework.application.Post.create.one({ data: { title: "Hi", author: { $connect: { id: authorId } } } }); // ok
144
+ // @ts-expect-error neither `author` nor `authorId`
145
+ await framework.application.Post.create.one({ data: { title: "Hi" } });
146
+ // @ts-expect-error `author` and `authorId` both
147
+ await framework.application.Post.create.one({ data: { title: "Hi", authorId, author: { $connect: { id: authorId } } } });
148
+ ```
149
+
150
+ It covers `create.one`'s `data`, every `create.many` record, `upsert`'s `create`, and nested `$create`,
151
+ `$connectOrCreate` and `$upsert` payloads, where the relation the create is nested through is supplied by its parent.
152
+ A `$ref` satisfies a field. Each layer's Contract states only what that layer lets a caller write: hide `authorId` and
153
+ `author` alone is required; hide `author` and `authorId` is. A field a `compute.create` stage fills is not required,
154
+ whether the stage is written inline in `createFramework({...})`, in a `defineResource` block or in a typed config.
155
+ The runtime still refuses what the types refuse (`A2004`, `V1000` or `V1012`).
156
+
157
+ A `create.many` or `create.count` record cannot write a relation, so there `authorId` is required. A layer that hides
158
+ `authorId` while it keeps those variants fails at startup (`COMPILER_HIDDEN_REQUIRED_FIELD`): expose `authorId`, give
159
+ it a `compute.create`, or exempt `create.many` and `create.count` in that layer
160
+ (`exemptions: { resources: { Post: { fields: { authorId: true }, operations: { create: ["many", "count"] } } } }`).
161
+
162
+ A field your operation pipe fills server-side is now required of the caller. Give it a `compute.create` stage (or a
163
+ database default) so callers can leave it out, or have them pass it.
164
+
165
+ Inside the pipeline the requirements hold from write compute on. A variant's guards, pipes and filters run before
166
+ compute, and their typed arguments require no field of a create, since compute may still fill it: `args.data.slug` is
167
+ `string | undefined` in a pipe, and a pipe may return a create without it. The variant's hooks and interceptors run
168
+ after compute and see every required field present.
169
+
170
+ ## Returning a façade from a method
171
+
172
+ A Nest project emits declarations (`declaration: true`), so a method without a return type has its type written out.
173
+ Every node of the typed façades has a name for that: a whole surface (`AvApplicationFacade`), one Resource
174
+ (`AvApplicationResourceFacade`), one family (`AvApplicationFamilyFacade`), and the same three for `client`, `appTx` and
175
+ `clientTx` (`AvClientFacade`, `AvAppTxResourceFacade`, …). The declaration writes the name, with the Contract view as
176
+ its argument, so this compiles:
177
+
178
+ ```ts
179
+ @Injectable()
180
+ export class PostsService {
181
+ constructor(@InjectFramework() private readonly framework: AppFramework) {}
182
+
183
+ posts() {
184
+ return this.framework.application.Post;
185
+ }
186
+ }
187
+ ```
188
+
189
+ The view is written out in full, about 400 KB of declaration per such method over 50 Resources. Give the method a
190
+ return type to keep it small: `AppFramework["application"]["Post"]` is written as that reference, about 0.2 KB.
191
+
192
+ ```ts
193
+ posts(): AppFramework["application"]["Post"] {
194
+ return this.framework.application.Post;
195
+ }
196
+ ```
197
+
198
+ A variant (`this.framework.application.Post.find.many`) is a call type the declaration cannot name: give that method a
199
+ return type, or return the call's result, whose row type is small. An application that publishes no declarations can
200
+ set `"declaration": false` and skip the question.
201
+
202
+ The configuration itself costs almost nothing to declare. The Prisma adapter's discovery artifact names the model's
203
+ type (`AvModel`), so the scaffold's `aventaraConfig()`, a `buildFramework` and its `AppFramework` alias write
204
+ `AvAdapter<AvModel>` and `AvFramework<AvModel, …>`: about 0.5 KB at any schema size, where rc.1 wrote
205
+ the model out once per mention (1.2 MB over 50 Resources).
206
+
207
+ An exported `defineResource(...)` result, and an exported configuration or Framework builder holding typed stages,
208
+ need no annotation: their stages are written by their public types (`readonly AvGuard[]`, `readonly AvPipe[]`, …),
209
+ never with the model the inline stages were typed from.
210
+
81
211
  ## Server-side calls copy their input
82
212
 
83
213
  `framework.application`, `framework.client`, `framework.execute`, `framework.executeTransaction`, and the `appTx` /
84
214
  `clientTx` builders read what you pass them once, when you call them, and copy it into plain data the framework owns.
85
- Everything after that — validation, your guards and pipes, computed values, the adapter — sees only the copy:
86
-
87
- - **Changing your object afterwards changes nothing.** An Immer draft revoked after `produce`, or a reactive store that
88
- moves on, is safe to pass: the call already has its own copy.
89
- - **A live Proxy works** (Vue `reactive`, MobX): it is read through its traps once.
90
- - **`Date`, `Decimal` and `Uint8Array`** (a Node `Buffer` too) are copied as themselves; `bigint` and other primitives are
91
- values.
92
- - **Only plain data.** Arrays and plain objects (`{}` or `Object.create(null)`) are copied with their own enumerable
93
- string keys, like JSON: inherited, non-enumerable and symbol keys are dropped. Any other object — a class instance, a
94
- `Map` — is refused.
95
- - **A value that cannot be read** (a revoked Proxy, a getter that throws) is refused too. Both refusals are your
96
- request's error, not the server's: `A2004` with one `V1001` at the value's path — `["arguments", …]`, or
97
- `["operations", i, "args", …]` with `cause.operation` in a transaction — before any guard, pipe or adapter runs:
215
+ Validation, your guards and pipes, computed values and the adapter all see only the copy, and your stages see it
216
+ frozen: only a pipe changes the arguments, by returning new ones, so what the validators checked is what the adapter
217
+ writes. In practice:
218
+
219
+ - Changing your object afterwards changes nothing. An Immer draft revoked after `produce`, or a reactive store that
220
+ moves on, is safe to pass, because the call already has its own copy.
221
+ - A live Proxy (Vue `reactive`, MobX) works: it is read through its traps once.
222
+ - `Date`, `AvDecimal` and `Uint8Array` (a Node `Buffer` too) are copied as themselves; `bigint` and other primitives
223
+ are values.
224
+ - Arrays and plain objects (`{}` or `Object.create(null)`) are copied with their own enumerable string keys, like JSON:
225
+ inherited, non-enumerable and symbol keys are dropped. Any other object, such as a class instance or a `Map`, is
226
+ refused.
227
+ - A value that cannot be read (a revoked Proxy, a getter that throws) is refused too. Both refusals are errors in your
228
+ request, not the server's: `A2004` with one `V1001` at the value's path (`["arguments", …]`, or
229
+ `["operations", i, "args", …]` with `cause.operation` in a transaction), before any guard, pipe or adapter runs:
98
230
 
99
231
  ```json
100
232
  { "code": "V1001", "path": ["arguments", "where", "id"], "message": "Value could not be read." }
101
233
  ```
102
234
 
103
- A builder never throws: `appTx`/`clientTx` keep the refusal, and `framework.transaction([...])` answers it.
235
+ A builder never throws: `appTx`/`clientTx` keep the refusal, and `framework.transaction([...])` throws it as an
236
+ `AvValidationError`.
104
237
 
105
238
  To count these refusals, set `misuse` at the root of the configuration, beside `diagnostics`:
106
239
 
107
240
  ```ts
108
241
  const framework = await createFramework({
109
- entrypoint: "/api",
242
+ api: "/api",
110
243
  adapter,
111
244
  misuse: (event) => metrics.increment("aventara.misuse", { kind: event.kind }),
112
245
  });
113
246
  ```
114
247
 
115
- It receives one `FrameworkMisuseEvent` per refusal — `kind` (`"unreadable-value"` or `"non-plain-value"`), the `path`
116
- the caller received, and `origin`, `resource`, `family`, `variant` and the transaction step (`operation`) when they could
117
- be read — never the value itself. It cannot change the response: an error it throws, or a promise it rejects, is
118
- ignored. `diagnostics` keeps receiving the server's own unexpected failures, and nothing is reported to both.
248
+ It receives one `AvMisuseEvent` per refusal, never the value itself. The event has `kind` (`"unreadable-value"` or
249
+ `"non-plain-value"`), the `path` the caller received, and `origin`, `resource`, `family`, `variant` and the
250
+ transaction step (`operation`) when they could be read. It cannot change the response: an error it throws, or a
251
+ promise it rejects, is ignored. `diagnostics` keeps receiving the server's own unexpected failures, and nothing is
252
+ reported to both.
253
+
254
+ HTTP requests are not copied twice. A body that `protocol.handleOperation` / `handleTransaction` parse from raw content
255
+ (as `@aventara/nest` hands it to them) is already plain data. A body your host parsed itself, passed as
256
+ `{ kind: "parsed" }`, is copied like any server-side input.
257
+
258
+ ## Developer SQL in an application transaction
259
+
260
+ `framework.appTx.$sql` adds a SQL statement to an application transaction. It is written only as a tagged template, and
261
+ every interpolated value is a bound parameter, never part of the SQL text:
262
+
263
+ ```ts
264
+ const post = framework.appTx.Post.create.one({ data: { title, authorId }, select: ["id"] });
265
+ const job = framework.appTx.$sql<{ msg_id: bigint }>`
266
+ select pgmq.send('jobs', jsonb_build_object('postId', ${post.$ref("id")}))`;
267
+
268
+ const [created, rows] = await framework.transaction([post, job]);
269
+ // rows is { msg_id: bigint }[]; without <Row> it is unknown[]
270
+ ```
271
+
272
+ - The statement runs in plan order, in the same database transaction as the other steps. If it fails, or a later step
273
+ fails, everything rolls back.
274
+ - A value is a string, number, boolean, `bigint`, `null`, `Date`, `AvDecimal`, `Uint8Array`, a JSON value (a plain
275
+ object or array, bound as JSON text, so cast it: `${value}::jsonb`), or a `$ref` to an earlier step's field, which
276
+ is read after that step ran and then bound. Values are copied like every other input (see above).
277
+ - The SQL text is static. A table or column name cannot come from a value.
278
+ - A later step cannot `$ref` a SQL step's rows (`A2007`/`V1010`).
279
+ - No guard, pipe, hook, interceptor or filter runs around a SQL step. A SQL error is answered as the adapter
280
+ classifies it (a uniqueness or reference violation is `A2008`, anything else `A3001`).
281
+ - A stage's `ctx.$sql` runs the same bound template at once. Inside a transaction it joins it; outside one it is a plain
282
+ statement, with no transaction opened around it.
283
+ - It exists only here. `clientTx` has no `$sql`, the ClientContract carries nothing of it, and `/_transactions` cannot
284
+ express it. The adapter must support it (`@aventara/prisma7-adapter` does wherever it runs transactions); otherwise a
285
+ plan holding one is refused with `A2002`.
286
+
287
+ Aventara itself never writes raw SQL. This tagged template is the only way SQL reaches the database, and the SQL is
288
+ yours.
289
+
290
+ ## The agent layer
291
+
292
+ `agent` is a layer for calls an AI agent makes, served over MCP. It narrows the view of the layer it `extends`
293
+ (`"client"` when left out, or `"application"`, or `"root"`) and never widens it; its stages run after that layer's, and
294
+ each one sees `ctx.$origin === "agent"`:
295
+
296
+ ```ts
297
+ const framework = await createFramework({
298
+ api: "/api",
299
+ mcp: "/mcp",
300
+ adapter,
301
+ agent: {
302
+ exposed: true,
303
+ exemptions: { resources: { Post: { operations: { delete: true } } } },
304
+ pipelines: { guards: [(ctx) => ctx.$state.user !== undefined] },
305
+ },
306
+ });
307
+ ```
119
308
 
120
- HTTP requests cost nothing extra: a body that `protocol.handleOperation` / `handleTransaction` parse from raw content
121
- (as `@aventara/nest` hands it to them) is already plain data and is not copied again. A body your host parsed itself,
122
- passed as `{ kind: "parsed" }`, is copied like any server-side input.
309
+ It compiles to `framework.contracts.agent`, identified by its own hash, and `framework.mcp` is the resolved MCP
310
+ endpoint. A host runs agent calls through `AvProtocol.bind(framework, { origin: "agent" })`, which validates them
311
+ exactly as client calls are validated, against the Agent Contract.
123
312
 
124
313
  ## License
125
314
 
126
- PolyForm Shield 1.0.0 with an additional permission — free to use, including in commercial applications; you may not
127
- use it to build a product that competes with Aventara itself. See `LICENSE` and `LICENSE-ADDITIONAL-PERMISSION.md`.
315
+ PolyForm Shield 1.0.0 with an additional permission. It is free to use, including in commercial applications, but you
316
+ may not use it to build a product that competes with Aventara itself. See `LICENSE` and
317
+ `LICENSE-ADDITIONAL-PERMISSION.md`.
@@ -1,8 +1,8 @@
1
- /** Codes of {@link AdapterDiscoveryDiagnostic}. */
2
- export type AdapterDiscoveryDiagnosticCode = "DISCOVERY_TRANSACTION_CAPABILITY_MISMATCH";
1
+ /** Codes of {@link AvAdapterDiscoveryDiagnostic}. */
2
+ export type AvAdapterDiscoveryDiagnosticCode = "DISCOVERY_TRANSACTION_CAPABILITY_MISMATCH";
3
3
  /** A problem found in what the adapter discovered, reported at framework construction. */
4
- export type AdapterDiscoveryDiagnostic = {
5
- readonly code: AdapterDiscoveryDiagnosticCode;
4
+ export type AvAdapterDiscoveryDiagnostic = {
5
+ readonly code: AvAdapterDiscoveryDiagnosticCode;
6
6
  readonly path: "adapter.transactions";
7
7
  readonly message: string;
8
8
  };
@@ -0,0 +1,6 @@
1
+ import type { ErrorCodeDescription } from "../runtime/error-guidance.js";
2
+ import type { AvAdapterDiscoveryDiagnosticCode } from "./adapter-discovery-diagnostic.js";
3
+ /** Meaning, cause and fix of every discovery diagnostic code. */
4
+ export declare const ADAPTER_DISCOVERY_DIAGNOSTIC_GUIDANCE: {
5
+ readonly [C in AvAdapterDiscoveryDiagnosticCode]: ErrorCodeDescription;
6
+ };
@@ -0,0 +1,7 @@
1
+ export const ADAPTER_DISCOVERY_DIAGNOSTIC_GUIDANCE = {
2
+ DISCOVERY_TRANSACTION_CAPABILITY_MISMATCH: {
3
+ message: "The adapter's transaction capability does not match it.",
4
+ cause: "The adapter declares interactive transactions but provides no transaction function.",
5
+ fix: "A defect of the adapter: install the adapter release that matches @aventara/core exactly.",
6
+ },
7
+ };