@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
@@ -0,0 +1,275 @@
1
+ import { isOperationVariantAvailable } from "../contracts/resource-operations.js";
2
+ import { parseOperationIdentity } from "../operations/operation-identity.js";
3
+ import { validationIssue } from "../operations/validation-code.js";
4
+ import { readSqlTemplate } from "../transactions/sql-statement.js";
5
+ import { normalizeSqlValue } from "../transactions/sql-statement.validator.js";
6
+ import { AvTransactionIntegrityError } from "../transactions/transaction-integrity-error.js";
7
+ import { transactionInfrastructureFailure } from "../transactions/transaction-response.js";
8
+ import { copyAtDoor, refuseCallerData } from "./caller-data.door.js";
9
+ import { createReporter, } from "./diagnostics-reporter.js";
10
+ import { AdapterBoundary, sanitizeOperationFailure } from "./error-boundary.js";
11
+ import { thrownFailure } from "./framework-error.factory.js";
12
+ import { operationFailure } from "./operation-response.js";
13
+ import { mapValidationOutcome } from "./outcome-mapper.js";
14
+ import { readonlyView } from "./readonly-value.js";
15
+ const COMPUTE_STATE = "Compute's ctx.$state";
16
+ const STATE = Symbol("aventara.context");
17
+ const READ_FAMILY = "find";
18
+ function readOnlyRefusal(member) {
19
+ return new TypeError(`Compute's ctx is read-only: ${member} is not available in a compute stage. Put effects on other rows in an after hook.`);
20
+ }
21
+ function refusedStatement(issues) {
22
+ return mapValidationOutcome(issues);
23
+ }
24
+ function unavailable(message) {
25
+ return operationFailure("A2002", {
26
+ message,
27
+ issues: [validationIssue("V1006", [], message)],
28
+ });
29
+ }
30
+ export function createContextExecutor(dependencies) {
31
+ const { adapter, misuse } = dependencies;
32
+ const model = dependencies.model;
33
+ const stateOf = (context) => context[STATE];
34
+ const reporterOf = (scope) => createReporter(dependencies.diagnostics, {
35
+ kind: "transaction",
36
+ origin: "application",
37
+ requestId: scope.requestId,
38
+ });
39
+ const call = async (scope, resource, identity, args) => {
40
+ const response = await dependencies.run({
41
+ ...identity,
42
+ origin: "application",
43
+ resource,
44
+ requestId: scope.requestId,
45
+ state: scope.state,
46
+ arguments: args === undefined ? {} : args,
47
+ }, scope.transaction);
48
+ if (response.cause !== null) {
49
+ throw thrownFailure(response);
50
+ }
51
+ return response.data;
52
+ };
53
+ const resourceTree = (scope, resource, readOnly) => {
54
+ const families = {};
55
+ const operations = model.resources[resource]?.operations ?? {};
56
+ for (const [family, variants] of Object.entries(operations)) {
57
+ if (readOnly && family !== READ_FAMILY) {
58
+ continue;
59
+ }
60
+ const leaves = {};
61
+ for (const [variant, availability] of Object.entries(variants ?? {})) {
62
+ const identity = parseOperationIdentity(family, variant);
63
+ if (identity !== undefined &&
64
+ isOperationVariantAvailable(availability)) {
65
+ leaves[variant] = (args) => call(scope, resource, identity, args);
66
+ }
67
+ }
68
+ families[family] = Object.freeze(leaves);
69
+ }
70
+ if (readOnly) {
71
+ const tree = Object.create(Object.prototype);
72
+ for (const [family, leaves] of Object.entries(families)) {
73
+ Object.defineProperty(tree, family, {
74
+ value: leaves,
75
+ enumerable: true,
76
+ });
77
+ }
78
+ for (const family of Object.keys(operations)) {
79
+ if (family === READ_FAMILY) {
80
+ continue;
81
+ }
82
+ Object.defineProperty(tree, family, {
83
+ get() {
84
+ throw readOnlyRefusal(`ctx.${resource}.${family}`);
85
+ },
86
+ enumerable: false,
87
+ });
88
+ }
89
+ return Object.freeze(tree);
90
+ }
91
+ return Object.freeze(families);
92
+ };
93
+ const statementOf = (strings, values) => {
94
+ if (adapter.sqlStatements !== true) {
95
+ return {
96
+ ok: false,
97
+ response: unavailable("SQL statements are not available on this Adapter."),
98
+ };
99
+ }
100
+ const text = readSqlTemplate(strings, values.length);
101
+ if (text === undefined) {
102
+ return {
103
+ ok: false,
104
+ response: refusedStatement([
105
+ validationIssue("V1001", ["strings"], "SQL must be written as a tagged template: ctx.$sql`…`."),
106
+ ]),
107
+ };
108
+ }
109
+ const copy = copyAtDoor([...values]);
110
+ if (!copy.ok) {
111
+ return {
112
+ ok: false,
113
+ response: refusedStatement([
114
+ refuseCallerData(copy.error, ["values"], { origin: "application" }, misuse),
115
+ ]),
116
+ };
117
+ }
118
+ const bound = [];
119
+ const issues = [];
120
+ for (const [position, value] of copy.value.entries()) {
121
+ const normalized = normalizeSqlValue(value, ["values", position]);
122
+ if (normalized.ok) {
123
+ bound.push(normalized.value);
124
+ }
125
+ else {
126
+ issues.push(...normalized.issues);
127
+ }
128
+ }
129
+ if (issues.length > 0) {
130
+ return { ok: false, response: refusedStatement(issues) };
131
+ }
132
+ return { ok: true, statement: { strings: text, values: bound } };
133
+ };
134
+ const executeStatement = async (runner, inTransaction, statement, report) => {
135
+ if (inTransaction && typeof runner.executeSql !== "function") {
136
+ const error = new AvTransactionIntegrityError("statement-unavailable");
137
+ report(error, "A3002");
138
+ throw thrownFailure(transactionInfrastructureFailure());
139
+ }
140
+ const boundary = new AdapterBoundary();
141
+ try {
142
+ return await boundary.execute(async () => {
143
+ if (typeof runner.executeSql !== "function") {
144
+ throw new TypeError("Adapter declares sqlStatements but has no executeSql.");
145
+ }
146
+ const rows = await runner.executeSql(statement);
147
+ if (!Array.isArray(rows)) {
148
+ throw new TypeError("Adapter executeSql must resolve the statement's rows as an array.");
149
+ }
150
+ return [...rows];
151
+ });
152
+ }
153
+ catch (error) {
154
+ throw thrownFailure(sanitizeOperationFailure(error, boundary.originOf(error), report, {
155
+ path: ["values"],
156
+ arguments: statement.values,
157
+ }));
158
+ }
159
+ };
160
+ const openTransaction = async (scope, work) => {
161
+ if (typeof adapter.transaction !== "function") {
162
+ throw thrownFailure(unavailable("Transactions are not available on this Adapter."));
163
+ }
164
+ let thrown;
165
+ try {
166
+ return await adapter.transaction(async (executor) => {
167
+ try {
168
+ return await work(executor);
169
+ }
170
+ catch (error) {
171
+ thrown = { error };
172
+ throw error;
173
+ }
174
+ });
175
+ }
176
+ catch (error) {
177
+ if (thrown !== undefined && error === thrown.error) {
178
+ throw error;
179
+ }
180
+ reporterOf(scope)(error, "A3002");
181
+ throw thrownFailure(transactionInfrastructureFailure());
182
+ }
183
+ };
184
+ const sql = async (scope, strings, values) => {
185
+ const prepared = statementOf(strings, values);
186
+ if (!prepared.ok) {
187
+ throw thrownFailure(prepared.response);
188
+ }
189
+ const report = reporterOf(scope);
190
+ const open = scope.transaction;
191
+ return open !== undefined
192
+ ? executeStatement(open, true, prepared.statement, report)
193
+ : executeStatement(adapter, false, prepared.statement, report);
194
+ };
195
+ const contextOf = (prototype, scope, facts, readOnly = false) => {
196
+ const context = Object.create(prototype);
197
+ Object.defineProperty(context, STATE, {
198
+ value: { scope, facts, resources: new Map() },
199
+ });
200
+ for (const [key, value] of Object.entries(facts)) {
201
+ if (value !== undefined) {
202
+ Object.defineProperty(context, key, { value, enumerable: true });
203
+ }
204
+ }
205
+ Object.defineProperty(context, "$state", {
206
+ value: readOnly ? readonlyView(scope.state, COMPUTE_STATE) : scope.state,
207
+ enumerable: true,
208
+ });
209
+ return context;
210
+ };
211
+ const transactionOf = (prototype) => (context, work) => {
212
+ const { scope, facts } = stateOf(context);
213
+ if (typeof work !== "function") {
214
+ return Promise.reject(new TypeError("ctx.$transaction takes an async callback: (tx) => …"));
215
+ }
216
+ const run = work;
217
+ if (scope.transaction !== undefined) {
218
+ return (async () => run(context))();
219
+ }
220
+ if (dependencies.application.transactions === "none") {
221
+ return Promise.reject(thrownFailure(unavailable("Transactions are not available on the application Contract.")));
222
+ }
223
+ return openTransaction(scope, (executor) => run(contextOf(prototype, {
224
+ requestId: scope.requestId,
225
+ transaction: executor,
226
+ state: scope.state,
227
+ }, facts)));
228
+ };
229
+ const prototypeOf = (readOnly) => {
230
+ const prototype = {};
231
+ for (const resource of Object.keys(model.resources)) {
232
+ Object.defineProperty(prototype, resource, {
233
+ get() {
234
+ const state = stateOf(this);
235
+ let tree = state.resources.get(resource);
236
+ if (tree === undefined) {
237
+ tree = resourceTree(state.scope, resource, readOnly);
238
+ state.resources.set(resource, tree);
239
+ }
240
+ return tree;
241
+ },
242
+ });
243
+ }
244
+ if (readOnly) {
245
+ for (const member of ["$sql", "$transaction"]) {
246
+ Object.defineProperty(prototype, member, {
247
+ get() {
248
+ throw readOnlyRefusal(`ctx.${member}`);
249
+ },
250
+ });
251
+ }
252
+ return Object.freeze(prototype);
253
+ }
254
+ const transaction = transactionOf(prototype);
255
+ Object.defineProperty(prototype, "$sql", {
256
+ get() {
257
+ const { scope } = stateOf(this);
258
+ return (strings, ...values) => sql(scope, strings, values);
259
+ },
260
+ });
261
+ Object.defineProperty(prototype, "$transaction", {
262
+ get() {
263
+ return (work) => transaction(this, work);
264
+ },
265
+ });
266
+ return Object.freeze(prototype);
267
+ };
268
+ const full = prototypeOf(false);
269
+ const reads = prototypeOf(true);
270
+ return {
271
+ operation: (scope, facts) => contextOf(full, scope, facts),
272
+ transaction: (scope, facts) => contextOf(full, scope, facts),
273
+ compute: (scope, facts) => contextOf(reads, scope, facts, true),
274
+ };
275
+ }
@@ -1,101 +1,66 @@
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 { AvCreateRequirements } from "../contracts/create-requirements.js";
3
+ import type { AvOperationIdentity } from "../operations/operation-identity.js";
4
+ import type { AvValidationIssue } from "../operations/validation-code.js";
4
5
  import type { ReferentialActionTable } from "./referential-action.js";
