@aventara/core 0.1.0-pilot.3 → 1.0.0-rc.0
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 +338 -0
- package/README.md +100 -3
- package/dist/adapters/adapter-discovery-diagnostic.d.ts +2 -0
- package/dist/adapters/adapter-field.d.ts +3 -26
- package/dist/adapters/adapter-identifier.d.ts +1 -11
- package/dist/adapters/adapter-model.d.ts +12 -0
- package/dist/adapters/adapter-operation-executor.interface.d.ts +5 -1
- package/dist/adapters/adapter-resource.d.ts +7 -28
- package/dist/adapters/adapter.interface.d.ts +25 -26
- package/dist/compiler/contract-compiler-diagnostic.d.ts +8 -0
- package/dist/compiler/contract.compiler.d.ts +11 -22
- package/dist/compiler/contract.compiler.js +67 -0
- package/dist/config/any-framework-config.d.ts +5 -26
- package/dist/config/config-diagnostic.d.ts +2 -0
- package/dist/config/config-layer.d.ts +6 -19
- package/dist/config/config.resolver.d.ts +9 -14
- package/dist/config/config.resolver.js +1 -0
- package/dist/config/config.validator.d.ts +6 -3
- package/dist/config/config.validator.js +6 -0
- package/dist/config/define-fields.d.ts +15 -48
- package/dist/config/effective-fields.d.ts +6 -29
- package/dist/config/entrypoint.normalizer.d.ts +6 -18
- package/dist/config/framework-behaviors-config.d.ts +11 -10
- package/dist/config/framework-config.d.ts +19 -16
- package/dist/config/framework-fields-config.d.ts +20 -7
- package/dist/config/framework-restrictions-config.d.ts +41 -61
- package/dist/config/pipeline-config.d.ts +7 -17
- package/dist/contracts/capability.d.ts +13 -49
- package/dist/contracts/client-contract-structure.validator.d.ts +28 -54
- package/dist/contracts/client-contract-structure.validator.js +99 -2
- package/dist/contracts/contract-canonicalizer.d.ts +4 -6
- package/dist/contracts/contract-canonicalizer.js +32 -0
- package/dist/contracts/contract-hash.d.ts +3 -2
- package/dist/contracts/contract-limits.d.ts +7 -1
- package/dist/contracts/contract-protocol.d.ts +7 -8
- package/dist/contracts/contract.d.ts +20 -4
- package/dist/contracts/enum-definition.d.ts +2 -0
- package/dist/contracts/field.d.ts +40 -167
- package/dist/contracts/identifier.d.ts +1 -16
- package/dist/contracts/json-shape.d.ts +65 -0
- package/dist/contracts/json-shape.js +1 -0
- package/dist/contracts/lifecycle-trait.d.ts +4 -3
- 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 +2 -62
- package/dist/contracts/resource.d.ts +2 -0
- package/dist/contracts/scalar-value-type.d.ts +28 -48
- package/dist/contracts/scalar.d.ts +4 -3
- package/dist/contracts/transaction-capability.d.ts +2 -0
- package/dist/contracts/wire-scalar-format.d.ts +6 -21
- package/dist/framework/contract-view.d.ts +152 -130
- package/dist/framework/framework-construction.error.d.ts +6 -1
- package/dist/framework/framework.d.ts +33 -46
- package/dist/framework/framework.factory.d.ts +3 -17
- package/dist/framework/framework.factory.js +56 -13
- package/dist/framework/operation-facade.d.ts +3 -7
- package/dist/index.d.ts +8 -40
- package/dist/index.js +0 -20
- package/dist/internal.d.ts +35 -0
- package/dist/internal.js +16 -0
- package/dist/json/avz.d.ts +96 -0
- package/dist/json/avz.js +212 -0
- package/dist/json/index.d.ts +6 -0
- package/dist/json/index.js +1 -0
- package/dist/json/json-shape.registry.d.ts +22 -0
- package/dist/json/json-shape.registry.js +16 -0
- package/dist/json/zod-issue.translator.d.ts +51 -0
- package/dist/json/zod-issue.translator.js +142 -0
- package/dist/operations/operation-arguments.d.ts +198 -303
- package/dist/operations/operation-call.d.ts +13 -15
- package/dist/operations/operation-identity.d.ts +6 -2
- package/dist/operations/operation-identity.js +3 -0
- package/dist/operations/operation-result.d.ts +15 -61
- package/dist/operations/operation-validator-core.d.ts +6 -5
- package/dist/operations/operation-validator-core.js +28 -10
- package/dist/operations/operation-validator.d.ts +22 -9
- package/dist/operations/operation-validator.js +26 -10
- package/dist/operations/projection-scope.resolver.d.ts +1 -11
- package/dist/operations/structural-limits.walker.d.ts +19 -0
- package/dist/operations/structural-limits.walker.js +344 -0
- package/dist/operations/validation-code.d.ts +5 -17
- package/dist/operations/write-scope.resolver.d.ts +3 -28
- package/dist/protocol/absent-route.responder.d.ts +25 -39
- package/dist/protocol/absent-route.responder.js +32 -6
- package/dist/protocol/av-protocol.d.ts +2 -8
- package/dist/protocol/contract-document.responder.d.ts +5 -18
- package/dist/protocol/http-request.decoder.d.ts +18 -59
- package/dist/protocol/http-request.decoder.js +11 -3
- package/dist/protocol/http-request.reader.d.ts +5 -5
- package/dist/protocol/http-response.encoder.d.ts +14 -20
- package/dist/protocol/http-status.table.d.ts +0 -8
- package/dist/protocol/index.d.ts +2 -7
- package/dist/protocol/operation-response.guard.d.ts +0 -15
- package/dist/protocol/protocol-failure.d.ts +8 -27
- package/dist/protocol/protocol-headers.d.ts +15 -42
- package/dist/protocol/protocol-surface.d.ts +0 -22
- package/dist/protocol/protocol.binder.d.ts +19 -27
- package/dist/protocol/protocol.binder.js +3 -1
- package/dist/protocol/protocol.handler.d.ts +19 -23
- package/dist/protocol/protocol.handler.js +14 -4
- 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 +65 -0
- package/dist/runtime/computed-read-runtime.js +3 -10
- package/dist/runtime/computed-value.error.d.ts +13 -0
- package/dist/runtime/computed-value.error.js +9 -0
- package/dist/runtime/create-requirement.d.ts +43 -7
- package/dist/runtime/create-requirement.js +89 -9
- package/dist/runtime/decimal.d.ts +5 -3
- package/dist/runtime/diagnostics-reporter.d.ts +33 -37
- package/dist/runtime/diagnostics-reporter.js +11 -4
- package/dist/runtime/error-boundary.d.ts +14 -10
- package/dist/runtime/error-boundary.js +65 -35
- package/dist/runtime/execution-options.d.ts +3 -7
- package/dist/runtime/field-behavior.d.ts +14 -21
- package/dist/runtime/framework-error.d.ts +14 -2
- package/dist/runtime/json-value.d.ts +7 -15
- package/dist/runtime/misuse-reporter.d.ts +32 -0
- package/dist/runtime/misuse-reporter.js +19 -0
- package/dist/runtime/mutation-planner.d.ts +6 -12
- package/dist/runtime/mutation-planner.js +13 -11
- package/dist/runtime/operation-request.d.ts +11 -11
- package/dist/runtime/operation-response.d.ts +18 -23
- package/dist/runtime/operation-runtime.d.ts +25 -33
- package/dist/runtime/operation-runtime.js +37 -18
- package/dist/runtime/outcome-mapper.js +12 -2
- package/dist/runtime/output-validator.d.ts +10 -0
- package/dist/runtime/output-validator.js +11 -0
- package/dist/runtime/owned-execution.registry.d.ts +13 -0
- package/dist/runtime/owned-execution.registry.js +7 -0
- package/dist/runtime/pipeline.d.ts +33 -36
- package/dist/runtime/referential-action.d.ts +8 -26
- package/dist/runtime/request-envelope.validator.d.ts +5 -0
- package/dist/runtime/request-envelope.validator.js +118 -0
- package/dist/runtime/request-id.d.ts +3 -10
- package/dist/runtime/scalar-runtime.d.ts +42 -14
- package/dist/runtime/scalar-runtime.js +162 -79
- package/dist/transactions/deferred-operation.d.ts +10 -21
- package/dist/transactions/operation-arguments-encoder.d.ts +1 -0
- package/dist/transactions/operation-fingerprint.d.ts +3 -1
- package/dist/transactions/transaction-envelope.d.ts +2 -4
- package/dist/transactions/transaction-integrity-error.d.ts +4 -15
- package/dist/transactions/transaction-plan-assembler.d.ts +6 -1
- package/dist/transactions/transaction-plan-assembler.js +74 -75
- package/dist/transactions/transaction-plan-validator.d.ts +33 -24
- package/dist/transactions/transaction-plan-validator.js +204 -153
- 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 +9 -12
- package/dist/transactions/transaction-reference-resolver.js +10 -5
- package/dist/transactions/transaction-reference-validator.js +24 -17
- package/dist/transactions/transaction-reference.d.ts +31 -64
- package/dist/transactions/transaction-request.d.ts +6 -8
- package/dist/transactions/transaction-response.d.ts +10 -7
- package/dist/transactions/transaction-response.js +24 -1
- package/dist/transactions/transaction-runtime.d.ts +7 -5
- package/dist/transactions/transaction-runtime.js +4 -3
- package/dist/transactions/transaction-slot-path-error.d.ts +5 -15
- package/dist/transactions/transaction-slot-writer.d.ts +3 -13
- package/package.json +17 -3
- 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
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { lookupField, lookupOwn, lookupResource, } from "../contracts/contract-lookup.js";
|
|
2
|
+
import { planOperationArgumentsPath } from "../runtime/error-boundary.js";
|
|
3
|
+
import { isPlainRecord, referenceOperandShape, } from "../runtime/scalar-runtime.js";
|
|
4
|
+
import { routeTransactionReferenceCandidate, } from "./transaction-reference.js";
|
|
5
|
+
function isObject(value) {
|
|
6
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
function at(position, ...segments) {
|
|
9
|
+
return { ...position, path: [...position.path, ...segments] };
|
|
10
|
+
}
|
|
11
|
+
function collectValue(field, shape, value, path, candidates, written = false) {
|
|
12
|
+
const route = routeTransactionReferenceCandidate(value);
|
|
13
|
+
if (route.kind === "ordinary") {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
candidates.push({
|
|
17
|
+
path,
|
|
18
|
+
field,
|
|
19
|
+
shape,
|
|
20
|
+
written,
|
|
21
|
+
candidate: route.candidate,
|
|
22
|
+
});
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
function collectKey(position, selector, candidates) {
|
|
26
|
+
if (!isObject(selector)) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const resource = lookupResource(position.contract, position.resource);
|
|
30
|
+
for (const [fieldName, value] of Object.entries(selector)) {
|
|
31
|
+
const field = lookupField(resource, fieldName);
|
|
32
|
+
if (field?.kind === "scalar") {
|
|
33
|
+
collectValue(field, "nonNullValue", value, [...position.path, fieldName], candidates);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function collectKeys(position, selectors, candidates) {
|
|
38
|
+
if (Array.isArray(selectors)) {
|
|
39
|
+
selectors.forEach((selector, index) => {
|
|
40
|
+
collectKey(at(position, index), selector, candidates);
|
|
41
|
+
});
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
collectKey(position, selectors, candidates);
|
|
45
|
+
}
|
|
46
|
+
function collectScalarFilter(field, filter, path, candidates) {
|
|
47
|
+
if (collectValue(field, "value", filter, path, candidates) ||
|
|
48
|
+
!isPlainRecord(filter)) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
for (const [operator, operand] of Object.entries(filter)) {
|
|
52
|
+
const operandPath = [...path, operator];
|
|
53
|
+
if (operator === "not") {
|
|
54
|
+
collectScalarFilter(field, operand, operandPath, candidates);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const shape = referenceOperandShape(operator);
|
|
58
|
+
if (shape !== undefined) {
|
|
59
|
+
collectValue(field, shape, operand, operandPath, candidates);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function collectWhere(position, where, candidates) {
|
|
64
|
+
if (!isObject(where)) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const resource = lookupResource(position.contract, position.resource);
|
|
68
|
+
for (const [key, value] of Object.entries(where)) {
|
|
69
|
+
if (key === "AND" || key === "OR") {
|
|
70
|
+
if (Array.isArray(value)) {
|
|
71
|
+
value.forEach((entry, index) => {
|
|
72
|
+
collectWhere(at(position, key, index), entry, candidates);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (key === "NOT") {
|
|
78
|
+
collectWhere(at(position, key), value, candidates);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const field = lookupField(resource, key);
|
|
82
|
+
if (field?.kind === "scalar") {
|
|
83
|
+
collectScalarFilter(field, value, [...position.path, key], candidates);
|
|
84
|
+
}
|
|
85
|
+
else if (field?.kind === "relation") {
|
|
86
|
+
const target = { ...at(position, key), resource: field.target };
|
|
87
|
+
if (field.cardinality === "one") {
|
|
88
|
+
collectWhere(target, value, candidates);
|
|
89
|
+
}
|
|
90
|
+
else if (isObject(value)) {
|
|
91
|
+
for (const operator of ["some", "every", "none"]) {
|
|
92
|
+
if (Object.hasOwn(value, operator)) {
|
|
93
|
+
collectWhere(at(target, operator), value[operator], candidates);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function eachEntry(position, operand, visit) {
|
|
101
|
+
if (Array.isArray(operand)) {
|
|
102
|
+
operand.forEach((entry, index) => {
|
|
103
|
+
visit(at(position, index), entry);
|
|
104
|
+
});
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
visit(position, operand);
|
|
108
|
+
}
|
|
109
|
+
function collectRelationDirectives(position, edge, value, candidates) {
|
|
110
|
+
if (!isObject(value)) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const target = { ...position, resource: edge.target };
|
|
114
|
+
for (const [directive, operand] of Object.entries(value)) {
|
|
115
|
+
const directivePosition = at(target, directive);
|
|
116
|
+
switch (directive) {
|
|
117
|
+
case "$connect":
|
|
118
|
+
case "$disconnect":
|
|
119
|
+
case "$set":
|
|
120
|
+
collectKeys(directivePosition, operand, candidates);
|
|
121
|
+
break;
|
|
122
|
+
case "$create":
|
|
123
|
+
eachEntry(directivePosition, operand, (entryPosition, entry) => {
|
|
124
|
+
collectData(entryPosition, entry, candidates);
|
|
125
|
+
});
|
|
126
|
+
break;
|
|
127
|
+
case "$connectOrCreate":
|
|
128
|
+
case "$update":
|
|
129
|
+
case "$delete":
|
|
130
|
+
case "$upsert":
|
|
131
|
+
eachEntry(directivePosition, operand, (entryPosition, entry) => {
|
|
132
|
+
if (!isObject(entry)) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const where = at(entryPosition, "where");
|
|
136
|
+
if (directive === "$update" || directive === "$delete") {
|
|
137
|
+
collectWhere(where, entry.where, candidates);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
collectKey(where, entry.where, candidates);
|
|
141
|
+
}
|
|
142
|
+
for (const branch of ["create", "update", "data"]) {
|
|
143
|
+
if (Object.hasOwn(entry, branch)) {
|
|
144
|
+
collectData(at(entryPosition, branch), entry[branch], candidates);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
function collectData(position, data, candidates) {
|
|
153
|
+
if (!isObject(data)) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const resource = lookupResource(position.contract, position.resource);
|
|
157
|
+
for (const [fieldName, value] of Object.entries(data)) {
|
|
158
|
+
const field = lookupField(resource, fieldName);
|
|
159
|
+
if (field?.kind === "scalar") {
|
|
160
|
+
collectValue(field, "value", value, [...position.path, fieldName], candidates, true);
|
|
161
|
+
}
|
|
162
|
+
else if (field?.kind === "relation") {
|
|
163
|
+
collectRelationDirectives(at(position, fieldName), field, value, candidates);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
export function collectTransactionReferenceCandidates(contract, request, index, args) {
|
|
168
|
+
const candidates = [];
|
|
169
|
+
const root = {
|
|
170
|
+
contract,
|
|
171
|
+
resource: request.resource,
|
|
172
|
+
path: planOperationArgumentsPath(index),
|
|
173
|
+
};
|
|
174
|
+
const where = lookupOwn(args, "where");
|
|
175
|
+
if (request.variant === "unique") {
|
|
176
|
+
collectKey(at(root, "where"), where, candidates);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
collectWhere(at(root, "where"), where, candidates);
|
|
180
|
+
}
|
|
181
|
+
collectKey(at(root, "cursor"), lookupOwn(args, "cursor"), candidates);
|
|
182
|
+
if (request.family === "create") {
|
|
183
|
+
const data = lookupOwn(args, "data");
|
|
184
|
+
if (request.variant === "many" || request.variant === "count") {
|
|
185
|
+
if (Array.isArray(data)) {
|
|
186
|
+
data.forEach((entry, dataIndex) => {
|
|
187
|
+
collectData(at(root, "data", dataIndex), entry, candidates);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
collectData(at(root, "data"), data, candidates);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
else if (request.family === "update") {
|
|
196
|
+
collectData(at(root, "data"), lookupOwn(args, "data"), candidates);
|
|
197
|
+
}
|
|
198
|
+
else if (request.family === "upsert") {
|
|
199
|
+
for (const stage of ["create", "update"]) {
|
|
200
|
+
collectData(at(root, stage), lookupOwn(args, stage), candidates);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return candidates;
|
|
204
|
+
}
|
|
@@ -10,17 +10,14 @@ export type ResolvedTransactionArguments = {
|
|
|
10
10
|
};
|
|
11
11
|
/**
|
|
12
12
|
* Substitutes every validated `$ref` placeholder of one operation from the results
|
|
13
|
-
* ledger: each earlier operation's final `data`, exactly the value at its index in
|
|
14
|
-
*
|
|
15
|
-
* projected path and type, and none of that is re-run here; only what can change
|
|
16
|
-
*
|
|
17
|
-
* referenced own key, resolves to no value at the full reference path. The result
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* Reading final data runs developer-produced accessors; a throw from here is the
|
|
24
|
-
* framework's own per-operation failure, classified by the caller.
|
|
13
|
+
* ledger: each earlier operation's final `data`, exactly the value at its index in the
|
|
14
|
+
* `A1009` results array. Validation already proved index, source fingerprint,
|
|
15
|
+
* projected path and type, and none of that is re-run here; only what can change at
|
|
16
|
+
* runtime is checked. A `null` or non-record source, or a source lacking the
|
|
17
|
+
* referenced own key, resolves to no value at the full reference path. The result is a
|
|
18
|
+
* fresh argument graph: only the ancestors of substituted slots are cloned, so the
|
|
19
|
+
* validated plan is never mutated, and every substituted value is a framework-owned
|
|
20
|
+
* copy of the source's value, so a dependent operation mutating its arguments cannot
|
|
21
|
+
* alter the source's committed result.
|
|
25
22
|
*/
|
|
26
23
|
export declare function resolveTransactionReferences(operation: ValidatedTransactionOperation, results: readonly unknown[]): ResolvedTransactionArguments;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { validationIssue } from "../operations/validation-code.js";
|
|
2
|
-
import { copyScalarFieldValue } from "../runtime/scalar-runtime.js";
|
|
2
|
+
import { copyScalarFieldValue, jsonShapeIssues, } from "../runtime/scalar-runtime.js";
|
|
3
3
|
import { replaceTransactionSlotValues } from "./transaction-slot-writer.js";
|
|
4
4
|
function isRecord(value) {
|
|
5
5
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6
6
|
}
|
|
7
7
|
export function resolveTransactionReferences(operation, results) {
|
|
8
8
|
const substitutions = [];
|
|
9
|
+
const shapeIssues = [];
|
|
9
10
|
for (const slot of operation.references) {
|
|
10
11
|
const { operation: source, path: [segment], } = slot.reference.$ref;
|
|
11
12
|
const row = results[source];
|
|
@@ -17,10 +18,14 @@ export function resolveTransactionReferences(operation, results) {
|
|
|
17
18
|
],
|
|
18
19
|
};
|
|
19
20
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
21
|
+
const value = copyScalarFieldValue(slot.source, row[segment]);
|
|
22
|
+
if (slot.written) {
|
|
23
|
+
shapeIssues.push(...jsonShapeIssues(slot.field, value, slot.path));
|
|
24
|
+
}
|
|
25
|
+
substitutions.push({ path: slot.path, value });
|
|
26
|
+
}
|
|
27
|
+
if (shapeIssues.length > 0) {
|
|
28
|
+
return { ok: false, issues: shapeIssues };
|
|
24
29
|
}
|
|
25
30
|
return {
|
|
26
31
|
ok: true,
|
|
@@ -141,25 +141,28 @@ function containsUnpairedSurrogate(value) {
|
|
|
141
141
|
}
|
|
142
142
|
return false;
|
|
143
143
|
}
|
|
144
|
-
function
|
|
144
|
+
function sameScalar(source, destination) {
|
|
145
145
|
if ("scalar" in source.type) {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
if (source.type.scalar !== destination.type.scalar) {
|
|
150
|
-
return false;
|
|
151
|
-
}
|
|
146
|
+
return ("scalar" in destination.type &&
|
|
147
|
+
source.type.scalar === destination.type.scalar);
|
|
152
148
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
149
|
+
return ("enum" in destination.type && source.type.enum === destination.type.enum);
|
|
150
|
+
}
|
|
151
|
+
function isAssignable(source, destination, shape) {
|
|
152
|
+
if (!sameScalar(source, destination)) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
switch (shape) {
|
|
156
|
+
case "value":
|
|
157
|
+
return (source.list === destination.list &&
|
|
158
|
+
!(source.nullable && !destination.nullable));
|
|
159
|
+
case "nonNullValue":
|
|
160
|
+
return source.list === destination.list && !source.nullable;
|
|
161
|
+
case "entry":
|
|
162
|
+
return !source.list && !source.nullable;
|
|
163
|
+
case "entries":
|
|
164
|
+
return source.list && !source.nullable;
|
|
160
165
|
}
|
|
161
|
-
return (source.list === destination.list &&
|
|
162
|
-
!(source.nullable && !destination.nullable));
|
|
163
166
|
}
|
|
164
167
|
const CANDIDATE_KEYS = new Set(["$ref"]);
|
|
165
168
|
const REFERENCE_KEYS = new Set(["operation", "fingerprint", "path"]);
|
|
@@ -234,7 +237,8 @@ export function validateTransactionReferences(operation, earlier) {
|
|
|
234
237
|
if (sourceField === undefined) {
|
|
235
238
|
return failure(validationIssue("V1010", pathPath, "Transaction reference path is not present in the source projection."), operation.index);
|
|
236
239
|
}
|
|
237
|
-
if (sourceField.kind !== "scalar" ||
|
|
240
|
+
if (sourceField.kind !== "scalar" ||
|
|
241
|
+
!isAssignable(sourceField, slot.field, slot.shape)) {
|
|
238
242
|
return failure(validationIssue("V1011", pathPath, "Transaction reference source type is not assignable to its destination."), operation.index);
|
|
239
243
|
}
|
|
240
244
|
const reference = Object.freeze({
|
|
@@ -247,6 +251,9 @@ export function validateTransactionReferences(operation, earlier) {
|
|
|
247
251
|
references.push({
|
|
248
252
|
path: Object.freeze([...slot.path]),
|
|
249
253
|
field: slot.field,
|
|
254
|
+
shape: slot.shape,
|
|
255
|
+
written: slot.written,
|
|
256
|
+
source: sourceField,
|
|
250
257
|
reference,
|
|
251
258
|
});
|
|
252
259
|
}
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import type { WriteScope } from "../contracts/capability.js";
|
|
2
2
|
import type { Contract } from "../contracts/contract.js";
|
|
3
3
|
import type { ScalarForms } from "../contracts/scalar-value-type.js";
|
|
4
|
-
import type { CreateDataInput, OperationArgumentsFor, ResourceKey, UpdateDataInput
|
|
4
|
+
import type { CreateDataInput, OperationArgumentsFor, ResourceKey, UpdateDataInput } from "../operations/operation-arguments.js";
|
|
5
5
|
import type { OperationIdentity } from "../operations/operation-identity.js";
|
|
6
6
|
import type { OperationFingerprint } from "./deferred-operation.js";
|
|
7
7
|
declare const REFERENCE_VALUE: unique symbol;
|
|
8
|
+
/** Any object with a `$ref` key, before it is validated as a reference. */
|
|
8
9
|
export type TransactionReferenceCandidate = {
|
|
9
10
|
readonly $ref: unknown;
|
|
10
11
|
} & Readonly<Record<string, unknown>>;
|
|
12
|
+
/**
|
|
13
|
+
* A reference to a field of an earlier operation's result in the same
|
|
14
|
+
* transaction plan: `{ $ref: { operation, fingerprint, path } }`.
|
|
15
|
+
*/
|
|
11
16
|
export type TransactionReference<Value = unknown> = {
|
|
12
17
|
readonly $ref: {
|
|
13
18
|
readonly operation: number;
|
|
@@ -16,6 +21,7 @@ export type TransactionReference<Value = unknown> = {
|
|
|
16
21
|
};
|
|
17
22
|
readonly [REFERENCE_VALUE]?: Value;
|
|
18
23
|
};
|
|
24
|
+
/** Whether a value is an ordinary value or a `$ref` candidate. */
|
|
19
25
|
export type TransactionReferenceCandidateRoute = {
|
|
20
26
|
readonly kind: "ordinary";
|
|
21
27
|
} | {
|
|
@@ -27,15 +33,11 @@ export type TransactionReferenceCandidateRoute = {
|
|
|
27
33
|
readonly kind: "reflection-failure";
|
|
28
34
|
readonly candidate: unknown;
|
|
29
35
|
};
|
|
30
|
-
/**
|
|
31
|
-
* Total descriptor-only routing for a scalar value at a transaction-reference
|
|
32
|
-
* position.
|
|
33
|
-
*/
|
|
36
|
+
/** Whether a scalar value at a reference position is an ordinary value or a `$ref` candidate. */
|
|
34
37
|
export declare function routeTransactionReferenceCandidate(value: unknown): TransactionReferenceCandidateRoute;
|
|
38
|
+
/** Whether `value` is an object with a `$ref` key; it is not validated here. */
|
|
35
39
|
export declare function isTransactionReferenceCandidate(value: unknown): value is TransactionReferenceCandidate;
|
|
36
|
-
/**
|
|
37
|
-
* Narrows a structurally complete `$ref` object.
|
|
38
|
-
*/
|
|
40
|
+
/** Whether `value` is a complete `$ref` object. */
|
|
39
41
|
export declare function isTransactionReferenceObject(value: unknown): value is TransactionReference;
|
|
40
42
|
/**
|
|
41
43
|
* A scalar mutation value inside a plan: the value itself, or a reference to an
|
|
@@ -43,68 +45,33 @@ export declare function isTransactionReferenceObject(value: unknown): value is T
|
|
|
43
45
|
*/
|
|
44
46
|
export type TransactionScalarValue<Value> = Value | TransactionReference<Value>;
|
|
45
47
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* a `$ref` typed by the application form of the same Contract field — strict type
|
|
49
|
-
* compatibility compares Contract field types, never their forms. Unstated, both
|
|
50
|
-
* are the same map and this is {@link TransactionScalarValue}.
|
|
51
|
-
*/
|
|
52
|
-
type ReferenceableValue<Value, ReferenceValue> = Value | TransactionReference<ReferenceValue>;
|
|
53
|
-
type MemberOf<Data, Key> = Key extends keyof Data ? Data[Key] : never;
|
|
54
|
-
/**
|
|
55
|
-
* The exported {@link TransactionCreateDataInput} is it with neither form stated;
|
|
56
|
-
* the typed builders state both.
|
|
57
|
-
*/
|
|
58
|
-
export type ReferenceableCreateData<C extends Contract, K extends ResourceKey<C>, Scope extends WriteScope, Forms extends ScalarForms, ReferenceForms extends ScalarForms> = Readonly<{
|
|
59
|
-
[F in keyof CreateDataInput<C, K, Scope, Forms>]: F extends WritableRelationKey<C, K, "create", Scope> ? CreateDataInput<C, K, Scope, Forms>[F] : ReferenceableValue<CreateDataInput<C, K, Scope, Forms>[F], MemberOf<CreateDataInput<C, K, Scope, ReferenceForms>, F>>;
|
|
60
|
-
}>;
|
|
61
|
-
export type ReferenceableUpdateData<C extends Contract, K extends ResourceKey<C>, Scope extends WriteScope, Forms extends ScalarForms, ReferenceForms extends ScalarForms> = Readonly<{
|
|
62
|
-
[F in keyof UpdateDataInput<C, K, Scope, Forms>]: F extends WritableRelationKey<C, K, "update", Scope> ? UpdateDataInput<C, K, Scope, Forms>[F] : ReferenceableValue<UpdateDataInput<C, K, Scope, Forms>[F], MemberOf<UpdateDataInput<C, K, Scope, ReferenceForms>, F>>;
|
|
63
|
-
}>;
|
|
64
|
-
/**
|
|
65
|
-
* Only top-level scalar fields accept a `$ref`; a relation field keeps its
|
|
66
|
-
* relation mutation action, where a `$ref` is an ordinary invalid value.
|
|
48
|
+
* What a Transaction Slot holds of its destination field, which decides the source
|
|
49
|
+
* fields a reference there accepts — always the same scalar or enum, no coercion:
|
|
67
50
|
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
51
|
+
* - `"value"` — the field's whole value, where a `null` means something: a mutation
|
|
52
|
+
* value, or an equality filter (`null` matches the rows the field is unset on). A
|
|
53
|
+
* nullable source only into a nullable field.
|
|
54
|
+
* - `"nonNullValue"` — the field's whole value, where a `null` identifies or orders
|
|
55
|
+
* nothing: a unique key, a `cursor`, an ordering or text comparison. The source is
|
|
56
|
+
* never nullable.
|
|
57
|
+
* - `"entry"` — one entry of a list field (`has`): a non-null, non-list source.
|
|
58
|
+
* - `"entries"` — a list of entries (`in`, `notIn`, `hasEvery`, `hasSome`): a
|
|
59
|
+
* non-null list source.
|
|
72
60
|
*/
|
|
73
|
-
export type
|
|
61
|
+
export type TransactionSlotShape = "value" | "nonNullValue" | "entry" | "entries";
|
|
74
62
|
/**
|
|
75
|
-
*
|
|
63
|
+
* Create data inside a transaction plan, at one write position: its scalar values
|
|
64
|
+
* and the unique keys its relation directives name may hold a `$ref`. The default
|
|
65
|
+
* is the unrestricted position, as on `CreateDataInput`.
|
|
76
66
|
*/
|
|
77
|
-
export type
|
|
67
|
+
export type TransactionCreateDataInput<C extends Contract, K extends ResourceKey<C>, Scope extends WriteScope = "nested"> = CreateDataInput<C, K, Scope, ScalarForms, ScalarForms>;
|
|
68
|
+
/** Update data inside a transaction plan. See {@link TransactionCreateDataInput}. */
|
|
69
|
+
export type TransactionUpdateDataInput<C extends Contract, K extends ResourceKey<C>, Scope extends WriteScope = "nested"> = UpdateDataInput<C, K, Scope, ScalarForms, ScalarForms>;
|
|
78
70
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
71
|
+
* Operation arguments inside a transaction plan, under one value form and one
|
|
72
|
+
* reference form: `OperationArgumentsFor` with its reference positions opened.
|
|
81
73
|
*/
|
|
82
|
-
export type ReferenceableArgumentsFor<C extends Contract, K extends ResourceKey<C>, I extends OperationIdentity, Forms extends ScalarForms, ReferenceForms extends ScalarForms> = I
|
|
83
|
-
family: "create";
|
|
84
|
-
variant: "one";
|
|
85
|
-
} ? Omit<OperationArgumentsFor<C, K, I, Forms>, "data"> & {
|
|
86
|
-
data: ReferenceableCreateData<C, K, "nested", Forms, ReferenceForms>;
|
|
87
|
-
} : I extends {
|
|
88
|
-
family: "create";
|
|
89
|
-
variant: "many" | "count";
|
|
90
|
-
} ? Omit<OperationArgumentsFor<C, K, I, Forms>, "data"> & {
|
|
91
|
-
data: readonly ReferenceableCreateData<C, K, "bulkWrite", Forms, ReferenceForms>[];
|
|
92
|
-
} : I extends {
|
|
93
|
-
family: "update";
|
|
94
|
-
variant: "first" | "unique";
|
|
95
|
-
} ? Omit<OperationArgumentsFor<C, K, I, Forms>, "data"> & {
|
|
96
|
-
data: ReferenceableUpdateData<C, K, "nested", Forms, ReferenceForms>;
|
|
97
|
-
} : I extends {
|
|
98
|
-
family: "update";
|
|
99
|
-
variant: "many" | "count";
|
|
100
|
-
} ? Omit<OperationArgumentsFor<C, K, I, Forms>, "data"> & {
|
|
101
|
-
data: ReferenceableUpdateData<C, K, "bulkWrite", Forms, ReferenceForms>;
|
|
102
|
-
} : I extends {
|
|
103
|
-
family: "upsert";
|
|
104
|
-
} ? Omit<OperationArgumentsFor<C, K, I, Forms>, "create" | "update"> & {
|
|
105
|
-
create: ReferenceableCreateData<C, K, "nested", Forms, ReferenceForms>;
|
|
106
|
-
update: ReferenceableUpdateData<C, K, "nested", Forms, ReferenceForms>;
|
|
107
|
-
} : OperationArgumentsFor<C, K, I, Forms>;
|
|
74
|
+
export type ReferenceableArgumentsFor<C extends Contract, K extends ResourceKey<C>, I extends OperationIdentity, Forms extends ScalarForms, ReferenceForms extends ScalarForms> = OperationArgumentsFor<C, K, I, Forms, ReferenceForms>;
|
|
108
75
|
/** Operation arguments inside a transaction plan, no scalar form stated. */
|
|
109
76
|
export type TransactionOperationArgumentsFor<C extends Contract, K extends ResourceKey<C>, I extends OperationIdentity> = ReferenceableArgumentsFor<C, K, I, ScalarForms, ScalarForms>;
|
|
110
77
|
export {};
|
|
@@ -4,25 +4,23 @@ type TransactionRequestBase = {
|
|
|
4
4
|
readonly requestId: string;
|
|
5
5
|
readonly plan: unknown;
|
|
6
6
|
};
|
|
7
|
+
/** An in-process transaction request, run under the Application Contract. */
|
|
7
8
|
export type ApplicationTransactionRequest = TransactionRequestBase & {
|
|
8
|
-
readonly
|
|
9
|
+
readonly origin: "application";
|
|
9
10
|
readonly protocol?: never;
|
|
10
11
|
readonly transport?: never;
|
|
11
12
|
};
|
|
13
|
+
/** A remote transaction request, run under the Client Contract. */
|
|
12
14
|
export type ClientTransactionRequest = TransactionRequestBase & {
|
|
13
|
-
readonly
|
|
15
|
+
readonly origin: "client";
|
|
14
16
|
readonly protocol: ClientProtocolIdentity;
|
|
15
17
|
readonly transport?: PipelineTransportContext;
|
|
16
18
|
};
|
|
19
|
+
/** One transaction request, as `framework.executeTransaction` takes it. */
|
|
17
20
|
export type FrameworkTransactionRequest = ApplicationTransactionRequest | ClientTransactionRequest;
|
|
18
21
|
/**
|
|
19
22
|
* The origin one plan operation runs under: its own layer's Contract, its own
|
|
20
23
|
* pipelines, and — for a client step — the protocol identity it is accepted with.
|
|
21
|
-
* The untyped seam derives every operation's origin from the request; the typed
|
|
22
|
-
* runner states one per handle.
|
|
23
|
-
*
|
|
24
|
-
* Internal to the transaction runtime, and deliberately not a member of the
|
|
25
|
-
* request: the public seam's request cannot smuggle a per-operation origin.
|
|
26
24
|
*/
|
|
27
|
-
export type TransactionOperationOrigin = Pick<ApplicationTransactionRequest, "
|
|
25
|
+
export type TransactionOperationOrigin = Pick<ApplicationTransactionRequest, "origin"> | Pick<ClientTransactionRequest, "origin" | "protocol" | "transport">;
|
|
28
26
|
export {};
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import type { OperationFailureResponse } from "../runtime/operation-response.js";
|
|
2
|
-
/**
|
|
3
|
-
* A committed plan: each operation's final `data`, in plan order.
|
|
4
|
-
*
|
|
5
|
-
* `T` mirrors `OperationResponse<T>`: the untyped seam (`executeTransaction`)
|
|
6
|
-
* answers the default `readonly unknown[]`, and the typed runner
|
|
7
|
-
* (`framework.transaction`) supplies the per-position tuple its handles derive.
|
|
8
|
-
*/
|
|
2
|
+
/** A committed plan: each operation's final `data`, in plan order. */
|
|
9
3
|
export type TransactionCommittedResponse<T = readonly unknown[]> = {
|
|
10
4
|
readonly data: T;
|
|
11
5
|
readonly code: "A1009";
|
|
12
6
|
readonly cause: null;
|
|
13
7
|
};
|
|
8
|
+
/** What a transaction answers: committed (`A1009`) or a failure. */
|
|
14
9
|
export type TransactionResponse = TransactionCommittedResponse | OperationFailureResponse;
|
|
10
|
+
/** Builds the committed response. */
|
|
15
11
|
export declare function transactionCommitted(results: readonly unknown[]): TransactionCommittedResponse;
|
|
12
|
+
/**
|
|
13
|
+
* Builds the failure response of a plan step: the step named in
|
|
14
|
+
* `cause.operation`, and each issue at its full plan location —
|
|
15
|
+
* `["operations", operation, "args", …]` for the step's arguments,
|
|
16
|
+
* `["operations", operation, …]` for the step itself.
|
|
17
|
+
*/
|
|
16
18
|
export declare function transactionOperationFailure(failure: OperationFailureResponse, operation: number): OperationFailureResponse;
|
|
19
|
+
/** Builds the `A3002` response for a transaction that itself failed. */
|
|
17
20
|
export declare function transactionInfrastructureFailure(operation?: number): OperationFailureResponse;
|
|
@@ -1,13 +1,36 @@
|
|
|
1
|
+
import { OPERATION_ARGUMENTS_PATH, planOperationArgumentsPath, planStepPath, } from "../runtime/error-boundary.js";
|
|
1
2
|
import { operationFailure } from "../runtime/operation-response.js";
|
|
2
3
|
export function transactionCommitted(results) {
|
|
3
4
|
return { data: results, code: "A1009", cause: null };
|
|
4
5
|
}
|
|
5
6
|
export function transactionOperationFailure(failure, operation) {
|
|
7
|
+
const { issues, ...cause } = failure.cause;
|
|
6
8
|
return operationFailure(failure.code, {
|
|
7
|
-
...
|
|
9
|
+
...cause,
|
|
10
|
+
...(issues === undefined
|
|
11
|
+
? {}
|
|
12
|
+
: { issues: issues.map((issue) => atPlanLocation(issue, operation)) }),
|
|
8
13
|
operation,
|
|
9
14
|
});
|
|
10
15
|
}
|
|
16
|
+
function isPlanLocated(path) {
|
|
17
|
+
return path[0] === "operations" && typeof path[1] === "number";
|
|
18
|
+
}
|
|
19
|
+
function atPlanLocation(issue, operation) {
|
|
20
|
+
const { path } = issue;
|
|
21
|
+
if (path === undefined || isPlanLocated(path)) {
|
|
22
|
+
return issue;
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
...issue,
|
|
26
|
+
path: path[0] === OPERATION_ARGUMENTS_PATH[0]
|
|
27
|
+
? [
|
|
28
|
+
...planOperationArgumentsPath(operation),
|
|
29
|
+
...path.slice(OPERATION_ARGUMENTS_PATH.length),
|
|
30
|
+
]
|
|
31
|
+
: [...planStepPath(operation), ...path],
|
|
32
|
+
};
|
|
33
|
+
}
|
|
11
34
|
export function transactionInfrastructureFailure(operation) {
|
|
12
35
|
return operationFailure("A3002", {
|
|
13
36
|
message: "Transaction failed.",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AdapterModel } from "../adapters/adapter-model.js";
|
|
2
2
|
import type { TransactionDiagnosticsChannel } from "../runtime/diagnostics-reporter.js";
|
|
3
3
|
import type { OperationRuntimeDependencies } from "../runtime/operation-runtime.js";
|
|
4
|
+
import type { PlanArguments } from "./transaction-plan-validator.js";
|
|
4
5
|
import type { FrameworkTransactionRequest, TransactionOperationOrigin } from "./transaction-request.js";
|
|
5
6
|
import type { TransactionResponse } from "./transaction-response.js";
|
|
6
7
|
/**
|
|
@@ -9,12 +10,13 @@ import type { TransactionResponse } from "./transaction-response.js";
|
|
|
9
10
|
* hands it in, so every report of a plan travels the same route.
|
|
10
11
|
*
|
|
11
12
|
* `origins`, when given, states each operation's own origin (the typed
|
|
12
|
-
* runner's mixed plans)
|
|
13
|
+
* runner's mixed plans), and `planArguments` whether the steps' arguments are
|
|
14
|
+
* copied at the door; see `validateTransactionPlan`.
|
|
13
15
|
*/
|
|
14
|
-
export type FrameworkTransactionExecutor = (request: FrameworkTransactionRequest, diagnostics: TransactionDiagnosticsChannel, origins
|
|
16
|
+
export type FrameworkTransactionExecutor = (request: FrameworkTransactionRequest, diagnostics: TransactionDiagnosticsChannel, origins: readonly TransactionOperationOrigin[] | undefined, planArguments: PlanArguments) => Promise<TransactionResponse>;
|
|
15
17
|
/**
|
|
16
|
-
* Validates a whole plan through the Framework Validation Layer, then runs it
|
|
17
|
-
*
|
|
18
|
-
*
|
|
18
|
+
* Validates a whole plan through the Framework Validation Layer, then runs it inside
|
|
19
|
+
* exactly one Adapter transaction. Guards, pipes, hooks and interceptors of every plan
|
|
20
|
+
* operation run while the provider transaction is open.
|
|
19
21
|
*/
|
|
20
22
|
export declare function createTransactionRuntime<M extends AdapterModel>(dependencies: OperationRuntimeDependencies<M>): FrameworkTransactionExecutor;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { recordWriteFactsOf } from "../runtime/create-requirement.js";
|
|
1
2
|
import { planOperationArgumentsPath } from "../runtime/error-boundary.js";
|
|
2
3
|
import { internalFailure } from "../runtime/operation-response.js";
|
|
3
4
|
import { executeValidatedOperation } from "../runtime/operation-runtime.js";
|
|
@@ -12,14 +13,14 @@ export function createTransactionRuntime(dependencies) {
|
|
|
12
13
|
const { adapter, ...runtimeDependencies } = dependencies;
|
|
13
14
|
const pipelineDependencies = {
|
|
14
15
|
...runtimeDependencies,
|
|
15
|
-
|
|
16
|
+
recordWrites: recordWriteFactsOf(adapter),
|
|
16
17
|
};
|
|
17
18
|
const planDependencies = {
|
|
18
19
|
...pipelineDependencies,
|
|
19
20
|
cascades: resolveCascadeClosure(adapter.referentialActions),
|
|
20
21
|
};
|
|
21
|
-
return async (request, diagnostics, origins) => {
|
|
22
|
-
const validation = await validateTransactionPlan(planDependencies, request, origins);
|
|
22
|
+
return async (request, diagnostics, origins, planArguments) => {
|
|
23
|
+
const validation = await validateTransactionPlan(planDependencies, request, origins, planArguments);
|
|
23
24
|
if (!validation.ok) {
|
|
24
25
|
return validation.response;
|
|
25
26
|
}
|
|
@@ -1,22 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The ways a transaction slot path can fail to name a member of
|
|
3
|
-
*
|
|
4
|
-
* plan validator, so any of these is a framework defect rather than a caller
|
|
5
|
-
* error; the violation is the only thing that tells them apart, so it is
|
|
6
|
-
* structured data rather than message text.
|
|
7
|
-
*
|
|
8
|
-
* - `slot-prefix`: the path does not begin `["operations", <this operation>,
|
|
9
|
-
* "args", <member>]`, or the view itself is not an object.
|
|
10
|
-
* - `absent-member`: a segment names no own member of its container.
|
|
11
|
-
* - `non-object-ancestor`: a segment descends through a non-object value.
|
|
2
|
+
* The ways a transaction slot path can fail to name a member of its argument
|
|
3
|
+
* view. Each is a framework defect, not a caller error.
|
|
12
4
|
*/
|
|
13
5
|
export type TransactionSlotPathViolation = "slot-prefix" | "absent-member" | "non-object-ancestor";
|
|
14
6
|
/**
|
|
15
|
-
*
|
|
16
|
-
* the
|
|
17
|
-
*
|
|
18
|
-
* guard's `A3000`. It reaches a diagnostics sink as the raw `error`, where the
|
|
19
|
-
* violation discriminates the three defects.
|
|
7
|
+
* Thrown internally when a slot path does not name a member of its argument
|
|
8
|
+
* view; the caller receives `A3000`, and the diagnostics sink receives this
|
|
9
|
+
* error.
|
|
20
10
|
*/
|
|
21
11
|
export declare class TransactionSlotPathError extends Error {
|
|
22
12
|
readonly violation: TransactionSlotPathViolation;
|