@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,26 +1,39 @@
|
|
|
1
1
|
import type { ClientProtocolIdentity } from "../runtime/operation-request.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { AvTransportContext } from "../runtime/pipeline.js";
|
|
3
|
+
import type { AvState } from "../runtime/request-state.js";
|
|
3
4
|
type TransactionRequestBase = {
|
|
4
5
|
readonly requestId: string;
|
|
5
6
|
readonly plan: unknown;
|
|
7
|
+
/**
|
|
8
|
+
* The run's `ctx.$state`: every step's stages and the transaction stages share
|
|
9
|
+
* this one object. Omitted, it is a fresh `{}`.
|
|
10
|
+
*/
|
|
11
|
+
readonly state?: AvState;
|
|
6
12
|
};
|
|
7
13
|
/** An in-process transaction request, run under the Application Contract. */
|
|
8
14
|
export type ApplicationTransactionRequest = TransactionRequestBase & {
|
|
9
|
-
readonly
|
|
15
|
+
readonly origin: "application";
|
|
10
16
|
readonly protocol?: never;
|
|
11
17
|
readonly transport?: never;
|
|
12
18
|
};
|
|
13
19
|
/** A remote transaction request, run under the Client Contract. */
|
|
14
20
|
export type ClientTransactionRequest = TransactionRequestBase & {
|
|
15
|
-
readonly
|
|
21
|
+
readonly origin: "client";
|
|
16
22
|
readonly protocol: ClientProtocolIdentity;
|
|
17
|
-
readonly transport?:
|
|
23
|
+
readonly transport?: AvTransportContext;
|
|
24
|
+
};
|
|
25
|
+
/** An AI agent's transaction request, run under the Agent Contract. */
|
|
26
|
+
export type AgentTransactionRequest = TransactionRequestBase & {
|
|
27
|
+
readonly origin: "agent";
|
|
28
|
+
readonly protocol: ClientProtocolIdentity;
|
|
29
|
+
readonly transport?: AvTransportContext;
|
|
18
30
|
};
|
|
19
31
|
/** One transaction request, as `framework.executeTransaction` takes it. */
|
|
20
|
-
export type FrameworkTransactionRequest = ApplicationTransactionRequest | ClientTransactionRequest;
|
|
32
|
+
export type FrameworkTransactionRequest = ApplicationTransactionRequest | ClientTransactionRequest | AgentTransactionRequest;
|
|
21
33
|
/**
|
|
22
34
|
* The origin one plan operation runs under: its own layer's Contract, its own
|
|
23
|
-
* pipelines, and — for a client step — the protocol identity it is
|
|
35
|
+
* pipelines, and — for a client or agent step — the protocol identity it is
|
|
36
|
+
* accepted with.
|
|
24
37
|
*/
|
|
25
|
-
export type TransactionOperationOrigin = Pick<ApplicationTransactionRequest, "
|
|
38
|
+
export type TransactionOperationOrigin = Pick<ApplicationTransactionRequest, "origin"> | Pick<ClientTransactionRequest, "origin" | "protocol" | "transport"> | Pick<AgentTransactionRequest, "origin" | "protocol" | "transport">;
|
|
26
39
|
export {};
|
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AvOperationFailureResponse } from "../runtime/operation-response.js";
|
|
2
2
|
/** A committed plan: each operation's final `data`, in plan order. */
|
|
3
|
-
export type
|
|
3
|
+
export type AvTransactionCommittedResponse<T = readonly unknown[]> = {
|
|
4
4
|
readonly data: T;
|
|
5
5
|
readonly code: "A1009";
|
|
6
6
|
readonly cause: null;
|
|
7
7
|
};
|
|
8
8
|
/** What a transaction answers: committed (`A1009`) or a failure. */
|
|
9
|
-
export type
|
|
9
|
+
export type AvTransactionResponse = AvTransactionCommittedResponse | AvOperationFailureResponse;
|
|
10
10
|
/** Builds the committed response. */
|
|
11
|
-
export declare function transactionCommitted(results: readonly unknown[]):
|
|
12
|
-
/**
|
|
13
|
-
|
|
11
|
+
export declare function transactionCommitted(results: readonly unknown[]): AvTransactionCommittedResponse;
|
|
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
|
+
*/
|
|
18
|
+
export declare function transactionOperationFailure(failure: AvOperationFailureResponse, operation: number): AvOperationFailureResponse;
|
|
14
19
|
/** Builds the `A3002` response for a transaction that itself failed. */
|
|
15
|
-
export declare function transactionInfrastructureFailure(operation?: number):
|
|
20
|
+
export declare function transactionInfrastructureFailure(operation?: number): AvOperationFailureResponse;
|
|
@@ -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,20 +1,23 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AvAdapterModel } from "../adapters/adapter-model.js";
|
|
2
2
|
import type { TransactionDiagnosticsChannel } from "../runtime/diagnostics-reporter.js";
|
|
3
|
-
import type { OperationRuntimeDependencies } from "../runtime/operation-runtime.js";
|
|
3
|
+
import type { OperationPipelineDependencies, 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
|
-
import type {
|
|
6
|
+
import type { AvTransactionResponse } from "./transaction-response.js";
|
|
6
7
|
/**
|
|
7
8
|
* The transaction executor core. Like the operation executor it owns no
|
|
8
9
|
* diagnostics channel: the framework factory binds one to the request and
|
|
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<AvTransactionResponse>;
|
|
15
17
|
/**
|
|
16
18
|
* Validates a whole plan through the Framework Validation Layer, then runs it inside
|
|
17
|
-
* exactly one Adapter transaction.
|
|
18
|
-
* operation
|
|
19
|
+
* exactly one Adapter transaction. The touched Resources' transaction stages and
|
|
20
|
+
* every plan operation's guards, pipes, hooks and interceptors run while the
|
|
21
|
+
* provider transaction is open.
|
|
19
22
|
*/
|
|
20
|
-
export declare function createTransactionRuntime<M extends
|
|
23
|
+
export declare function createTransactionRuntime<M extends AvAdapterModel>(dependencies: OperationRuntimeDependencies<M>, pipelineDependencies: OperationPipelineDependencies<M>): FrameworkTransactionExecutor;
|
|
@@ -1,80 +1,197 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { transactionLevelsOf } from "../config/pipeline-tree.resolver.js";
|
|
2
|
+
import { AdapterBoundary, planOperationArgumentsPath, planStepPath, sanitizeOperationFailure, } from "../runtime/error-boundary.js";
|
|
3
|
+
import { isPlainRecord, valueAt } from "../runtime/field-stage.runtime.js";
|
|
4
|
+
import { internalFailure, operationSuccess, } from "../runtime/operation-response.js";
|
|
5
|
+
import { admitOperation, executeAdmittedOperation, prepareStep, withRequestState, } from "../runtime/operation-runtime.js";
|
|
4
6
|
import { mapValidationOutcome } from "../runtime/outcome-mapper.js";
|
|
5
7
|
import { resolveCascadeClosure } from "../runtime/referential-action.js";
|
|
6
|
-
import {
|
|
8
|
+
import { AvTransactionIntegrityError } from "./transaction-integrity-error.js";
|
|
7
9
|
import { validateTransactionPlan } from "./transaction-plan-validator.js";
|
|
8
|
-
import { resolveTransactionReferences } from "./transaction-reference-resolver.js";
|
|
10
|
+
import { resolveSqlStatement, resolveTransactionReferences, } from "./transaction-reference-resolver.js";
|
|
9
11
|
import { transactionCommitted, transactionInfrastructureFailure, transactionOperationFailure, } from "./transaction-response.js";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
...runtimeDependencies,
|
|
15
|
-
createRequirements: adapter.createRequirements ?? {},
|
|
16
|
-
};
|
|
12
|
+
import { settleTransaction } from "./transaction-settlement.runtime.js";
|
|
13
|
+
import { touchedTransactionLevels, transactionFacts, } from "./transaction-stage.runtime.js";
|
|
14
|
+
export function createTransactionRuntime(dependencies, pipelineDependencies) {
|
|
15
|
+
const { adapter } = dependencies;
|
|
17
16
|
const planDependencies = {
|
|
18
17
|
...pipelineDependencies,
|
|
19
18
|
cascades: resolveCascadeClosure(adapter.referentialActions),
|
|
19
|
+
sqlStatements: adapter.sqlStatements === true,
|
|
20
20
|
};
|
|
21
|
-
return async (
|
|
22
|
-
const
|
|
21
|
+
return async (seeded, diagnostics, origins, planArguments) => {
|
|
22
|
+
const request = withRequestState(seeded);
|
|
23
|
+
const validation = await validateTransactionPlan(planDependencies, request, origins, planArguments);
|
|
23
24
|
if (!validation.ok) {
|
|
24
25
|
return validation.response;
|
|
25
26
|
}
|
|
26
|
-
return executeTransactionPlan(adapter, pipelineDependencies, validation.plan, diagnostics);
|
|
27
|
+
return executeTransactionPlan(adapter, pipelineDependencies, request, validation.plan, request.state, diagnostics);
|
|
27
28
|
};
|
|
28
29
|
}
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
function planOrigin(request, plan) {
|
|
31
|
+
for (const step of plan.operations) {
|
|
32
|
+
if (step.kind === "operation") {
|
|
33
|
+
return step.request;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return request;
|
|
37
|
+
}
|
|
38
|
+
function stepView(step, args) {
|
|
39
|
+
if (step.kind === "sql") {
|
|
40
|
+
return {
|
|
41
|
+
sql: {
|
|
42
|
+
strings: step.strings,
|
|
43
|
+
values: step.values.map((value) => value.kind === "value"
|
|
44
|
+
? value.value
|
|
45
|
+
: { $ref: { operation: value.operation, path: [value.field] } }),
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
resource: step.request.resource,
|
|
51
|
+
family: step.request.family,
|
|
52
|
+
variant: step.request.variant,
|
|
53
|
+
args,
|
|
35
54
|
};
|
|
36
|
-
|
|
37
|
-
|
|
55
|
+
}
|
|
56
|
+
function pathKey(path) {
|
|
57
|
+
return JSON.stringify(path);
|
|
58
|
+
}
|
|
59
|
+
function relativeSlotPath(operation, path) {
|
|
60
|
+
return path.slice(planOperationArgumentsPath(operation.index).length);
|
|
61
|
+
}
|
|
62
|
+
function standsAt(args, path, slot) {
|
|
63
|
+
const value = valueAt(args, path);
|
|
64
|
+
if (value === slot.reference) {
|
|
65
|
+
return true;
|
|
38
66
|
}
|
|
39
|
-
const
|
|
67
|
+
const reference = isPlainRecord(value) ? value.$ref : undefined;
|
|
68
|
+
if (!isPlainRecord(reference) || !Array.isArray(reference.path)) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
const expected = slot.reference.$ref;
|
|
72
|
+
return (reference.operation === expected.operation &&
|
|
73
|
+
reference.path.length === 1 &&
|
|
74
|
+
reference.path[0] === expected.path[0]);
|
|
75
|
+
}
|
|
76
|
+
function slotKeys(operation) {
|
|
77
|
+
return new Set(operation.references.map((slot) => pathKey(relativeSlotPath(operation, slot.path))));
|
|
78
|
+
}
|
|
79
|
+
async function executeTransactionPlan(adapter, dependencies, request, plan, state, diagnostics) {
|
|
80
|
+
const stateful = (operation) => ({ ...operation.request, state });
|
|
81
|
+
const admitted = [];
|
|
82
|
+
for (const step of plan.operations) {
|
|
83
|
+
if (step.kind === "sql") {
|
|
84
|
+
admitted.push({ ok: true, args: undefined, piped: false });
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const references = slotKeys(step);
|
|
88
|
+
const admission = await admitOperation(dependencies, stateful(step), step.contract, step.arguments, planOperationArgumentsPath(step.index), diagnostics.operation(step.request, step.index), { requestId: request.requestId, transaction: undefined, state }, {
|
|
89
|
+
select: (path) => !references.has(pathKey(path)),
|
|
90
|
+
validation: { transactionReferences: true },
|
|
91
|
+
});
|
|
92
|
+
if (!admission.ok) {
|
|
93
|
+
return transactionOperationFailure(admission.response, step.index);
|
|
94
|
+
}
|
|
95
|
+
admitted.push(admission);
|
|
96
|
+
}
|
|
97
|
+
const origin = planOrigin(request, plan);
|
|
98
|
+
const contract = dependencies.contracts[origin.origin];
|
|
99
|
+
const tree = dependencies.config[origin.origin].pipelines;
|
|
100
|
+
const view = plan.operations.map((step, index) => stepView(step, admitted[index]?.args));
|
|
101
|
+
const runPlanOperation = async (operation, args, transactionPiped, executor, results, outer) => {
|
|
40
102
|
const report = diagnostics.operation(operation.request, operation.index);
|
|
103
|
+
const argumentsPath = planOperationArgumentsPath(operation.index);
|
|
104
|
+
const stepRequest = stateful(operation);
|
|
41
105
|
try {
|
|
42
|
-
const
|
|
106
|
+
const live = operation.references.filter((slot) => standsAt(args, relativeSlotPath(operation, slot.path), slot));
|
|
107
|
+
const resolved = resolveTransactionReferences({
|
|
108
|
+
...operation,
|
|
109
|
+
arguments: args,
|
|
110
|
+
references: live,
|
|
111
|
+
}, results);
|
|
43
112
|
if (!resolved.ok) {
|
|
44
113
|
return mapValidationOutcome(resolved.issues);
|
|
45
114
|
}
|
|
46
|
-
|
|
115
|
+
const written = new Set(live
|
|
116
|
+
.filter((slot) => slot.written)
|
|
117
|
+
.map((slot) => pathKey(relativeSlotPath(operation, slot.path))));
|
|
118
|
+
const prepared = await prepareStep(dependencies, stepRequest, operation.contract, resolved.arguments, argumentsPath, report, executor, {
|
|
119
|
+
written: (path) => written.has(pathKey(path)),
|
|
120
|
+
transactionPiped,
|
|
121
|
+
pipedAroundReferences: admitted[operation.index]?.piped === true &&
|
|
122
|
+
operation.references.length > 0,
|
|
123
|
+
}, outer);
|
|
124
|
+
if (!prepared.ok) {
|
|
125
|
+
return prepared.response;
|
|
126
|
+
}
|
|
127
|
+
return await executeAdmittedOperation(dependencies, stepRequest, operation.contract, prepared.args, argumentsPath, { kind: "transaction", executor, outer }, report);
|
|
47
128
|
}
|
|
48
129
|
catch (error) {
|
|
49
130
|
report(error, "A3000");
|
|
50
131
|
return internalFailure();
|
|
51
132
|
}
|
|
52
133
|
};
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
134
|
+
const runSqlStatement = async (step, executor, results) => {
|
|
135
|
+
const report = diagnostics.transaction(step.index);
|
|
136
|
+
const boundary = new AdapterBoundary();
|
|
137
|
+
try {
|
|
138
|
+
const resolved = resolveSqlStatement(step, results);
|
|
139
|
+
if (!resolved.ok) {
|
|
140
|
+
return mapValidationOutcome(resolved.issues);
|
|
141
|
+
}
|
|
142
|
+
if (typeof executor.executeSql !== "function") {
|
|
143
|
+
report(new AvTransactionIntegrityError("statement-unavailable"), "A3002");
|
|
144
|
+
return transactionInfrastructureFailure();
|
|
145
|
+
}
|
|
146
|
+
const executeSql = executor.executeSql.bind(executor);
|
|
147
|
+
try {
|
|
148
|
+
const rows = await boundary.execute(async () => {
|
|
149
|
+
const answer = await executeSql(resolved.statement);
|
|
150
|
+
if (!Array.isArray(answer)) {
|
|
151
|
+
throw new TypeError("Adapter executeSql must resolve the statement's rows as an array.");
|
|
152
|
+
}
|
|
153
|
+
return answer;
|
|
154
|
+
});
|
|
155
|
+
return operationSuccess([...rows], "A1000");
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
return sanitizeOperationFailure(error, boundary.originOf(error), report, {
|
|
159
|
+
path: [...planStepPath(step.index), "values"],
|
|
160
|
+
arguments: resolved.statement.values,
|
|
161
|
+
});
|
|
62
162
|
}
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
catch (error) {
|
|
66
|
-
if (error !== TRANSACTION_ABORT) {
|
|
67
|
-
return infrastructureFailure(error);
|
|
68
163
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
164
|
+
catch (error) {
|
|
165
|
+
report(error, "A3000");
|
|
166
|
+
return internalFailure();
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
const settled = await settleTransaction({
|
|
170
|
+
adapter,
|
|
171
|
+
levels: touchedTransactionLevels(view, (resource) => transactionLevelsOf(tree, resource)),
|
|
172
|
+
plan: view,
|
|
173
|
+
contextOf: (current, executor) => dependencies.contexts.transaction({ requestId: origin.requestId, transaction: executor, state }, transactionFacts(contract, origin, current)),
|
|
174
|
+
failureView: { path: ["operations"], arguments: view },
|
|
175
|
+
report: diagnostics.transaction(),
|
|
176
|
+
runStep: (index, step, piped, executor, results, outer) => {
|
|
177
|
+
const operation = plan.operations[index];
|
|
178
|
+
if (operation === undefined) {
|
|
179
|
+
throw new TypeError(`Transaction step ${index} is not in the plan.`);
|
|
180
|
+
}
|
|
181
|
+
return operation.kind === "sql"
|
|
182
|
+
? runSqlStatement(operation, executor, results)
|
|
183
|
+
: runPlanOperation(operation, step.args, piped, executor, results, outer);
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
switch (settled.kind) {
|
|
187
|
+
case "committed":
|
|
188
|
+
return transactionCommitted(settled.responses.map((response) => response.data));
|
|
189
|
+
case "rolled-back":
|
|
190
|
+
return settled.operation === undefined
|
|
191
|
+
? settled.response
|
|
192
|
+
: transactionOperationFailure(settled.response, settled.operation);
|
|
193
|
+
case "broken":
|
|
194
|
+
diagnostics.transaction(settled.operation)(settled.error, "A3002");
|
|
195
|
+
return transactionInfrastructureFailure(settled.operation);
|
|
78
196
|
}
|
|
79
|
-
return transactionCommitted([...ledger.results]);
|
|
80
197
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { AvAdapter } from "../adapters/adapter.interface.js";
|
|
2
|
+
import type { AvAdapterModel } from "../adapters/adapter-model.js";
|
|
3
|
+
import type { AvAdapterTransactionExecutor } from "../adapters/adapter-transaction-executor.interface.js";
|
|
4
|
+
import type { ResolvedTransactionPipelineConfig } from "../config/pipeline-config.js";
|
|
5
|
+
import type { DiagnosticsReporter } from "../runtime/diagnostics-reporter.js";
|
|
6
|
+
import { type CallerArgumentsView, type OuterFailureLayer } from "../runtime/error-boundary.js";
|
|
7
|
+
import type { AvOperationFailureResponse, AvOperationResponse } from "../runtime/operation-response.js";
|
|
8
|
+
import type { AvTransactionContext } from "../runtime/pipeline.js";
|
|
9
|
+
import { type TransactionStepView } from "./transaction-stage.runtime.js";
|
|
10
|
+
/**
|
|
11
|
+
* Runs one step inside the open transaction: `step` as the transaction pipes
|
|
12
|
+
* left it, `piped` whether one ran, `results` the completed steps' data in plan
|
|
13
|
+
* order, `outer` where an error the step's own filters leave unhandled is handed:
|
|
14
|
+
* the touched Resources' transaction filters answer it once the transaction
|
|
15
|
+
* interceptors have unwound. Its answer is the step's own outcome.
|
|
16
|
+
*/
|
|
17
|
+
export type TransactionStepRunner<M extends AvAdapterModel> = (index: number, step: TransactionStepView, piped: boolean, executor: AvAdapterTransactionExecutor<M>, results: readonly unknown[], outer: OuterFailureLayer) => Promise<AvOperationResponse>;
|
|
18
|
+
/** How one transaction settled. */
|
|
19
|
+
export type TransactionSettlement =
|
|
20
|
+
/** Committed: every step's own outcome, in plan order. */
|
|
21
|
+
{
|
|
22
|
+
readonly kind: "committed";
|
|
23
|
+
readonly responses: readonly AvOperationResponse[];
|
|
24
|
+
}
|
|
25
|
+
/** Rolled back on a deliberate outcome: a step's (with its index) or a stage's. */
|
|
26
|
+
| {
|
|
27
|
+
readonly kind: "rolled-back";
|
|
28
|
+
readonly response: AvOperationFailureResponse;
|
|
29
|
+
readonly operation: number | undefined;
|
|
30
|
+
}
|
|
31
|
+
/** The transaction contract broke: `A3002`, the error for diagnostics. */
|
|
32
|
+
| {
|
|
33
|
+
readonly kind: "broken";
|
|
34
|
+
readonly error: unknown;
|
|
35
|
+
readonly operation: number | undefined;
|
|
36
|
+
};
|
|
37
|
+
export type TransactionSettlementInput<M extends AvAdapterModel> = {
|
|
38
|
+
readonly adapter: AvAdapter<M>;
|
|
39
|
+
/** The touched Resources' transaction levels, outer to inner. */
|
|
40
|
+
readonly levels: readonly ResolvedTransactionPipelineConfig[];
|
|
41
|
+
readonly plan: readonly TransactionStepView[];
|
|
42
|
+
/** The ctx a transaction stage is told, bound to the open transaction. */
|
|
43
|
+
readonly contextOf: (plan: readonly TransactionStepView[], executor: AvAdapterTransactionExecutor<M>) => AvTransactionContext;
|
|
44
|
+
/** What a stage failure's filters may read as the caller's arguments. */
|
|
45
|
+
readonly failureView: CallerArgumentsView;
|
|
46
|
+
/** The channel a transaction stage's own failure is reported on. */
|
|
47
|
+
readonly report: DiagnosticsReporter;
|
|
48
|
+
readonly runStep: TransactionStepRunner<M>;
|
|
49
|
+
};
|
|
50
|
+
/** Runs `plan` inside one Adapter transaction, its stages around its steps, and settles it. */
|
|
51
|
+
export declare function settleTransaction<M extends AvAdapterModel>(input: TransactionSettlementInput<M>): Promise<TransactionSettlement>;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { filterChain, resolveUnhandledFailure, sanitizeOperationFailure, } from "../runtime/error-boundary.js";
|
|
2
|
+
import { thrownFailure } from "../runtime/framework-error.factory.js";
|
|
3
|
+
import { operationFailure } from "../runtime/operation-response.js";
|
|
4
|
+
import { AvTransactionIntegrityError } from "./transaction-integrity-error.js";
|
|
5
|
+
import { resolveTransactionStageFailure, runTransactionStages, TRANSACTION_ABORT, } from "./transaction-stage.runtime.js";
|
|
6
|
+
export async function settleTransaction(input) {
|
|
7
|
+
const { adapter, levels, plan, contextOf } = input;
|
|
8
|
+
if (typeof adapter.transaction !== "function") {
|
|
9
|
+
return {
|
|
10
|
+
kind: "broken",
|
|
11
|
+
error: new AvTransactionIntegrityError("transaction-unavailable"),
|
|
12
|
+
operation: undefined,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
const ledger = { results: [], responses: [], failure: undefined, deferred: undefined };
|
|
16
|
+
const { results, responses } = ledger;
|
|
17
|
+
const failedOperation = () => ledger.failure?.kind === "rolled-back"
|
|
18
|
+
? ledger.failure.operation
|
|
19
|
+
: undefined;
|
|
20
|
+
try {
|
|
21
|
+
await adapter.transaction(async (executor) => {
|
|
22
|
+
const staged = await runTransactionStages(levels, plan, (current) => contextOf(current, executor), async ({ plan: current, piped }) => {
|
|
23
|
+
const outer = {
|
|
24
|
+
defer: (failure) => {
|
|
25
|
+
ledger.deferred = { failure, plan: current };
|
|
26
|
+
return sanitizeOperationFailure(failure.error, failure.boundary.originOf(failure.error), () => { }, failure.view);
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
for (const [index, step] of current.entries()) {
|
|
30
|
+
const response = await input.runStep(index, step, piped, executor, results, outer);
|
|
31
|
+
if (response.cause !== null) {
|
|
32
|
+
ledger.failure = {
|
|
33
|
+
kind: "rolled-back",
|
|
34
|
+
response,
|
|
35
|
+
operation: index,
|
|
36
|
+
};
|
|
37
|
+
throw thrownFailure(response);
|
|
38
|
+
}
|
|
39
|
+
results.push(response.data);
|
|
40
|
+
responses.push(response);
|
|
41
|
+
}
|
|
42
|
+
return [...results];
|
|
43
|
+
});
|
|
44
|
+
if (staged.kind === "broken") {
|
|
45
|
+
ledger.failure = { kind: "broken", error: staged.error };
|
|
46
|
+
throw TRANSACTION_ABORT;
|
|
47
|
+
}
|
|
48
|
+
const deferred = ledger.deferred;
|
|
49
|
+
if (deferred !== undefined && ledger.failure?.kind === "rolled-back") {
|
|
50
|
+
ledger.failure = {
|
|
51
|
+
...ledger.failure,
|
|
52
|
+
response: await resolveUnhandledFailure(deferred.failure, filterChain(levels.flatMap((level) => level.filters), contextOf(deferred.plan, executor))),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (staged.kind === "ran") {
|
|
56
|
+
if (ledger.failure === undefined && results.length !== plan.length) {
|
|
57
|
+
ledger.failure = {
|
|
58
|
+
kind: "broken",
|
|
59
|
+
error: new AvTransactionIntegrityError("steps-not-run"),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (ledger.failure !== undefined) {
|
|
63
|
+
throw TRANSACTION_ABORT;
|
|
64
|
+
}
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (ledger.failure === undefined) {
|
|
68
|
+
let response;
|
|
69
|
+
if (staged.kind === "denied") {
|
|
70
|
+
response = operationFailure("A4001", {
|
|
71
|
+
message: "Operation denied by a framework guard.",
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
else if (staged.kind === "refused") {
|
|
75
|
+
input.report(staged.refusal.error, "A3004");
|
|
76
|
+
response = staged.refusal.response;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
response = await resolveTransactionStageFailure(staged.error, levels, contextOf(plan, executor), input.report, input.failureView);
|
|
80
|
+
}
|
|
81
|
+
ledger.failure = {
|
|
82
|
+
kind: "rolled-back",
|
|
83
|
+
response,
|
|
84
|
+
operation: undefined,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
throw TRANSACTION_ABORT;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
if (error !== TRANSACTION_ABORT) {
|
|
92
|
+
return { kind: "broken", error, operation: failedOperation() };
|
|
93
|
+
}
|
|
94
|
+
if (ledger.failure === undefined) {
|
|
95
|
+
return {
|
|
96
|
+
kind: "broken",
|
|
97
|
+
error: new AvTransactionIntegrityError("foreign-abort"),
|
|
98
|
+
operation: undefined,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return ledger.failure.kind === "broken"
|
|
102
|
+
? { kind: "broken", error: ledger.failure.error, operation: undefined }
|
|
103
|
+
: ledger.failure;
|
|
104
|
+
}
|
|
105
|
+
if (ledger.failure !== undefined) {
|
|
106
|
+
return {
|
|
107
|
+
kind: "broken",
|
|
108
|
+
error: new AvTransactionIntegrityError("resolved-after-abort"),
|
|
109
|
+
operation: failedOperation(),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
if (responses.length !== plan.length) {
|
|
113
|
+
return {
|
|
114
|
+
kind: "broken",
|
|
115
|
+
error: new AvTransactionIntegrityError("resolved-incomplete"),
|
|
116
|
+
operation: undefined,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
return { kind: "committed", responses };
|
|
120
|
+
}
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* The ways a transaction slot path can fail to name a member of its argument
|
|
3
3
|
* view. Each is a framework defect, not a caller error.
|
|
4
4
|
*/
|
|
5
|
-
export type
|
|
5
|
+
export type AvTransactionSlotPathViolation = "slot-prefix" | "absent-member" | "non-object-ancestor";
|
|
6
6
|
/**
|
|
7
7
|
* Thrown internally when a slot path does not name a member of its argument
|
|
8
8
|
* view; the caller receives `A3000`, and the diagnostics sink receives this
|
|
9
9
|
* error.
|
|
10
10
|
*/
|
|
11
|
-
export declare class
|
|
12
|
-
readonly violation:
|
|
13
|
-
constructor(violation:
|
|
11
|
+
export declare class AvTransactionSlotPathError extends Error {
|
|
12
|
+
readonly violation: AvTransactionSlotPathViolation;
|
|
13
|
+
constructor(violation: AvTransactionSlotPathViolation);
|
|
14
14
|
}
|
|
@@ -3,11 +3,11 @@ const TRANSACTION_SLOT_PATH_MESSAGES = {
|
|
|
3
3
|
"absent-member": "Transaction slot path names an absent member of the operation arguments.",
|
|
4
4
|
"non-object-ancestor": "Transaction slot path descends through a non-object value.",
|
|
5
5
|
};
|
|
6
|
-
export class
|
|
6
|
+
export class AvTransactionSlotPathError extends Error {
|
|
7
7
|
violation;
|
|
8
8
|
constructor(violation) {
|
|
9
9
|
super(TRANSACTION_SLOT_PATH_MESSAGES[violation]);
|
|
10
|
-
this.name = "
|
|
10
|
+
this.name = "AvTransactionSlotPathError";
|
|
11
11
|
this.violation = violation;
|
|
12
12
|
}
|
|
13
13
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AvTransactionSlotPathError } from "./transaction-slot-path-error.js";
|
|
2
2
|
function slotPathMismatch(violation) {
|
|
3
|
-
throw new
|
|
3
|
+
throw new AvTransactionSlotPathError(violation);
|
|
4
4
|
}
|
|
5
5
|
function cloneContainerWithReplacement(container, property, replacement) {
|
|
6
6
|
const array = Array.isArray(container);
|