@aventara/core 1.0.0-rc.0 → 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 +1140 -0
- package/README.md +224 -57
- 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 +9 -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 -29
- 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/{json → avz}/avz.js +150 -8
- package/dist/{json → avz}/index.d.ts +2 -1
- package/dist/{json → avz}/json-shape.registry.d.ts +7 -7
- package/dist/{json → avz}/zod-issue.translator.d.ts +8 -2
- package/dist/{json → avz}/zod-issue.translator.js +7 -0
- package/dist/compiler/contract-compiler-diagnostic.d.ts +31 -5
- package/dist/compiler/contract.compiler.d.ts +18 -18
- package/dist/compiler/contract.compiler.js +548 -441
- 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 +74 -31
- package/dist/config/config.resolver.js +108 -44
- package/dist/config/config.validator.d.ts +7 -7
- package/dist/config/config.validator.js +581 -72
- 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 +110 -39
- 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 +323 -28
- package/dist/contracts/client-contract-structure.validator.js +152 -8
- package/dist/contracts/contract-canonicalizer.d.ts +19 -3
- package/dist/contracts/contract-canonicalizer.js +141 -28
- 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 +24 -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 +52 -42
- package/dist/contracts/identifier.d.ts +4 -4
- package/dist/contracts/json-shape.d.ts +12 -1
- package/dist/contracts/lifecycle-trait.d.ts +2 -2
- 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 +15 -15
- 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 +213 -147
- 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 +47 -23
- package/dist/framework/framework.factory.d.ts +8 -6
- package/dist/framework/framework.factory.js +40 -20
- package/dist/framework/operation-facade.d.ts +123 -52
- package/dist/framework/operation-facade.js +9 -1
- package/dist/index.d.ts +55 -50
- package/dist/index.js +6 -6
- package/dist/internal.d.ts +15 -10
- package/dist/internal.js +3 -1
- package/dist/operations/operation-arguments.d.ts +267 -202
- package/dist/operations/operation-call.d.ts +27 -28
- package/dist/operations/operation-identity.d.ts +10 -10
- 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 +13 -2
- package/dist/operations/operation-validator.d.ts +9 -9
- package/dist/operations/projection-scope.resolver.d.ts +6 -6
- package/dist/operations/structural-limits.walker.d.ts +6 -6
- package/dist/operations/structural-limits.walker.js +145 -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 -12
- package/dist/protocol/absent-route.responder.js +19 -19
- 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 +17 -13
- package/dist/protocol/http-request.decoder.js +10 -10
- 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 +50 -27
- package/dist/protocol/protocol.binder.js +12 -9
- package/dist/protocol/protocol.handler.d.ts +22 -13
- package/dist/protocol/protocol.handler.js +44 -9
- package/dist/protocol/unmounted-route.error.d.ts +4 -4
- package/dist/protocol/unmounted-route.error.js +2 -2
- package/dist/runtime/caller-data.copier.d.ts +5 -5
- package/dist/runtime/caller-data.copier.js +13 -13
- package/dist/runtime/caller-data.door.d.ts +6 -6
- package/dist/runtime/caller-data.door.js +6 -4
- package/dist/runtime/computed-read-runtime.d.ts +7 -6
- package/dist/runtime/computed-read-runtime.js +61 -48
- package/dist/runtime/computed-value.error.d.ts +6 -6
- package/dist/runtime/computed-value.error.js +3 -3
- 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 +10 -81
- package/dist/runtime/create-requirement.js +80 -57
- package/dist/runtime/decimal.d.ts +2 -2
- package/dist/runtime/decimal.js +1 -1
- package/dist/runtime/diagnostics-reporter.d.ts +53 -27
- package/dist/runtime/diagnostics-reporter.js +24 -0
- package/dist/runtime/error-boundary.d.ts +65 -8
- package/dist/runtime/error-boundary.js +45 -19
- 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 +68 -8
- 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 +12 -12
- package/dist/runtime/mutation-planner.d.ts +19 -10
- package/dist/runtime/mutation-planner.js +54 -30
- 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 +33 -6
- package/dist/runtime/operation-response.d.ts +17 -17
- package/dist/runtime/operation-runtime.d.ts +113 -25
- package/dist/runtime/operation-runtime.js +395 -74
- package/dist/runtime/outcome-mapper.d.ts +16 -5
- package/dist/runtime/outcome-mapper.js +23 -6
- package/dist/runtime/output-validator.d.ts +10 -10
- package/dist/runtime/output-validator.js +3 -3
- package/dist/runtime/owned-execution.registry.d.ts +6 -6
- 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 +196 -34
- package/dist/runtime/readonly-value.d.ts +32 -0
- package/dist/runtime/readonly-value.js +141 -0
- package/dist/runtime/request-envelope.validator.d.ts +3 -3
- package/dist/runtime/request-envelope.validator.js +12 -7
- 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 +31 -16
- package/dist/runtime/scalar-runtime.js +16 -18
- 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 +21 -11
- package/dist/transactions/transaction-plan-assembler.js +148 -34
- package/dist/transactions/transaction-plan-validator.d.ts +29 -20
- package/dist/transactions/transaction-plan-validator.js +70 -38
- package/dist/transactions/transaction-reference-collector.d.ts +5 -5
- package/dist/transactions/transaction-reference-resolver.d.ts +19 -2
- package/dist/transactions/transaction-reference-resolver.js +26 -14
- package/dist/transactions/transaction-reference-validator.d.ts +34 -4
- package/dist/transactions/transaction-reference-validator.js +58 -26
- package/dist/transactions/transaction-reference.d.ts +13 -13
- package/dist/transactions/transaction-request.d.ts +18 -5
- package/dist/transactions/transaction-response.d.ts +6 -6
- package/dist/transactions/transaction-runtime.d.ts +8 -7
- package/dist/transactions/transaction-runtime.js +166 -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 +6 -5
- package/src/runtime/field-check.evaluator.ts +720 -0
- package/dist/config/define-fields.d.ts +0 -42
- 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 -42
- package/dist/config/framework-restrictions-config.d.ts +0 -142
- package/dist/json/avz.d.ts +0 -96
- 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/{json → avz}/index.js +0 -0
- /package/dist/{json → avz}/json-shape.registry.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,101 +1,30 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
1
|
+
import type { AvContract } from "../contracts/contract.js";
|
|
2
|
+
import type { AvOperationIdentity } from "../operations/operation-identity.js";
|
|
3
|
+
import type { AvValidationIssue } from "../operations/validation-code.js";
|
|
4
4
|
import type { ReferentialActionTable } from "./referential-action.js";
|
|
5
|
-
/**
|
|
6
|
-
* Core's create-requirement vocabulary, and the check that reads it.
|
|
7
|
-
*
|
|
8
|
-
* **The facts are an Adapter's.** Which values a store cannot create a row
|
|
9
|
-
* without is a property of the store's schema — a column with no default, a
|
|
10
|
-
* reference that must point somewhere — and only the Adapter can read it. The
|
|
11
|
-
* words are Aventara's, so an Adapter translates its provider's facts into them,
|
|
12
|
-
* and the reasoning over them is core's, so no Adapter re-implements it.
|
|
13
|
-
*
|
|
14
|
-
* None of this enters a Contract. A Contract carries no foreign-key detail and
|
|
15
|
-
* no knowledge of which relation is the other end of which, and a requirement
|
|
16
|
-
* needs both; it is a server-side fact, read once when the Framework is
|
|
17
|
-
* constructed, like the referential actions.
|
|
18
|
-
*
|
|
19
|
-
* **When the check runs.** After guards, pipes and computed write behaviours —
|
|
20
|
-
* the moment the arguments are what the Adapter will be handed — and before
|
|
21
|
-
* any `before` hook or Adapter work. Earlier would refuse a value a pipe or a
|
|
22
|
-
* computed behaviour was about to supply; later is the store's own refusal,
|
|
23
|
-
* which reaches the caller as an internal failure. A missing value is the
|
|
24
|
-
* caller's to fix, so it answers `A2004` with a `V1000` issue at the path where
|
|
25
|
-
* the value belongs.
|
|
26
|
-
*
|
|
27
|
-
* **One value, two spellings.** A relation that holds a reference has scalar
|
|
28
|
-
* fields that hold it too — the Adapter states which, on the relation's
|
|
29
|
-
* referential edge (`ReferentialEdge.references`), for every such relation,
|
|
30
|
-
* required or optional. A write that sets both — `authorId` and
|
|
31
|
-
* `author: { $connect: … }` in one record, at create or update — names the
|
|
32
|
-
* reference twice. No store can honour both, and which one the caller meant is
|
|
33
|
-
* not the framework's to guess, so it is the caller's `A2004` too: a `V1012`
|
|
34
|
-
* issue at the relation, in every record the check walks, before any Adapter
|
|
35
|
-
* work. The same edge is what a required relation may instead be written
|
|
36
|
-
* through, so the pairing has one source.
|
|
37
|
-
*
|
|
38
|
-
* **One store, one spelling per record.** A store may take a record's
|
|
39
|
-
* references only one way at a time — every relation that holds one written as
|
|
40
|
-
* a relation, or every one through its fields — and state it as the Contract's
|
|
41
|
-
* `referenceWrites: "uniform"`. Under it, a record that writes a relation
|
|
42
|
-
* holding a reference beside another relation's reference field is the caller's
|
|
43
|
-
* `A2004` as well: a `V1012` issue at the relation write.
|
|
44
|
-
*/
|
|
45
|
-
/** A relation edge, named by the Resource that holds it and its field there. */
|
|
46
|
-
export type CreateRequirementEdge = {
|
|
47
|
-
readonly resource: string;
|
|
48
|
-
readonly relation: string;
|
|
49
|
-
};
|
|
50
|
-
/**
|
|
51
|
-
* One value a create of a Resource cannot do without.
|
|
52
|
-
*
|
|
53
|
-
* - `field` — a scalar with no default, generated value or other source: it
|
|
54
|
-
* must be written.
|
|
55
|
-
* - `relation` — a required to-one relation: it must be written (connected or
|
|
56
|
-
* created), or every field that holds its reference must be — the
|
|
57
|
-
* `references` of the relation's referential edge, less any the store fills
|
|
58
|
-
* itself (`DEFAULTED` or `GENERATED_ON_CREATE`). When the row is created
|
|
59
|
-
* **through** the relation's other end (`inverse`), the parent supplies it,
|
|
60
|
-
* and it is not required.
|
|
61
|
-
*/
|
|
62
|
-
export type CreateRequirement = {
|
|
63
|
-
readonly kind: "field";
|
|
64
|
-
readonly field: string;
|
|
65
|
-
} | {
|
|
66
|
-
readonly kind: "relation";
|
|
67
|
-
readonly relation: string;
|
|
68
|
-
readonly inverse?: CreateRequirementEdge;
|
|
69
|
-
};
|
|
70
|
-
/**
|
|
71
|
-
* Every Resource's create requirements, keyed by Resource. A Resource that is
|
|
72
|
-
* absent, or carries an empty list, requires nothing core can check.
|
|
73
|
-
*/
|
|
74
|
-
export type CreateRequirementTable = Readonly<Record<string, readonly CreateRequirement[]>>;
|
|
75
5
|
type Path = readonly (string | number)[];
|
|
76
6
|
/**
|
|
77
|
-
* What the Adapter stated that the check reads: its
|
|
78
|
-
*
|
|
79
|
-
* the Framework is constructed.
|
|
7
|
+
* What the Adapter stated beside its model that the check reads: its
|
|
8
|
+
* referential edges, for the fields that hold each reference. Read once when
|
|
9
|
+
* the Framework is constructed. The requirements themselves are the active
|
|
10
|
+
* Contract's.
|
|
80
11
|
*/
|
|
81
12
|
export type RecordWriteFacts = {
|
|
82
|
-
readonly requirements: CreateRequirementTable;
|
|
83
13
|
readonly references: ReferentialActionTable;
|
|
84
14
|
};
|
|
85
15
|
/** The facts an Adapter stated, read off it once; an absent table states nothing. */
|
|
86
16
|
export declare function recordWriteFactsOf(adapter: {
|
|
87
|
-
readonly createRequirements?: CreateRequirementTable;
|
|
88
17
|
readonly referentialActions?: ReferentialActionTable;
|
|
89
18
|
}): RecordWriteFacts;
|
|
90
19
|
/**
|
|
91
20
|
* The `V1000` issues for every create position in one operation's arguments
|
|
92
|
-
* that lacks a value the
|
|
21
|
+
* that lacks a value the active Contract requires — `create.*`'s `data`, `upsert`'s
|
|
93
22
|
* `create`, and every nested create under any write — and the `V1012` issues
|
|
94
23
|
* for every write record, create or update, that sets a relation and its
|
|
95
24
|
* reference both, in argument order. Empty when there are none. Total over
|
|
96
25
|
* malformed input.
|
|
97
26
|
*/
|
|
98
|
-
export declare function createRequirementIssues(contract:
|
|
27
|
+
export declare function createRequirementIssues(contract: AvContract, facts: RecordWriteFacts, request: AvOperationIdentity & {
|
|
99
28
|
readonly resource: string;
|
|
100
|
-
}, args: unknown, argumentsPath: Path): readonly
|
|
29
|
+
}, args: unknown, argumentsPath: Path): readonly AvValidationIssue[];
|
|
101
30
|
export {};
|
|
@@ -8,10 +8,6 @@ function isRecord(value) {
|
|
|
8
8
|
function written(record, key) {
|
|
9
9
|
return Object.hasOwn(record, key) && record[key] !== undefined;
|
|
10
10
|
}
|
|
11
|
-
function requirementsOf(table, resource) {
|
|
12
|
-
const listed = Object.hasOwn(table, resource) ? table[resource] : undefined;
|
|
13
|
-
return Array.isArray(listed) ? listed : [];
|
|
14
|
-
}
|
|
15
11
|
function edgesOf(table, resource) {
|
|
16
12
|
const listed = Object.hasOwn(table, resource) ? table[resource] : undefined;
|
|
17
13
|
return Array.isArray(listed) ? listed : [];
|
|
@@ -19,16 +15,6 @@ function edgesOf(table, resource) {
|
|
|
19
15
|
function referencesOf(edge) {
|
|
20
16
|
return Array.isArray(edge.references) ? edge.references : [];
|
|
21
17
|
}
|
|
22
|
-
function referenceFieldsOf(table, resource, relation) {
|
|
23
|
-
const edge = edgesOf(table, resource).find((candidate) => candidate.field === relation);
|
|
24
|
-
return edge === undefined ? [] : referencesOf(edge);
|
|
25
|
-
}
|
|
26
|
-
function storeSupplied(contract, resource, field) {
|
|
27
|
-
const found = lookupField(lookupResource(contract, resource), field);
|
|
28
|
-
return (found?.kind === "scalar" &&
|
|
29
|
-
(found.lifecycle.includes("DEFAULTED") ||
|
|
30
|
-
found.lifecycle.includes("GENERATED_ON_CREATE")));
|
|
31
|
-
}
|
|
32
18
|
function creatableScalar(contract, resource, field) {
|
|
33
19
|
const found = lookupField(lookupResource(contract, resource), field);
|
|
34
20
|
return found?.kind === "scalar" && found.capabilities.create !== undefined;
|
|
@@ -38,6 +24,41 @@ function creatableRelation(contract, resource, relation, scope) {
|
|
|
38
24
|
return (found?.kind === "relation" &&
|
|
39
25
|
advertisedDirectivesAt(found.capabilities.create, scope) !== undefined);
|
|
40
26
|
}
|
|
27
|
+
function blockedByPosition(contract, resource, relation, scope) {
|
|
28
|
+
return (scope !== NESTED_WRITE_SCOPE &&
|
|
29
|
+
creatableRelation(contract, resource, relation, NESTED_WRITE_SCOPE) &&
|
|
30
|
+
!creatableRelation(contract, resource, relation, scope));
|
|
31
|
+
}
|
|
32
|
+
function requirementsOf(contract, resource) {
|
|
33
|
+
const found = lookupResource(contract, resource)?.createRequirements;
|
|
34
|
+
return isRecord(found) ? found : undefined;
|
|
35
|
+
}
|
|
36
|
+
function namesOf(value) {
|
|
37
|
+
return Array.isArray(value)
|
|
38
|
+
? value.filter((name) => typeof name === "string")
|
|
39
|
+
: [];
|
|
40
|
+
}
|
|
41
|
+
function suppliedThrough(requirements, via) {
|
|
42
|
+
if (via === undefined || !isRecord(requirements.parentSupplies)) {
|
|
43
|
+
return new Set();
|
|
44
|
+
}
|
|
45
|
+
const byRelation = Object.hasOwn(requirements.parentSupplies, via.resource)
|
|
46
|
+
? requirements.parentSupplies[via.resource]
|
|
47
|
+
: undefined;
|
|
48
|
+
if (!isRecord(byRelation) || !Object.hasOwn(byRelation, via.relation)) {
|
|
49
|
+
return new Set();
|
|
50
|
+
}
|
|
51
|
+
return new Set(namesOf(byRelation[via.relation]));
|
|
52
|
+
}
|
|
53
|
+
function missingIssue(path, resource, field, relation, or = []) {
|
|
54
|
+
return {
|
|
55
|
+
code: "V1000",
|
|
56
|
+
path: [...path, field],
|
|
57
|
+
message: relation
|
|
58
|
+
? `Relation "${field}" is required to create ${resource}${or.length > 0 ? `: write it, or ${or.map((name) => `"${name}"`).join(" and ")}` : ""}.`
|
|
59
|
+
: `Field "${field}" is required to create ${resource}.`,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
41
62
|
function checkCreateRecord(context, resource, record, path, scope, via) {
|
|
42
63
|
if (!isRecord(record)) {
|
|
43
64
|
return;
|
|
@@ -45,46 +66,52 @@ function checkCreateRecord(context, resource, record, path, scope, via) {
|
|
|
45
66
|
const { contract, issues } = context;
|
|
46
67
|
const conflicted = referenceConflicts(context, resource, record, path);
|
|
47
68
|
mixedReferenceWrites(context, resource, record, path, conflicted);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
69
|
+
const requirements = requirementsOf(contract, resource);
|
|
70
|
+
if (requirements !== undefined) {
|
|
71
|
+
const supplied = suppliedThrough(requirements, via);
|
|
72
|
+
for (const field of namesOf(requirements.required)) {
|
|
73
|
+
if (supplied.has(field) || written(record, field)) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (creatableScalar(contract, resource, field)) {
|
|
77
|
+
issues.push(missingIssue(path, resource, field, false));
|
|
78
|
+
}
|
|
79
|
+
else if (!conflicted.has(field) &&
|
|
80
|
+
creatableRelation(contract, resource, field, scope)) {
|
|
81
|
+
issues.push(missingIssue(path, resource, field, true));
|
|
82
|
+
}
|
|
83
|
+
else if (blockedByPosition(contract, resource, field, scope)) {
|
|
84
|
+
const edge = edgesOf(context.references, resource).find((candidate) => candidate.field === field);
|
|
85
|
+
const references = edge === undefined ? [] : referencesOf(edge);
|
|
86
|
+
if (!references.some((name) => written(record, name))) {
|
|
87
|
+
issues.push(missingIssue(path, resource, references[0] ?? field, false));
|
|
88
|
+
}
|
|
57
89
|
}
|
|
58
|
-
continue;
|
|
59
|
-
}
|
|
60
|
-
if (conflicted.has(requirement.relation)) {
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
if (via !== undefined &&
|
|
64
|
-
requirement.inverse?.resource === via.resource &&
|
|
65
|
-
requirement.inverse.relation === via.relation) {
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
const orFields = referenceFieldsOf(context.references, resource, requirement.relation).filter((field) => !storeSupplied(contract, resource, field));
|
|
69
|
-
if (written(record, requirement.relation) ||
|
|
70
|
-
(orFields.length > 0 && orFields.every((field) => written(record, field)))) {
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
if (creatableRelation(contract, resource, requirement.relation, scope)) {
|
|
74
|
-
issues.push({
|
|
75
|
-
code: "V1000",
|
|
76
|
-
path: [...path, requirement.relation],
|
|
77
|
-
message: `Relation "${requirement.relation}" is required to create ${resource}${orFields.length > 0 ? `: write it, or ${orFields.map((field) => `"${field}"`).join(" and ")}` : ""}.`,
|
|
78
|
-
});
|
|
79
|
-
continue;
|
|
80
90
|
}
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
91
|
+
const groups = Array.isArray(requirements.oneOf) ? requirements.oneOf : [];
|
|
92
|
+
for (const group of groups) {
|
|
93
|
+
const [relation, ...references] = namesOf(group);
|
|
94
|
+
if (relation === undefined ||
|
|
95
|
+
references.length === 0 ||
|
|
96
|
+
conflicted.has(relation) ||
|
|
97
|
+
supplied.has(relation) ||
|
|
98
|
+
references.some((field) => supplied.has(field)) ||
|
|
99
|
+
written(record, relation) ||
|
|
100
|
+
references.every((field) => written(record, field))) {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (creatableRelation(contract, resource, relation, scope)) {
|
|
104
|
+
issues.push(missingIssue(path, resource, relation, true, references));
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const missing = references.find((field) => !written(record, field) &&
|
|
108
|
+
creatableScalar(contract, resource, field)) ??
|
|
109
|
+
(blockedByPosition(contract, resource, relation, scope)
|
|
110
|
+
? references.find((field) => !written(record, field))
|
|
111
|
+
: undefined);
|
|
112
|
+
if (missing !== undefined) {
|
|
113
|
+
issues.push(missingIssue(path, resource, missing, false));
|
|
114
|
+
}
|
|
88
115
|
}
|
|
89
116
|
}
|
|
90
117
|
walkNestedCreates(context, resource, record, path);
|
|
@@ -177,10 +204,7 @@ function walkNestedCreates(context, resource, record, path) {
|
|
|
177
204
|
}
|
|
178
205
|
}
|
|
179
206
|
export function recordWriteFactsOf(adapter) {
|
|
180
|
-
return {
|
|
181
|
-
requirements: adapter.createRequirements ?? {},
|
|
182
|
-
references: adapter.referentialActions ?? {},
|
|
183
|
-
};
|
|
207
|
+
return { references: adapter.referentialActions ?? {} };
|
|
184
208
|
}
|
|
185
209
|
export function createRequirementIssues(contract, facts, request, args, argumentsPath) {
|
|
186
210
|
if (!isRecord(args)) {
|
|
@@ -188,7 +212,6 @@ export function createRequirementIssues(contract, facts, request, args, argument
|
|
|
188
212
|
}
|
|
189
213
|
const context = {
|
|
190
214
|
contract,
|
|
191
|
-
requirements: facts.requirements,
|
|
192
215
|
references: facts.references,
|
|
193
216
|
issues: [],
|
|
194
217
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* An exact decimal value, independent of any database driver's decimal class.
|
|
3
|
-
* Results carry `decimal` fields as `
|
|
3
|
+
* Results carry `decimal` fields as `AvDecimal`.
|
|
4
4
|
*/
|
|
5
|
-
export declare class
|
|
5
|
+
export declare class AvDecimal {
|
|
6
6
|
#private;
|
|
7
7
|
constructor(value: string);
|
|
8
8
|
toString(): string;
|
package/dist/runtime/decimal.js
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { AvRequestOrigin } from "../config/config-layer.js";
|
|
2
|
+
import type { AvOperationFamily } from "../operations/operation-identity.js";
|
|
3
3
|
import type { FrameworkTransactionRequest } from "../transactions/transaction-request.js";
|
|
4
4
|
import type { FrameworkOperationRequest } from "./operation-request.js";
|
|
5
|
-
import type
|
|
5
|
+
import { type AvOperationErrorCode, type AvOperationFailureResponse } from "./operation-response.js";
|
|
6
6
|
/**
|
|
7
7
|
* One unplanned failure of an operation: the raw error, the code the caller
|
|
8
|
-
* received, and the operation and request it happened in
|
|
9
|
-
* deliberate internal failure, marked `deliberate`. Server-side only:
|
|
8
|
+
* received, and the operation and request it happened in. It can also be a
|
|
9
|
+
* developer's deliberate internal failure, marked `deliberate`. Server-side only:
|
|
10
10
|
* diagnostics are never sent to the caller.
|
|
11
11
|
*/
|
|
12
|
-
export type
|
|
12
|
+
export type AvOperationDiagnostic = {
|
|
13
13
|
readonly kind: "operation";
|
|
14
14
|
readonly error: unknown;
|
|
15
|
-
readonly code:
|
|
16
|
-
readonly origin:
|
|
15
|
+
readonly code: AvOperationErrorCode;
|
|
16
|
+
readonly origin: AvRequestOrigin;
|
|
17
17
|
readonly resource: string;
|
|
18
|
-
readonly family:
|
|
18
|
+
readonly family: AvOperationFamily;
|
|
19
19
|
readonly variant: string;
|
|
20
20
|
readonly requestId: string;
|
|
21
21
|
readonly operation?: number;
|
|
22
22
|
/**
|
|
23
|
-
* `true` when `error` is
|
|
24
|
-
* callback, a
|
|
23
|
+
* `true` when `error` is an `AvError` its thrower (a pipeline
|
|
24
|
+
* callback, a compute stage, a filter or an Adapter) raised deliberately with an
|
|
25
25
|
* internal (`A3xxx`) code: the developer's own failure, whose message and
|
|
26
26
|
* issues the caller never receives. Absent for a failure the framework did not
|
|
27
27
|
* expect.
|
|
@@ -32,48 +32,74 @@ export type OperationDiagnostic = {
|
|
|
32
32
|
* One unplanned failure of a transaction: the raw error, the code the caller
|
|
33
33
|
* received, and the step it is blamed on (`operation`) when there is one.
|
|
34
34
|
*/
|
|
35
|
-
export type
|
|
35
|
+
export type AvTransactionDiagnostic = {
|
|
36
36
|
readonly kind: "transaction";
|
|
37
37
|
readonly error: unknown;
|
|
38
|
-
readonly code:
|
|
39
|
-
readonly origin:
|
|
38
|
+
readonly code: AvOperationErrorCode;
|
|
39
|
+
readonly origin: AvRequestOrigin;
|
|
40
40
|
readonly requestId: string;
|
|
41
41
|
readonly operation?: number;
|
|
42
42
|
/**
|
|
43
43
|
* Never present: only an operation diagnostic is marked `deliberate`. Declared
|
|
44
|
-
* so the mark can be read on any {@link
|
|
44
|
+
* so the mark can be read on any {@link AvDiagnostic}.
|
|
45
45
|
*/
|
|
46
46
|
readonly deliberate?: never;
|
|
47
47
|
};
|
|
48
|
-
/**
|
|
49
|
-
|
|
48
|
+
/**
|
|
49
|
+
* One unplanned failure of the MCP endpoint itself, outside any tool call's
|
|
50
|
+
* operation: the raw error, answered `500` with no detail.
|
|
51
|
+
*/
|
|
52
|
+
export type AvMcpDiagnostic = {
|
|
53
|
+
readonly kind: "mcp";
|
|
54
|
+
readonly error: unknown;
|
|
55
|
+
/** Always `A3000`: an internal failure, with nothing more specific to say. */
|
|
56
|
+
readonly code: "A3000";
|
|
57
|
+
readonly origin: "agent";
|
|
58
|
+
/** Minted for the report: the MCP request carries no Aventara request id. */
|
|
59
|
+
readonly requestId: string;
|
|
60
|
+
/** Never present: no operation of a plan is involved. */
|
|
61
|
+
readonly operation?: never;
|
|
62
|
+
/** Never present: only an operation diagnostic is marked `deliberate`. */
|
|
63
|
+
readonly deliberate?: never;
|
|
64
|
+
};
|
|
65
|
+
/** One diagnostic: of an operation, of a transaction as a whole, or of the MCP endpoint. */
|
|
66
|
+
export type AvDiagnostic = AvOperationDiagnostic | AvTransactionDiagnostic | AvMcpDiagnostic;
|
|
50
67
|
/**
|
|
51
68
|
* Receives a diagnostic for every unplanned failure. Set once, as the root
|
|
52
69
|
* configuration's `diagnostics`.
|
|
53
70
|
*/
|
|
54
|
-
export type
|
|
71
|
+
export type AvDiagnosticsSink = (diagnostic: AvDiagnostic) => void | Promise<void>;
|
|
55
72
|
/**
|
|
56
73
|
* The channel as the runtime holds it: bound to one request, told the raw
|
|
57
74
|
* error and the code being emitted. Total by construction — it returns
|
|
58
75
|
* before the sink has finished and swallows everything the sink does.
|
|
59
76
|
*/
|
|
60
|
-
export type DiagnosticsReporter = (error: unknown, code:
|
|
77
|
+
export type DiagnosticsReporter = (error: unknown, code: AvOperationErrorCode, marks?: DiagnosticMarks) => void;
|
|
61
78
|
/** What a report states about its error beyond the code: today, whether it was deliberate. */
|
|
62
|
-
export type DiagnosticMarks = Pick<
|
|
79
|
+
export type DiagnosticMarks = Pick<AvOperationDiagnostic, "deliberate">;
|
|
63
80
|
/** The identifying half of a diagnostic, captured once per request. */
|
|
64
|
-
type OperationDiagnosticIdentity = Omit<
|
|
65
|
-
type TransactionDiagnosticIdentity = Omit<
|
|
81
|
+
type OperationDiagnosticIdentity = Omit<AvOperationDiagnostic, "error" | "code">;
|
|
82
|
+
type TransactionDiagnosticIdentity = Omit<AvTransactionDiagnostic, "error" | "code">;
|
|
66
83
|
/** The diagnostics channel bound to one diagnostic identity. */
|
|
67
|
-
export declare function createReporter(sink:
|
|
84
|
+
export declare function createReporter(sink: AvDiagnosticsSink | undefined, identity: OperationDiagnosticIdentity | TransactionDiagnosticIdentity): DiagnosticsReporter;
|
|
85
|
+
/**
|
|
86
|
+
* The MCP endpoint's failure channel for `framework`: each call reports one
|
|
87
|
+
* {@link AvMcpDiagnostic} to its configured sink, under a minted request id, and
|
|
88
|
+
* answers the response the caller receives instead: the generic `A3000`, which
|
|
89
|
+
* carries nothing of the error. Total: it returns before the sink has finished
|
|
90
|
+
* and swallows everything the sink does. A Framework without a sink gets a
|
|
91
|
+
* channel that observes nothing and still answers the `A3000`.
|
|
92
|
+
*/
|
|
93
|
+
export declare function mcpFailureReporterOf(framework: object): (error: unknown) => AvOperationFailureResponse;
|
|
68
94
|
/** Records the sink `framework` was configured with; called once, at construction. */
|
|
69
|
-
export declare function recordDiagnosticsSink(framework: object, sink:
|
|
95
|
+
export declare function recordDiagnosticsSink(framework: object, sink: AvDiagnosticsSink | undefined): void;
|
|
70
96
|
/** The sink `framework` was configured with, or `undefined` for none. */
|
|
71
|
-
export declare function diagnosticsSinkOf(framework: object):
|
|
97
|
+
export declare function diagnosticsSinkOf(framework: object): AvDiagnosticsSink | undefined;
|
|
72
98
|
/**
|
|
73
99
|
* Binds the configured sink to one operation request. The sink is not awaited,
|
|
74
100
|
* and nothing it throws or rejects with reaches the response.
|
|
75
101
|
*/
|
|
76
|
-
export declare function createDiagnosticsReporter(sink:
|
|
102
|
+
export declare function createDiagnosticsReporter(sink: AvDiagnosticsSink | undefined, request: FrameworkOperationRequest, operation?: number): DiagnosticsReporter;
|
|
77
103
|
/** The diagnostics channel of one transaction request. */
|
|
78
104
|
export type TransactionDiagnosticsChannel = {
|
|
79
105
|
/** A plan-level report; `operation` attributes it to a recorded failing index. */
|
|
@@ -82,5 +108,5 @@ export type TransactionDiagnosticsChannel = {
|
|
|
82
108
|
readonly operation: (request: FrameworkOperationRequest, operation: number) => DiagnosticsReporter;
|
|
83
109
|
};
|
|
84
110
|
/** Binds the configured sink to one transaction request and its plan operations. */
|
|
85
|
-
export declare function createTransactionDiagnosticsChannel(sink:
|
|
111
|
+
export declare function createTransactionDiagnosticsChannel(sink: AvDiagnosticsSink | undefined, request: FrameworkTransactionRequest): TransactionDiagnosticsChannel;
|
|
86
112
|
export {};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { internalFailure, } from "./operation-response.js";
|
|
2
|
+
import { requestIdOf } from "./request-id.js";
|
|
1
3
|
const IGNORE_DIAGNOSTIC = () => undefined;
|
|
2
4
|
function isThenable(value) {
|
|
3
5
|
if ((typeof value !== "object" || value === null) &&
|
|
@@ -30,6 +32,28 @@ export function createReporter(sink, identity) {
|
|
|
30
32
|
};
|
|
31
33
|
}
|
|
32
34
|
const CONFIGURED_SINKS = new WeakMap();
|
|
35
|
+
export function mcpFailureReporterOf(framework) {
|
|
36
|
+
const sink = CONFIGURED_SINKS.get(framework);
|
|
37
|
+
return (error) => {
|
|
38
|
+
if (sink !== undefined) {
|
|
39
|
+
try {
|
|
40
|
+
const settled = sink({
|
|
41
|
+
kind: "mcp",
|
|
42
|
+
error,
|
|
43
|
+
code: "A3000",
|
|
44
|
+
origin: "agent",
|
|
45
|
+
requestId: requestIdOf(undefined),
|
|
46
|
+
});
|
|
47
|
+
if (isThenable(settled)) {
|
|
48
|
+
settled.then(undefined, () => undefined);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return internalFailure();
|
|
55
|
+
};
|
|
56
|
+
}
|
|
33
57
|
export function recordDiagnosticsSink(framework, sink) {
|
|
34
58
|
if (sink !== undefined) {
|
|
35
59
|
CONFIGURED_SINKS.set(framework, sink);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { DiagnosticsReporter } from "./diagnostics-reporter.js";
|
|
2
|
-
import
|
|
3
|
-
import type {
|
|
2
|
+
import { AvError } from "./framework-error.js";
|
|
3
|
+
import type { AvCause, AvOperationErrorCode, AvOperationFailureResponse } from "./operation-response.js";
|
|
4
|
+
import type { AvContext } from "./pipeline.js";
|
|
4
5
|
/** Where an unexpected post-validation exception originated. */
|
|
5
6
|
export type FailureOrigin = "adapter" | "runtime";
|
|
6
7
|
/** The one generic Adapter-failure text; every unexpected A3001 carries it. */
|
|
@@ -39,18 +40,74 @@ export type CallerArgumentsView = {
|
|
|
39
40
|
* framework's text for its code and reported to the diagnostics channel.
|
|
40
41
|
*/
|
|
41
42
|
export declare const MAX_DEVELOPER_ISSUE_MESSAGE_LENGTH = 1000;
|
|
43
|
+
/** The stable outcome a thrower chose, once the boundary has vetted it. */
|
|
44
|
+
type DeliberateOutcome = {
|
|
45
|
+
readonly code: AvOperationErrorCode;
|
|
46
|
+
readonly cause: AvCause;
|
|
47
|
+
/**
|
|
48
|
+
* Every issue code, issue path and developer issue message the boundary could
|
|
49
|
+
* not vouch for, raw and in supplied order.
|
|
50
|
+
*/
|
|
51
|
+
readonly unvouched: readonly unknown[];
|
|
52
|
+
};
|
|
42
53
|
/**
|
|
43
54
|
* Final framework sanitization, shared by every boundary. A deliberate
|
|
44
|
-
* {@link
|
|
55
|
+
* {@link AvError} carries its own stable outcome; anything else is
|
|
45
56
|
* replaced by a generic cause so no provider text, stack, path, or secret
|
|
46
57
|
* can cross the response boundary. Total: it never throws.
|
|
47
58
|
*/
|
|
48
|
-
export declare function sanitizeOperationFailure(error: unknown, origin: FailureOrigin, report: DiagnosticsReporter, view: CallerArgumentsView):
|
|
59
|
+
export declare function sanitizeOperationFailure(error: unknown, origin: FailureOrigin, report: DiagnosticsReporter, view: CallerArgumentsView): AvOperationFailureResponse;
|
|
60
|
+
/**
|
|
61
|
+
* A filter over the context its stage is told: an operation's `AvFilter`,
|
|
62
|
+
* or a Resource transaction filter, whose context is the plan.
|
|
63
|
+
*/
|
|
64
|
+
type FilterOf<Context> = (error: unknown, context: Context) => AvError | undefined | Promise<AvError | undefined>;
|
|
49
65
|
/**
|
|
50
66
|
* Post-validation exception flow: effective filters are stored as `[root...,
|
|
51
67
|
* scoped...]`, so reverse iteration tries scoped filters in reverse registration
|
|
52
|
-
* order, then root filters in reverse
|
|
53
|
-
*
|
|
54
|
-
*
|
|
68
|
+
* order, then root filters in reverse. An error they leave unhandled goes to
|
|
69
|
+
* `outer` when there is one (a transaction step's: its Resource transaction
|
|
70
|
+
* filters, run once the transaction interceptors have unwound), else to final
|
|
71
|
+
* sanitization. A filter handles an error only by returning a {@link AvError};
|
|
72
|
+
* returning `undefined` or throwing leaves the original error unhandled.
|
|
73
|
+
*/
|
|
74
|
+
export declare function resolveOperationFailure<Context = AvContext>(error: unknown, filters: readonly FilterOf<Context>[], context: Context, boundary: AdapterBoundary, report: DiagnosticsReporter, view: CallerArgumentsView, outer?: OuterFailureLayer): Promise<AvOperationFailureResponse>;
|
|
75
|
+
/**
|
|
76
|
+
* An error a step's own filters left unhandled, with what answering it later
|
|
77
|
+
* needs: the caller's arguments as the step held them, the step's Adapter
|
|
78
|
+
* boundary (whose identity says whose words the error is) and its reporter.
|
|
79
|
+
*/
|
|
80
|
+
export type UnhandledFailure = {
|
|
81
|
+
readonly error: unknown;
|
|
82
|
+
readonly view: CallerArgumentsView;
|
|
83
|
+
readonly boundary: AdapterBoundary;
|
|
84
|
+
readonly report: DiagnosticsReporter;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Where a transaction step hands an error its own filters left unhandled. It
|
|
88
|
+
* records the error and answers a provisional failure, which fails the step; the
|
|
89
|
+
* transaction replaces it with the transaction filters' answer.
|
|
55
90
|
*/
|
|
56
|
-
export
|
|
91
|
+
export type OuterFailureLayer = {
|
|
92
|
+
readonly defer: (failure: UnhandledFailure) => AvOperationFailureResponse;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* An unhandled step error through `chain` (the transaction filters, the first
|
|
96
|
+
* that handles it wins), then final sanitization.
|
|
97
|
+
*/
|
|
98
|
+
export declare function resolveUnhandledFailure(failure: UnhandledFailure, chain: FilterChain): Promise<AvOperationFailureResponse>;
|
|
99
|
+
/**
|
|
100
|
+
* A chain of filters and the context they are told, tried in reverse: the first
|
|
101
|
+
* that returns an {@link AvError} handles the error.
|
|
102
|
+
*/
|
|
103
|
+
export type FilterChain = {
|
|
104
|
+
readonly attempt: (error: unknown, view: CallerArgumentsView, boundary: AdapterBoundary) => Promise<FilteredOutcome | undefined>;
|
|
105
|
+
};
|
|
106
|
+
/** The chain of `filters` (stored outer to inner, tried in reverse), told `context`. */
|
|
107
|
+
export declare function filterChain<Context>(filters: readonly FilterOf<Context>[], context: Context): FilterChain;
|
|
108
|
+
/** What a filter returned, and the deliberate outcome it vets as. */
|
|
109
|
+
type FilteredOutcome = {
|
|
110
|
+
readonly returned: unknown;
|
|
111
|
+
readonly outcome: DeliberateOutcome;
|
|
112
|
+
};
|
|
113
|
+
export {};
|