5
- /**
6
- * Core's create-requirement vocabulary, and the check that reads it.
7
- *
8
- * **The facts are an Adapter's.** Which values a store cannot create a row
9
- * without is a property of the store's schema — a column with no default, a
10
- * reference that must point somewhere — and only the Adapter can read it. The
11
- * words are Aventara's, so an Adapter translates its provider's facts into them,
12
- * and the reasoning over them is core's, so no Adapter re-implements it.
13
- *
14
- * None of this enters a Contract. A Contract carries no foreign-key detail and
15
- * no knowledge of which relation is the other end of which, and a requirement
16
- * needs both; it is a server-side fact, read once when the Framework is
17
- * constructed, like the referential actions.
18
- *
19
- * **When the check runs.** After guards, pipes and computed write behaviours —
20
- * the moment the arguments are what the Adapter will be handed — and before
21
- * any `before` hook or Adapter work. Earlier would refuse a value a pipe or a
22
- * computed behaviour was about to supply; later is the store's own refusal,
23
- * which reaches the caller as an internal failure. A missing value is the
24
- * caller's to fix, so it answers `A2004` with a `V1000` issue at the path where
25
- * the value belongs.
26
- *
27
- * **One value, two spellings.** A relation that holds a reference has scalar
28
- * fields that hold it too — the Adapter states which, on the relation's
29
- * referential edge (`ReferentialEdge.references`), for every such relation,
30
- * required or optional. A write that sets both — `authorId` and
31
- * `author: { $connect: … }` in one record, at create or update — names the
32
- * reference twice. No store can honour both, and which one the caller meant is
33
- * not the framework's to guess, so it is the caller's `A2004` too: a `V1012`
34
- * issue at the relation, in every record the check walks, before any Adapter
35
- * work. The same edge is what a required relation may instead be written
36
- * through, so the pairing has one source.
37
- *
38
- * **One store, one spelling per record.** A store may take a record's
39
- * references only one way at a time — every relation that holds one written as
40
- * a relation, or every one through its fields — and state it as the Contract's
41
- * `referenceWrites: "uniform"`. Under it, a record that writes a relation
42
- * holding a reference beside another relation's reference field is the caller's
43
- * `A2004` as well: a `V1012` issue at the relation write.
44
- */
45
- /** A relation edge, named by the Resource that holds it and its field there. */
46
- export type CreateRequirementEdge = {
6
+ type Path = readonly (string | number)[];
7
+ /** One required field a `compute.create` stage was to fill and left missing. */
8
+ export type ComputedRequirementGap = {
47
9
  readonly resource: string;
48
- readonly relation: string;
49
- };
50
- /**
51
- * One value a create of a Resource cannot do without.
52
- *
53
- * - `field` — a scalar with no default, generated value or other source: it
54
- * must be written.
55
- * - `relation` — a required to-one relation: it must be written (connected or
56
- * created), or every field that holds its reference must be — the
57
- * `references` of the relation's referential edge, less any the store fills
58
- * itself (`DEFAULTED` or `GENERATED_ON_CREATE`). When the row is created
59
- * **through** the relation's other end (`inverse`), the parent supplies it,
60
- * and it is not required.
61
- */
62
- export type CreateRequirement = {
63
- readonly kind: "field";
64
10
  readonly field: string;
65
- } | {
66
- readonly kind: "relation";
67
- readonly relation: string;
68
- readonly inverse?: CreateRequirementEdge;
11
+ readonly issue: AvValidationIssue;
69
12
  };
70
13
  /**
71
- * Every Resource's create requirements, keyed by Resource. A Resource that is
72
- * absent, or carries an empty list, requires nothing core can check.
73
- */
74
- export type CreateRequirementTable = Readonly<Record<string, readonly CreateRequirement[]>>;
75
- type Path = readonly (string | number)[];
76
- /**
77
- * What the Adapter stated that the check reads: its create requirements, and
78
- * its referential edges for the fields that hold each reference. Read once when
79
- * the Framework is constructed.
14
+ * What the Adapter stated that the checks read: its referential edges, for the
15
+ * fields that hold each reference, and its own create requirements per
16
+ * Resource, before any layer projected them (what write compute must not leave
17
+ * missing). Read once when the Framework is constructed. The requirements the
18
+ * caller is held to are the active Contract's.
80
19
  */
81
20
  export type RecordWriteFacts = {
82
- readonly requirements: CreateRequirementTable;
83
21
  readonly references: ReferentialActionTable;
22
+ readonly stated: (resource: string) => AvCreateRequirements | undefined;
84
23
  };
85
24
  /** The facts an Adapter stated, read off it once; an absent table states nothing. */
86
25
  export declare function recordWriteFactsOf(adapter: {
87
- readonly createRequirements?: CreateRequirementTable;
88
26
  readonly referentialActions?: ReferentialActionTable;
27
+ readonly model?: {
28
+ readonly resources: Readonly<Record<string, unknown>>;
29
+ };
89
30
  }): RecordWriteFacts;
90
31
  /**
91
32
  * The `V1000` issues for every create position in one operation's arguments
92
- * that lacks a value the Adapter requires — `create.*`'s `data`, `upsert`'s
33
+ * that lacks a value the active Contract requires — `create.*`'s `data`, `upsert`'s
93
34
  * `create`, and every nested create under any write — and the `V1012` issues
94
35
  * for every write record, create or update, that sets a relation and its
95
36
  * reference both, in argument order. Empty when there are none. Total over
96
37
  * malformed input.
97
38
  */
98
- export declare function createRequirementIssues(contract: Contract, facts: RecordWriteFacts, request: OperationIdentity & {
39
+ export declare function createRequirementIssues(contract: AvContract, facts: Pick<RecordWriteFacts, "references">, request: AvOperationIdentity & {
40
+ readonly resource: string;
41
+ }, args: unknown, argumentsPath: Path): readonly AvValidationIssue[];
42
+ /**
43
+ * The `V1000` issues for every create position of one operation's arguments
44
+ * that lacks a value the active Contract requires, and the `V1012` issues for
45
+ * every write record that sets a relation and its reference both, on the
46
+ * arguments as the caller sent them, before any pipeline stage runs. Empty when
47
+ * there are none.
48
+ */
49
+ export declare function preliminaryRecordIssues(contract: AvContract, facts: Pick<RecordWriteFacts, "references">, request: AvOperationIdentity & {
50
+ readonly resource: string;
51
+ }, args: unknown, argumentsPath: Path): readonly AvValidationIssue[];
52
+ /**
53
+ * Every required field a `compute.create` stage was to fill and that is still
54
+ * missing after write compute, at every create position of one operation's
55
+ * arguments (`create.*`'s `data`, `upsert`'s `create`, every nested create),
56
+ * in argument order, read against the Adapter's own statement of each
57
+ * Resource's create requirements; `computed` names the fields a Resource's
58
+ * `compute.create` stages fill.
59
+ * A field the parent supplies to a nested create, a group whose relation the
60
+ * record writes, and a value the caller sent are not missing. Empty when
61
+ * nothing is.
62
+ */
63
+ export declare function computedRequirementGapsOf(contract: AvContract, facts: RecordWriteFacts, request: AvOperationIdentity & {
99
64
  readonly resource: string;
100
- }, args: unknown, argumentsPath: Path): readonly ValidationIssue[];
65
+ }, args: unknown, argumentsPath: Path, computed: (resource: string) => ReadonlySet<string>): readonly ComputedRequirementGap[];
101
66
  export {};