@aventara/core 0.1.0-pilot.4 → 1.0.0-rc.1
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.
- package/CHANGELOG.md +1478 -0
- package/README.md +275 -11
- package/dist/adapters/adapter-discovery-diagnostic.d.ts +4 -4
- package/dist/adapters/adapter-field.d.ts +11 -11
- package/dist/adapters/adapter-identifier.d.ts +6 -6
- package/dist/adapters/adapter-model.d.ts +17 -9
- package/dist/adapters/adapter-operation-executor.interface.d.ts +4 -4
- package/dist/adapters/adapter-operation.d.ts +3 -3
- package/dist/adapters/adapter-resource.d.ts +18 -9
- package/dist/adapters/adapter-sql-statement.d.ts +19 -0
- package/dist/adapters/adapter-transaction-executor.interface.d.ts +19 -0
- package/dist/adapters/adapter.interface.d.ts +49 -25
- package/dist/avz/avz-check.factory.d.ts +83 -0
- package/dist/avz/avz-check.factory.js +116 -0
- package/dist/avz/avz-check.registry.d.ts +35 -0
- package/dist/avz/avz-check.registry.js +9 -0
- package/dist/avz/avz.d.ts +203 -0
- package/dist/avz/avz.js +354 -0
- package/dist/avz/index.d.ts +7 -0
- package/dist/avz/index.js +1 -0
- package/dist/avz/json-shape.registry.d.ts +22 -0
- package/dist/avz/json-shape.registry.js +16 -0
- package/dist/avz/zod-issue.translator.d.ts +57 -0
- package/dist/avz/zod-issue.translator.js +149 -0
- package/dist/compiler/contract-compiler-diagnostic.d.ts +37 -5
- package/dist/compiler/contract.compiler.d.ts +18 -18
- package/dist/compiler/contract.compiler.js +595 -421
- package/dist/compiler/create-requirements.projector.d.ts +49 -0
- package/dist/compiler/create-requirements.projector.js +423 -0
- package/dist/compiler/field-validator.compiler.d.ts +47 -0
- package/dist/compiler/field-validator.compiler.js +238 -0
- package/dist/config/any-framework-config.d.ts +19 -12
- package/dist/config/config-diagnostic.d.ts +11 -4
- package/dist/config/config-layer.d.ts +15 -6
- package/dist/config/config.resolver.d.ts +75 -29
- package/dist/config/config.resolver.js +109 -44
- package/dist/config/config.validator.d.ts +7 -7
- package/dist/config/config.validator.js +586 -71
- package/dist/config/define-resource.d.ts +57 -0
- package/dist/config/define-resource.js +14 -0
- package/dist/config/effective-fields.d.ts +19 -23
- package/dist/config/entrypoint.normalizer.d.ts +1 -1
- package/dist/config/exact-framework-config.d.ts +280 -0
- package/dist/config/field-compute.resolver.d.ts +19 -0
- package/dist/config/field-compute.resolver.js +115 -0
- package/dist/config/field-pipeline-config.d.ts +47 -0
- package/dist/config/forced-operation.validator.d.ts +10 -0
- package/dist/config/forced-operation.validator.js +66 -0
- package/dist/config/framework-config.d.ts +111 -37
- package/dist/config/framework-exemptions-config.d.ts +91 -0
- package/dist/config/framework-exemptions-config.js +1 -0
- package/dist/config/framework-field-definition.d.ts +78 -0
- package/dist/config/framework-field-definition.js +28 -0
- package/dist/config/framework-resources-config.d.ts +116 -0
- package/dist/config/framework-resources-config.js +1 -0
- package/dist/config/pipeline-config.d.ts +56 -20
- package/dist/config/pipeline-tree.resolver.d.ts +79 -0
- package/dist/config/pipeline-tree.resolver.js +220 -0
- package/dist/config/stage-type.eraser.d.ts +65 -0
- package/dist/config/stage-type.eraser.js +1 -0
- package/dist/contracts/capability.d.ts +11 -11
- package/dist/contracts/client-contract-structure.validator.d.ts +344 -29
- package/dist/contracts/client-contract-structure.validator.js +248 -7
- package/dist/contracts/contract-canonicalizer.d.ts +19 -3
- package/dist/contracts/contract-canonicalizer.js +172 -27
- package/dist/contracts/contract-hash.d.ts +12 -7
- package/dist/contracts/contract-hash.js +3 -2
- package/dist/contracts/contract-limits.d.ts +4 -1
- package/dist/contracts/contract-limits.js +1 -0
- package/dist/contracts/contract-lookup.d.ts +5 -5
- package/dist/contracts/contract-protocol.d.ts +4 -4
- package/dist/contracts/contract.d.ts +31 -16
- package/dist/contracts/create-requirements.d.ts +35 -0
- package/dist/contracts/create-requirements.js +1 -0
- package/dist/contracts/enum-definition.d.ts +1 -1
- package/dist/contracts/field-check.d.ts +101 -0
- package/dist/contracts/field-check.js +1 -0
- package/dist/contracts/field.d.ts +61 -41
- package/dist/contracts/identifier.d.ts +4 -4
- package/dist/contracts/json-shape.d.ts +76 -0
- package/dist/contracts/json-shape.js +1 -0
- package/dist/contracts/lifecycle-trait.d.ts +2 -2
- package/dist/contracts/reference-write-limit.d.ts +7 -0
- package/dist/contracts/reference-write-limit.js +1 -0
- package/dist/contracts/resource-operations.d.ts +28 -28
- package/dist/contracts/resource.d.ts +15 -9
- package/dist/contracts/scalar-value-type.d.ts +25 -14
- package/dist/contracts/scalar.d.ts +3 -3
- package/dist/contracts/transaction-capability.d.ts +1 -1
- package/dist/contracts/wire-scalar-format.d.ts +4 -4
- package/dist/framework/contract-view.d.ts +234 -63
- package/dist/framework/framework-construction.error.d.ts +10 -10
- package/dist/framework/framework-construction.error.js +2 -2
- package/dist/framework/framework.d.ts +50 -24
- package/dist/framework/framework.factory.d.ts +8 -6
- package/dist/framework/framework.factory.js +95 -32
- package/dist/framework/operation-facade.d.ts +123 -52
- package/dist/framework/operation-facade.js +9 -1
- package/dist/index.d.ts +55 -82
- package/dist/index.js +6 -26
- package/dist/internal.d.ts +40 -0
- package/dist/internal.js +18 -0
- package/dist/operations/operation-arguments.d.ts +316 -201
- package/dist/operations/operation-call.d.ts +27 -28
- package/dist/operations/operation-identity.d.ts +12 -10
- package/dist/operations/operation-identity.js +3 -0
- package/dist/operations/operation-result.d.ts +21 -21
- package/dist/operations/operation-validator-core.d.ts +6 -6
- package/dist/operations/operation-validator-core.js +41 -12
- package/dist/operations/operation-validator.d.ts +24 -9
- package/dist/operations/operation-validator.js +26 -10
- package/dist/operations/projection-scope.resolver.d.ts +7 -7
- package/dist/operations/structural-limits.walker.d.ts +19 -0
- package/dist/operations/structural-limits.walker.js +489 -0
- package/dist/operations/validation-code.d.ts +11 -6
- package/dist/operations/validation-code.js +4 -0
- package/dist/operations/write-scope.resolver.d.ts +6 -6
- package/dist/protocol/absent-route.responder.d.ts +13 -11
- package/dist/protocol/absent-route.responder.js +42 -16
- package/dist/protocol/contract-document.responder.d.ts +3 -3
- package/dist/protocol/contract-document.responder.js +2 -2
- package/dist/protocol/http-request.decoder.d.ts +23 -13
- package/dist/protocol/http-request.decoder.js +19 -11
- package/dist/protocol/http-request.reader.d.ts +3 -3
- package/dist/protocol/http-response.encoder.d.ts +4 -4
- package/dist/protocol/http-response.encoder.js +94 -55
- package/dist/protocol/http-status.table.d.ts +2 -2
- package/dist/protocol/operation-response.guard.d.ts +2 -2
- package/dist/protocol/protocol-surface.d.ts +4 -4
- package/dist/protocol/protocol.binder.d.ts +52 -27
- package/dist/protocol/protocol.binder.js +14 -9
- package/dist/protocol/protocol.handler.d.ts +28 -15
- package/dist/protocol/protocol.handler.js +55 -10
- package/dist/protocol/unmounted-route.error.d.ts +19 -0
- package/dist/protocol/unmounted-route.error.js +10 -0
- package/dist/runtime/caller-data.copier.d.ts +59 -0
- package/dist/runtime/caller-data.copier.js +470 -0
- package/dist/runtime/caller-data.door.d.ts +56 -0
- package/dist/runtime/caller-data.door.js +67 -0
- package/dist/runtime/computed-read-runtime.d.ts +7 -6
- package/dist/runtime/computed-read-runtime.js +61 -55
- package/dist/runtime/computed-value.error.d.ts +13 -0
- package/dist/runtime/computed-value.error.js +9 -0
- package/dist/runtime/context-executor.runtime.d.ts +59 -0
- package/dist/runtime/context-executor.runtime.js +275 -0
- package/dist/runtime/create-requirement.d.ts +22 -57
- package/dist/runtime/create-requirement.js +140 -37
- package/dist/runtime/decimal.d.ts +2 -2
- package/dist/runtime/decimal.js +1 -1
- package/dist/runtime/diagnostics-reporter.d.ts +64 -22
- package/dist/runtime/diagnostics-reporter.js +35 -4
- package/dist/runtime/error-boundary.d.ts +73 -8
- package/dist/runtime/error-boundary.js +104 -48
- package/dist/runtime/execution-options.d.ts +10 -2
- package/dist/runtime/field-check.evaluator.d.ts +29 -0
- package/dist/runtime/field-check.evaluator.js +521 -0
- package/dist/runtime/field-compute.d.ts +64 -0
- package/dist/runtime/field-compute.js +1 -0
- package/dist/runtime/field-stage.plan.d.ts +15 -0
- package/dist/runtime/field-stage.plan.js +27 -0
- package/dist/runtime/field-stage.runtime.d.ts +35 -0
- package/dist/runtime/field-stage.runtime.js +143 -0
- package/dist/runtime/field-validator.runtime.d.ts +11 -0
- package/dist/runtime/field-validator.runtime.js +87 -0
- package/dist/runtime/framework-error-class.table.d.ts +33 -0
- package/dist/runtime/framework-error-class.table.js +25 -0
- package/dist/runtime/framework-error.d.ts +79 -7
- package/dist/runtime/framework-error.factory.d.ts +4 -0
- package/dist/runtime/framework-error.factory.js +15 -0
- package/dist/runtime/framework-error.js +23 -2
- package/dist/runtime/interceptor-next.error.d.ts +5 -0
- package/dist/runtime/interceptor-next.error.js +6 -0
- package/dist/runtime/json-value.d.ts +3 -3
- package/dist/runtime/level-lifecycle.runtime.d.ts +25 -0
- package/dist/runtime/level-lifecycle.runtime.js +42 -0
- package/dist/runtime/misuse-reporter.d.ts +32 -0
- package/dist/runtime/misuse-reporter.js +19 -0
- package/dist/runtime/mutation-planner.d.ts +19 -10
- package/dist/runtime/mutation-planner.js +62 -36
- package/dist/runtime/nested-write.walker.d.ts +32 -0
- package/dist/runtime/nested-write.walker.js +73 -0
- package/dist/runtime/operation-request.d.ts +35 -15
- package/dist/runtime/operation-response.d.ts +17 -17
- package/dist/runtime/operation-runtime.d.ts +125 -30
- package/dist/runtime/operation-runtime.js +423 -83
- package/dist/runtime/outcome-mapper.d.ts +16 -5
- package/dist/runtime/outcome-mapper.js +35 -8
- package/dist/runtime/output-validator.d.ts +16 -6
- package/dist/runtime/output-validator.js +12 -1
- package/dist/runtime/owned-execution.registry.d.ts +13 -0
- package/dist/runtime/owned-execution.registry.js +7 -0
- package/dist/runtime/pipe-output.validator.d.ts +33 -18
- package/dist/runtime/pipe-output.validator.js +12 -12
- package/dist/runtime/pipeline.d.ts +202 -28
- package/dist/runtime/readonly-value.d.ts +32 -0
- package/dist/runtime/readonly-value.js +141 -0
- package/dist/runtime/referential-action.d.ts +7 -0
- package/dist/runtime/request-envelope.validator.d.ts +5 -0
- package/dist/runtime/request-envelope.validator.js +123 -0
- package/dist/runtime/request-id.d.ts +1 -1
- package/dist/runtime/request-state.d.ts +14 -0
- package/dist/runtime/request-state.js +1 -0
- package/dist/runtime/request-state.resolver.d.ts +12 -0
- package/dist/runtime/request-state.resolver.js +20 -0
- package/dist/runtime/scalar-runtime.d.ts +56 -13
- package/dist/runtime/scalar-runtime.js +167 -86
- package/dist/transactions/deferred-operation.d.ts +35 -20
- package/dist/transactions/operation-arguments-encoder.d.ts +3 -3
- package/dist/transactions/operation-arguments-encoder.js +2 -2
- package/dist/transactions/sql-statement.d.ts +77 -0
- package/dist/transactions/sql-statement.js +47 -0
- package/dist/transactions/sql-statement.validator.d.ts +44 -0
- package/dist/transactions/sql-statement.validator.js +134 -0
- package/dist/transactions/transaction-envelope.d.ts +4 -4
- package/dist/transactions/transaction-integrity-error.d.ts +6 -6
- package/dist/transactions/transaction-integrity-error.js +5 -2
- package/dist/transactions/transaction-plan-assembler.d.ts +23 -9
- package/dist/transactions/transaction-plan-assembler.js +195 -82
- package/dist/transactions/transaction-plan-validator.d.ts +53 -21
- package/dist/transactions/transaction-plan-validator.js +246 -163
- package/dist/transactions/transaction-reference-collector.d.ts +30 -0
- package/dist/transactions/transaction-reference-collector.js +204 -0
- package/dist/transactions/transaction-reference-resolver.d.ts +19 -2
- package/dist/transactions/transaction-reference-resolver.js +27 -10
- package/dist/transactions/transaction-reference-validator.d.ts +34 -4
- package/dist/transactions/transaction-reference-validator.js +82 -43
- package/dist/transactions/transaction-reference.d.ts +30 -58
- package/dist/transactions/transaction-request.d.ts +20 -7
- package/dist/transactions/transaction-response.d.ts +12 -7
- package/dist/transactions/transaction-response.js +24 -1
- package/dist/transactions/transaction-runtime.d.ts +11 -8
- package/dist/transactions/transaction-runtime.js +167 -50
- package/dist/transactions/transaction-settlement.runtime.d.ts +51 -0
- package/dist/transactions/transaction-settlement.runtime.js +120 -0
- package/dist/transactions/transaction-slot-path-error.d.ts +4 -4
- package/dist/transactions/transaction-slot-path-error.js +2 -2
- package/dist/transactions/transaction-slot-writer.js +2 -2
- package/dist/transactions/transaction-stage.runtime.d.ts +81 -0
- package/dist/transactions/transaction-stage.runtime.js +123 -0
- package/package.json +18 -3
- package/src/runtime/field-check.evaluator.ts +720 -0
- package/dist/config/define-fields.d.ts +0 -35
- package/dist/config/define-fields.js +0 -3
- package/dist/config/framework-behaviors-config.d.ts +0 -30
- package/dist/config/framework-fields-config.d.ts +0 -36
- package/dist/config/framework-restrictions-config.d.ts +0 -142
- package/dist/operations/operation-boolean-nodes.d.ts +0 -11
- package/dist/operations/operation-boolean-nodes.js +0 -283
- package/dist/operations/operation-nesting.d.ts +0 -8
- package/dist/operations/operation-nesting.js +0 -307
- package/dist/runtime/field-behavior.d.ts +0 -48
- /package/dist/{config/framework-behaviors-config.js → adapters/adapter-sql-statement.js} +0 -0
- /package/dist/{config/framework-fields-config.js → adapters/adapter-transaction-executor.interface.js} +0 -0
- /package/dist/config/{framework-restrictions-config.js → exact-framework-config.js} +0 -0
- /package/dist/{runtime/field-behavior.js → config/field-pipeline-config.js} +0 -0
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { validationIssue } from "../operations/validation-code.js";
|
|
1
|
+
import { VALIDATION_CODE_MESSAGES, validationIssue, } from "../operations/validation-code.js";
|
|
2
|
+
import { copyAtDoor, refuseCallerData } from "../runtime/caller-data.door.js";
|
|
2
3
|
import { operationFailure } from "../runtime/operation-response.js";
|
|
3
4
|
import { mapValidationOutcome } from "../runtime/outcome-mapper.js";
|
|
4
5
|
import { encodeOperationArgumentsForWire } from "./operation-arguments-encoder.js";
|
|
5
6
|
import { computeOperationFingerprint } from "./operation-fingerprint.js";
|
|
7
|
+
import { readSqlTemplate } from "./sql-statement.js";
|
|
6
8
|
import { transactionOperationFailure } from "./transaction-response.js";
|
|
9
|
+
const SQL_STEP_NODE = Object.freeze({ fingerprint: null });
|
|
7
10
|
function isPlainRecord(value) {
|
|
8
11
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
9
12
|
return false;
|
|
@@ -11,64 +14,111 @@ function isPlainRecord(value) {
|
|
|
11
14
|
const prototype = Object.getPrototypeOf(value);
|
|
12
15
|
return prototype === Object.prototype || prototype === null;
|
|
13
16
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return ["create", "update"];
|
|
21
|
-
default:
|
|
22
|
-
return [];
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
function referenceContainers(identity, args) {
|
|
26
|
-
if (!isPlainRecord(args)) {
|
|
27
|
-
return [];
|
|
28
|
-
}
|
|
29
|
-
return referenceKeys(identity).flatMap((key) => {
|
|
30
|
-
const value = args[key];
|
|
31
|
-
if (Array.isArray(value)) {
|
|
32
|
-
return value.flatMap((entry, index) => isPlainRecord(entry) ? [{ path: [key, index], record: entry }] : []);
|
|
17
|
+
const KEEP = Symbol("keep");
|
|
18
|
+
function rebuildArguments(root, leaf) {
|
|
19
|
+
const pathOf = (parent, key) => () => {
|
|
20
|
+
const segments = [];
|
|
21
|
+
if (key !== undefined) {
|
|
22
|
+
segments.push(key);
|
|
33
23
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
24
|
+
for (let frame = parent; frame?.key !== undefined; frame = frame.parent) {
|
|
25
|
+
segments.push(frame.key);
|
|
26
|
+
}
|
|
27
|
+
return segments.reverse();
|
|
28
|
+
};
|
|
29
|
+
const ancestors = new Set();
|
|
30
|
+
const finish = (frame) => {
|
|
31
|
+
ancestors.delete(frame.source);
|
|
32
|
+
if (!Array.isArray(frame.source)) {
|
|
33
|
+
return Object.fromEntries(frame.built);
|
|
34
|
+
}
|
|
35
|
+
const rebuilt = new Array(frame.source.length);
|
|
36
|
+
for (const [index, value] of frame.built) {
|
|
37
|
+
rebuilt[index] = value;
|
|
38
|
+
}
|
|
39
|
+
return rebuilt;
|
|
40
|
+
};
|
|
41
|
+
const enter = (value, parent, key) => {
|
|
42
|
+
const replaced = leaf(value, pathOf(parent, key));
|
|
43
|
+
if (replaced !== KEEP) {
|
|
44
|
+
return { value: replaced };
|
|
45
|
+
}
|
|
46
|
+
if (!Array.isArray(value) && !isPlainRecord(value)) {
|
|
47
|
+
return { value };
|
|
48
|
+
}
|
|
49
|
+
if (ancestors.has(value)) {
|
|
50
|
+
return { value };
|
|
51
|
+
}
|
|
52
|
+
ancestors.add(value);
|
|
53
|
+
const keys = Array.isArray(value)
|
|
54
|
+
? Object.keys(value).map(Number)
|
|
55
|
+
: Object.keys(value);
|
|
56
|
+
return { source: value, keys, built: [], parent, key, next: 0 };
|
|
57
|
+
};
|
|
58
|
+
const first = enter(root, undefined, undefined);
|
|
59
|
+
if (!("source" in first)) {
|
|
60
|
+
return first.value;
|
|
40
61
|
}
|
|
41
|
-
|
|
42
|
-
for (
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
62
|
+
let frame = first;
|
|
63
|
+
for (;;) {
|
|
64
|
+
if (frame.next < frame.keys.length) {
|
|
65
|
+
const key = frame.keys[frame.next];
|
|
66
|
+
frame.next += 1;
|
|
67
|
+
const entry = frame.source[key];
|
|
68
|
+
const child = enter(entry, frame, key);
|
|
69
|
+
if ("source" in child) {
|
|
70
|
+
frame = child;
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
frame.built.push([key, child.value]);
|
|
74
|
+
}
|
|
75
|
+
continue;
|
|
48
76
|
}
|
|
49
|
-
|
|
50
|
-
|
|
77
|
+
const rebuilt = finish(frame);
|
|
78
|
+
const parent = frame.parent;
|
|
79
|
+
if (parent === undefined) {
|
|
80
|
+
return rebuilt;
|
|
51
81
|
}
|
|
82
|
+
parent.built.push([frame.key, rebuilt]);
|
|
83
|
+
frame = parent;
|
|
52
84
|
}
|
|
53
|
-
return result;
|
|
54
85
|
}
|
|
55
86
|
function operationEntryFailure(operation, message) {
|
|
56
87
|
return transactionOperationFailure(operationFailure("A2004", {
|
|
57
88
|
message: "Transaction plan failed framework validation.",
|
|
58
|
-
issues: [validationIssue("V1001", [
|
|
89
|
+
issues: [validationIssue("V1001", [], message)],
|
|
59
90
|
}), operation);
|
|
60
91
|
}
|
|
61
92
|
function referenceFailure(issue, operation) {
|
|
62
93
|
return transactionOperationFailure(mapValidationOutcome([issue]), operation);
|
|
63
94
|
}
|
|
64
|
-
export function createTransactionPlanAssembler(contracts, protocol) {
|
|
95
|
+
export function createTransactionPlanAssembler(contracts, protocol, misuse) {
|
|
65
96
|
const handles = new WeakMap();
|
|
66
97
|
const placeholders = new WeakMap();
|
|
67
98
|
const originOf = (origin) => origin === "application"
|
|
68
|
-
? {
|
|
69
|
-
: {
|
|
70
|
-
const snapshot = (
|
|
71
|
-
|
|
99
|
+
? { origin: "application" }
|
|
100
|
+
: { origin: "client", protocol };
|
|
101
|
+
const snapshot = (args) => {
|
|
102
|
+
const copy = copyAtDoor(args, {
|
|
103
|
+
keep: (value) => placeholders.has(value),
|
|
104
|
+
});
|
|
105
|
+
return copy.ok ? { args: copy.value } : { args: {}, refused: copy.error };
|
|
106
|
+
};
|
|
107
|
+
const placeholderSites = (args) => {
|
|
108
|
+
const sites = [];
|
|
109
|
+
rebuildArguments(args, (value, pathOf) => {
|
|
110
|
+
const placeholder = typeof value === "object" && value !== null
|
|
111
|
+
? placeholders.get(value)
|
|
112
|
+
: undefined;
|
|
113
|
+
if (placeholder === undefined) {
|
|
114
|
+
return KEEP;
|
|
115
|
+
}
|
|
116
|
+
sites.push({ path: pathOf(), object: value, placeholder });
|
|
117
|
+
return value;
|
|
118
|
+
});
|
|
119
|
+
return sites;
|
|
120
|
+
};
|
|
121
|
+
const createHandle = (record) => {
|
|
72
122
|
const handle = Object.freeze({
|
|
73
123
|
$ref: (field) => {
|
|
74
124
|
const placeholder = Object.freeze({
|
|
@@ -78,15 +128,60 @@ export function createTransactionPlanAssembler(contracts, protocol) {
|
|
|
78
128
|
return placeholder;
|
|
79
129
|
},
|
|
80
130
|
});
|
|
81
|
-
handles.set(handle,
|
|
82
|
-
origin,
|
|
83
|
-
resource,
|
|
84
|
-
identity,
|
|
85
|
-
args: snapshot(identity, args),
|
|
86
|
-
});
|
|
131
|
+
handles.set(handle, record);
|
|
87
132
|
return handle;
|
|
88
133
|
};
|
|
89
|
-
const
|
|
134
|
+
const defer = (origin, resource, identity, args) => createHandle({
|
|
135
|
+
kind: "operation",
|
|
136
|
+
origin,
|
|
137
|
+
resource,
|
|
138
|
+
identity,
|
|
139
|
+
...snapshot(args),
|
|
140
|
+
});
|
|
141
|
+
const deferSql = (strings, values) => {
|
|
142
|
+
const copy = snapshot(values);
|
|
143
|
+
return createHandle({
|
|
144
|
+
kind: "sql",
|
|
145
|
+
strings: readSqlTemplate(strings, values.length),
|
|
146
|
+
values: Array.isArray(copy.args) ? copy.args : [],
|
|
147
|
+
...(copy.refused === undefined ? {} : { refused: copy.refused }),
|
|
148
|
+
});
|
|
149
|
+
};
|
|
150
|
+
const recordPlaceholderSites = (record) => placeholderSites(record.kind === "sql" ? record.values : record.args);
|
|
151
|
+
const planSqlStatement = (record, positions) => {
|
|
152
|
+
const values = record.values.map((value) => {
|
|
153
|
+
const sites = placeholderSites(value);
|
|
154
|
+
const [site] = sites;
|
|
155
|
+
if (site === undefined) {
|
|
156
|
+
return { kind: "value", value };
|
|
157
|
+
}
|
|
158
|
+
if (site.path.length > 0) {
|
|
159
|
+
return { kind: "misplaced-reference", path: site.path };
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
kind: "reference",
|
|
163
|
+
operation: positions.get(site.placeholder.source),
|
|
164
|
+
field: site.placeholder.field,
|
|
165
|
+
};
|
|
166
|
+
});
|
|
167
|
+
return {
|
|
168
|
+
strings: record.strings,
|
|
169
|
+
values,
|
|
170
|
+
...(record.refused === undefined ? {} : { refused: record.refused }),
|
|
171
|
+
};
|
|
172
|
+
};
|
|
173
|
+
const assemble = async (input) => {
|
|
174
|
+
const list = copyAtDoor(input, { keep: (value) => value !== input });
|
|
175
|
+
if (!list.ok) {
|
|
176
|
+
return {
|
|
177
|
+
ok: false,
|
|
178
|
+
response: operationFailure("A2004", {
|
|
179
|
+
message: "Transaction plan failed framework validation.",
|
|
180
|
+
issues: [refuseCallerData(list.error, ["operations"], {}, misuse)],
|
|
181
|
+
}),
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
const operations = list.value;
|
|
90
185
|
if (!Array.isArray(operations)) {
|
|
91
186
|
return {
|
|
92
187
|
ok: false,
|
|
@@ -119,18 +214,36 @@ export function createTransactionPlanAssembler(contracts, protocol) {
|
|
|
119
214
|
positions.set(entry, index);
|
|
120
215
|
records.push(record);
|
|
121
216
|
}
|
|
217
|
+
const originOfRecord = (record) => record.kind === "sql" ? "application" : record.origin;
|
|
218
|
+
const [first] = records;
|
|
219
|
+
if (first !== undefined) {
|
|
220
|
+
const planOrigin = originOfRecord(first);
|
|
221
|
+
const other = records.findIndex((record) => originOfRecord(record) !== planOrigin);
|
|
222
|
+
if (other !== -1) {
|
|
223
|
+
return {
|
|
224
|
+
ok: false,
|
|
225
|
+
response: transactionOperationFailure(operationFailure("A2004", {
|
|
226
|
+
message: "Transaction plan failed framework validation.",
|
|
227
|
+
issues: [
|
|
228
|
+
validationIssue("V1020", [], VALIDATION_CODE_MESSAGES.V1020),
|
|
229
|
+
],
|
|
230
|
+
}), other),
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
}
|
|
122
234
|
for (const [index, record] of records.entries()) {
|
|
123
|
-
for (const { path,
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
:
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
235
|
+
for (const { path, placeholder } of recordPlaceholderSites(record)) {
|
|
236
|
+
if (!positions.has(placeholder.source)) {
|
|
237
|
+
return {
|
|
238
|
+
ok: false,
|
|
239
|
+
response: referenceFailure(validationIssue("V1010", [
|
|
240
|
+
"operations",
|
|
241
|
+
index,
|
|
242
|
+
record.kind === "sql" ? "values" : "args",
|
|
243
|
+
...path,
|
|
244
|
+
"$ref",
|
|
245
|
+
], "Transaction reference names an operation that is not in this transaction."), index),
|
|
246
|
+
};
|
|
134
247
|
}
|
|
135
248
|
}
|
|
136
249
|
}
|
|
@@ -145,26 +258,20 @@ export function createTransactionPlanAssembler(contracts, protocol) {
|
|
|
145
258
|
};
|
|
146
259
|
const materialize = async (index) => {
|
|
147
260
|
const record = records[index];
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
};
|
|
163
|
-
}));
|
|
164
|
-
}
|
|
165
|
-
return bound;
|
|
166
|
-
});
|
|
167
|
-
await Promise.all(references);
|
|
261
|
+
if (record.kind === "sql") {
|
|
262
|
+
return SQL_STEP_NODE;
|
|
263
|
+
}
|
|
264
|
+
const bound = new Map();
|
|
265
|
+
await Promise.all(placeholderSites(record.args).map(async ({ object, placeholder }) => {
|
|
266
|
+
const operation = positions.get(placeholder.source);
|
|
267
|
+
const { fingerprint } = await nodeAt(operation);
|
|
268
|
+
bound.set(object, {
|
|
269
|
+
$ref: { operation, fingerprint, path: [placeholder.field] },
|
|
270
|
+
});
|
|
271
|
+
}));
|
|
272
|
+
const args = rebuildArguments(record.args, (value) => typeof value === "object" && value !== null && bound.has(value)
|
|
273
|
+
? bound.get(value)
|
|
274
|
+
: KEEP);
|
|
168
275
|
return {
|
|
169
276
|
resource: record.resource,
|
|
170
277
|
family: record.identity.family,
|
|
@@ -194,8 +301,14 @@ export function createTransactionPlanAssembler(contracts, protocol) {
|
|
|
194
301
|
plan: {
|
|
195
302
|
operations: await Promise.all(records.map((_, index) => nodeAt(index))),
|
|
196
303
|
},
|
|
197
|
-
origins: records.map((record) => originOf(record.origin)),
|
|
304
|
+
origins: records.map((record) => originOf(record.kind === "sql" ? "application" : record.origin)),
|
|
305
|
+
refused: new Map(records.flatMap((record, index) => record.kind === "sql" || record.refused === undefined
|
|
306
|
+
? []
|
|
307
|
+
: [[index, record.refused]])),
|
|
308
|
+
statements: new Map(records.flatMap((record, index) => record.kind === "sql"
|
|
309
|
+
? [[index, planSqlStatement(record, positions)]]
|
|
310
|
+
: [])),
|
|
198
311
|
};
|
|
199
312
|
};
|
|
200
|
-
return { defer, assemble };
|
|
313
|
+
return { defer, deferSql, assemble };
|
|
201
314
|
}
|
|
@@ -1,24 +1,51 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
1
|
+
import type { AvAdapterModel } from "../adapters/adapter-model.js";
|
|
2
|
+
import type { AvContract } from "../contracts/contract.js";
|
|
3
|
+
import type { AvScalarField } from "../contracts/field.js";
|
|
4
4
|
import type { SemanticOperationArguments } from "../operations/operation-validator.js";
|
|
5
|
+
import { AvCallerDataError } from "../runtime/caller-data.copier.js";
|
|
5
6
|
import { type ReadProjectionPlan } from "../runtime/computed-read-runtime.js";
|
|
6
7
|
import type { FrameworkOperationRequest } from "../runtime/operation-request.js";
|
|
7
|
-
import type {
|
|
8
|
+
import type { AvOperationFailureResponse } from "../runtime/operation-response.js";
|
|
8
9
|
import type { OperationPipelineDependencies } from "../runtime/operation-runtime.js";
|
|
9
10
|
import type { CascadeClosure } from "../runtime/referential-action.js";
|
|
10
11
|
import type { OperationFingerprint } from "./deferred-operation.js";
|
|
11
|
-
import type {
|
|
12
|
+
import type { PlannedSqlStatement, ValidatedSqlStatement } from "./sql-statement.js";
|
|
13
|
+
import type { AvTransactionReference } from "./transaction-reference.js";
|
|
14
|
+
import { type TransactionSlotShape } from "./transaction-reference.js";
|
|
15
|
+
import { type TransactionReferenceCandidateSlot } from "./transaction-reference-collector.js";
|
|
12
16
|
import type { FrameworkTransactionRequest, TransactionOperationOrigin } from "./transaction-request.js";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Where a plan's step arguments came from, so the validator knows whether to copy
|
|
19
|
+
* them at the door (see `ArgumentsSource`):
|
|
20
|
+
*
|
|
21
|
+
* - `"caller"` — `framework.executeTransaction`'s caller's own objects: every step's
|
|
22
|
+
* arguments are copied when the plan is handed in, before the validator's first
|
|
23
|
+
* await, so a step revoked or changed after the call is never read again;
|
|
24
|
+
* - `"owned"` — a plan the protocol decoder parsed, or the typed runner assembled
|
|
25
|
+
* from its builders' copies; `refused` names the steps whose arguments a builder
|
|
26
|
+
* could not copy, answered at their turn, and `statements` the steps that are
|
|
27
|
+
* `appTx.$sql` statements, which only the typed runner builds: they have no wire
|
|
28
|
+
* form, so no plan a caller or a remote client hands in can hold one.
|
|
29
|
+
*/
|
|
30
|
+
export type PlanArguments = {
|
|
31
|
+
readonly source: "caller";
|
|
32
|
+
} | {
|
|
33
|
+
readonly source: "owned";
|
|
34
|
+
readonly refused?: ReadonlyMap<number, AvCallerDataError>;
|
|
35
|
+
readonly statements?: ReadonlyMap<number, PlannedSqlStatement>;
|
|
17
36
|
};
|
|
37
|
+
export type { TransactionReferenceCandidateSlot } from "./transaction-reference-collector.js";
|
|
38
|
+
/** One validated Transaction Slot: where it is, what it holds, and its reference. */
|
|
18
39
|
export type TransactionReferenceSlot = {
|
|
19
40
|
readonly path: readonly (string | number)[];
|
|
20
|
-
|
|
21
|
-
readonly
|
|
41
|
+
/** The destination field. */
|
|
42
|
+
readonly field: AvScalarField<AvContract>;
|
|
43
|
+
readonly shape: TransactionSlotShape;
|
|
44
|
+
/** The slot is a scalar value of mutation data: what it resolves to is written. */
|
|
45
|
+
readonly written: boolean;
|
|
46
|
+
/** The source field, under its own step's Contract: what the slot receives. */
|
|
47
|
+
readonly source: AvScalarField<AvContract>;
|
|
48
|
+
readonly reference: AvTransactionReference;
|
|
22
49
|
};
|
|
23
50
|
export type CandidateTransactionOperation = {
|
|
24
51
|
readonly index: number;
|
|
@@ -29,45 +56,50 @@ export type CandidateTransactionOperation = {
|
|
|
29
56
|
readonly candidates: readonly TransactionReferenceCandidateSlot[];
|
|
30
57
|
};
|
|
31
58
|
export type ValidatedTransactionOperation = {
|
|
59
|
+
readonly kind: "operation";
|
|
32
60
|
readonly index: number;
|
|
33
61
|
readonly request: FrameworkOperationRequest;
|
|
34
62
|
/**
|
|
35
|
-
* The Contract of this operation's
|
|
36
|
-
* against, the one it runs under, and the one a later `$ref` reads its
|
|
37
|
-
* field from.
|
|
63
|
+
* The Contract of this operation's origin, which is the plan's: the one it was
|
|
64
|
+
* validated against, the one it runs under, and the one a later `$ref` reads its
|
|
65
|
+
* source field from.
|
|
38
66
|
*/
|
|
39
|
-
readonly contract:
|
|
67
|
+
readonly contract: AvContract;
|
|
40
68
|
readonly arguments: SemanticOperationArguments;
|
|
41
69
|
readonly projection: ReadProjectionPlan | undefined;
|
|
42
70
|
readonly fingerprint: OperationFingerprint;
|
|
43
71
|
readonly references: readonly TransactionReferenceSlot[];
|
|
44
72
|
};
|
|
73
|
+
/** One validated plan step: a standard operation, or an `appTx.$sql` statement. */
|
|
74
|
+
export type ValidatedTransactionStep = ValidatedTransactionOperation | ValidatedSqlStatement;
|
|
45
75
|
export type ValidatedTransactionPlan = {
|
|
46
|
-
readonly operations: readonly
|
|
76
|
+
readonly operations: readonly ValidatedTransactionStep[];
|
|
47
77
|
};
|
|
48
78
|
/**
|
|
49
79
|
* What validating a plan needs beyond one operation's pipeline: the cascade
|
|
50
80
|
* closure over the Adapter's referential actions, resolved once when the
|
|
51
|
-
* Framework is constructed. The
|
|
81
|
+
* Framework is constructed. The record-write facts are not among them: they
|
|
52
82
|
* are checked when each operation runs, after its pipes.
|
|
53
83
|
*/
|
|
54
|
-
export type TransactionPlanDependencies<M extends
|
|
84
|
+
export type TransactionPlanDependencies<M extends AvAdapterModel> = Omit<OperationPipelineDependencies<M>, "recordWrites" | "contexts" | "fieldStages"> & {
|
|
55
85
|
readonly cascades: CascadeClosure;
|
|
86
|
+
/** Whether the Adapter declares `sqlStatements`: read once, at construction. */
|
|
87
|
+
readonly sqlStatements: boolean;
|
|
56
88
|
};
|
|
57
89
|
export type TransactionPlanValidationResult = {
|
|
58
90
|
readonly ok: true;
|
|
59
91
|
readonly plan: ValidatedTransactionPlan;
|
|
60
92
|
} | {
|
|
61
93
|
readonly ok: false;
|
|
62
|
-
readonly response:
|
|
94
|
+
readonly response: AvOperationFailureResponse;
|
|
63
95
|
};
|
|
64
96
|
/**
|
|
65
97
|
* The refusal of a plan on a Contract without transaction plans (`A2002`, one `V1006`
|
|
66
98
|
* at `["operations"]`). The one spelling — the protocol's absence answer for
|
|
67
99
|
* `/_transactions` is this envelope too.
|
|
68
100
|
*/
|
|
69
|
-
export declare function transactionsUnavailableFailure():
|
|
101
|
+
export declare function transactionsUnavailableFailure(): AvOperationFailureResponse;
|
|
70
102
|
/**
|
|
71
103
|
* Whole-plan Framework Validation Layer for transaction structure and identity.
|
|
72
104
|
*/
|
|
73
|
-
export declare function validateTransactionPlan<M extends
|
|
105
|
+
export declare function validateTransactionPlan<M extends AvAdapterModel>(dependencies: TransactionPlanDependencies<M>, request: FrameworkTransactionRequest, origins?: readonly TransactionOperationOrigin[], planArguments?: PlanArguments): Promise<TransactionPlanValidationResult>;
|