@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,65 +1,30 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*
|
|
7
|
-
* **The facts are an Adapter's.** Which values a store cannot create a row
|
|
8
|
-
* without is a property of the store's schema — a column with no default, a
|
|
9
|
-
* reference that must point somewhere — and only the Adapter can read it. The
|
|
10
|
-
* words are Aventara's, so an Adapter translates its provider's facts into them,
|
|
11
|
-
* and the reasoning over them is core's, so no Adapter re-implements it.
|
|
12
|
-
*
|
|
13
|
-
* None of this enters a Contract. A Contract carries no foreign-key detail and
|
|
14
|
-
* no knowledge of which relation is the other end of which, and a requirement
|
|
15
|
-
* needs both; it is a server-side fact, read once when the Framework is
|
|
16
|
-
* constructed, like the referential actions.
|
|
17
|
-
*
|
|
18
|
-
* **When the check runs.** After guards, pipes and computed write behaviours —
|
|
19
|
-
* the moment the arguments are what the Adapter will be handed — and before
|
|
20
|
-
* any `before` hook or Adapter work. Earlier would refuse a value a pipe or a
|
|
21
|
-
* computed behaviour was about to supply; later is the store's own refusal,
|
|
22
|
-
* which reaches the caller as an internal failure. A missing value is the
|
|
23
|
-
* caller's to fix, so it answers `A2004` with a `V1000` issue at the path where
|
|
24
|
-
* the value belongs.
|
|
25
|
-
*/
|
|
26
|
-
/** A relation edge, named by the Resource that holds it and its field there. */
|
|
27
|
-
export type CreateRequirementEdge = {
|
|
28
|
-
readonly resource: string;
|
|
29
|
-
readonly relation: string;
|
|
30
|
-
};
|
|
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
|
+
import type { ReferentialActionTable } from "./referential-action.js";
|
|
5
|
+
type Path = readonly (string | number)[];
|
|
31
6
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* - `relation` — a required to-one relation: it must be written (connected or
|
|
37
|
-
* created), or every one of `orFields` must be — the scalar fields that hold
|
|
38
|
-
* the reference. When the row is created **through** the relation's other end
|
|
39
|
-
* (`inverse`), the parent supplies it, and it is not required.
|
|
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.
|
|
40
11
|
*/
|
|
41
|
-
export type
|
|
42
|
-
readonly
|
|
43
|
-
readonly field: string;
|
|
44
|
-
} | {
|
|
45
|
-
readonly kind: "relation";
|
|
46
|
-
readonly relation: string;
|
|
47
|
-
readonly orFields: readonly string[];
|
|
48
|
-
readonly inverse?: CreateRequirementEdge;
|
|
12
|
+
export type RecordWriteFacts = {
|
|
13
|
+
readonly references: ReferentialActionTable;
|
|
49
14
|
};
|
|
50
|
-
/**
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
export type CreateRequirementTable = Readonly<Record<string, readonly CreateRequirement[]>>;
|
|
55
|
-
type Path = readonly (string | number)[];
|
|
15
|
+
/** The facts an Adapter stated, read off it once; an absent table states nothing. */
|
|
16
|
+
export declare function recordWriteFactsOf(adapter: {
|
|
17
|
+
readonly referentialActions?: ReferentialActionTable;
|
|
18
|
+
}): RecordWriteFacts;
|
|
56
19
|
/**
|
|
57
20
|
* The `V1000` issues for every create position in one operation's arguments
|
|
58
|
-
* that lacks a value the
|
|
59
|
-
* `create`, and every nested create under any write —
|
|
60
|
-
*
|
|
21
|
+
* that lacks a value the active Contract requires — `create.*`'s `data`, `upsert`'s
|
|
22
|
+
* `create`, and every nested create under any write — and the `V1012` issues
|
|
23
|
+
* for every write record, create or update, that sets a relation and its
|
|
24
|
+
* reference both, in argument order. Empty when there are none. Total over
|
|
25
|
+
* malformed input.
|
|
61
26
|
*/
|
|
62
|
-
export declare function
|
|
27
|
+
export declare function createRequirementIssues(contract: AvContract, facts: RecordWriteFacts, request: AvOperationIdentity & {
|
|
63
28
|
readonly resource: string;
|
|
64
|
-
}, args: unknown, argumentsPath: Path): readonly
|
|
29
|
+
}, args: unknown, argumentsPath: Path): readonly AvValidationIssue[];
|
|
65
30
|
export {};
|
|
@@ -8,10 +8,13 @@ function isRecord(value) {
|
|
|
8
8
|
function written(record, key) {
|
|
9
9
|
return Object.hasOwn(record, key) && record[key] !== undefined;
|
|
10
10
|
}
|
|
11
|
-
function
|
|
11
|
+
function edgesOf(table, resource) {
|
|
12
12
|
const listed = Object.hasOwn(table, resource) ? table[resource] : undefined;
|
|
13
13
|
return Array.isArray(listed) ? listed : [];
|
|
14
14
|
}
|
|
15
|
+
function referencesOf(edge) {
|
|
16
|
+
return Array.isArray(edge.references) ? edge.references : [];
|
|
17
|
+
}
|
|
15
18
|
function creatableScalar(contract, resource, field) {
|
|
16
19
|
const found = lookupField(lookupResource(contract, resource), field);
|
|
17
20
|
return found?.kind === "scalar" && found.capabilities.create !== undefined;
|
|
@@ -21,52 +24,145 @@ function creatableRelation(contract, resource, relation, scope) {
|
|
|
21
24
|
return (found?.kind === "relation" &&
|
|
22
25
|
advertisedDirectivesAt(found.capabilities.create, scope) !== undefined);
|
|
23
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
|
+
}
|
|
24
62
|
function checkCreateRecord(context, resource, record, path, scope, via) {
|
|
25
63
|
if (!isRecord(record)) {
|
|
26
64
|
return;
|
|
27
65
|
}
|
|
28
66
|
const { contract, issues } = context;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
67
|
+
const conflicted = referenceConflicts(context, resource, record, path);
|
|
68
|
+
mixedReferenceWrites(context, resource, record, path, conflicted);
|
|
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
|
+
}
|
|
38
89
|
}
|
|
39
|
-
continue;
|
|
40
90
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
walkNestedCreates(context, resource, record, path);
|
|
118
|
+
}
|
|
119
|
+
function referenceConflicts(context, resource, record, path) {
|
|
120
|
+
const conflicted = new Set();
|
|
121
|
+
for (const edge of edgesOf(context.references, resource)) {
|
|
122
|
+
if (!written(record, edge.field)) {
|
|
44
123
|
continue;
|
|
45
124
|
}
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
: [];
|
|
49
|
-
if (written(record, requirement.relation) ||
|
|
50
|
-
(orFields.length > 0 && orFields.every((field) => written(record, field)))) {
|
|
125
|
+
const fields = referencesOf(edge).filter((field) => written(record, field));
|
|
126
|
+
if (fields.length === 0) {
|
|
51
127
|
continue;
|
|
52
128
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
129
|
+
conflicted.add(edge.field);
|
|
130
|
+
context.issues.push({
|
|
131
|
+
code: "V1012",
|
|
132
|
+
path: [...path, edge.field],
|
|
133
|
+
message: `Set ${fields.map((field) => `"${field}"`).join(" and ")} or "${edge.field}", not both.`,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return conflicted;
|
|
137
|
+
}
|
|
138
|
+
function mixedReferenceWrites(context, resource, record, path, conflicted) {
|
|
139
|
+
if (context.contract.referenceWrites !== "uniform") {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const edges = edgesOf(context.references, resource);
|
|
143
|
+
const referenceFields = [...new Set(edges.flatMap(referencesOf))];
|
|
144
|
+
for (const edge of edges) {
|
|
145
|
+
if (!written(record, edge.field) || conflicted.has(edge.field)) {
|
|
59
146
|
continue;
|
|
60
147
|
}
|
|
61
|
-
const
|
|
62
|
-
if (
|
|
63
|
-
|
|
64
|
-
code: "V1000",
|
|
65
|
-
path: [...path, missing],
|
|
66
|
-
message: `Field "${missing}" is required to create ${resource}.`,
|
|
67
|
-
});
|
|
148
|
+
const fields = referenceFields.filter((field) => written(record, field));
|
|
149
|
+
if (fields.length === 0) {
|
|
150
|
+
continue;
|
|
68
151
|
}
|
|
152
|
+
const named = fields.map((field) => `"${field}"`).join(" and ");
|
|
153
|
+
context.issues.push({
|
|
154
|
+
code: "V1012",
|
|
155
|
+
path: [...path, edge.field],
|
|
156
|
+
message: `Use relation fields only, or reference fields only, in one record: ${named} ${fields.length === 1 ? "is a reference field" : "are reference fields"} and "${edge.field}" is a relation.`,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function checkUpdateRecord(context, resource, record, path) {
|
|
161
|
+
if (!isRecord(record)) {
|
|
162
|
+
return;
|
|
69
163
|
}
|
|
164
|
+
const conflicted = referenceConflicts(context, resource, record, path);
|
|
165
|
+
mixedReferenceWrites(context, resource, record, path, conflicted);
|
|
70
166
|
walkNestedCreates(context, resource, record, path);
|
|
71
167
|
}
|
|
72
168
|
function walkNestedCreates(context, resource, record, path) {
|
|
@@ -100,18 +196,25 @@ function walkNestedCreates(context, resource, record, path) {
|
|
|
100
196
|
checkCreateRecord(context, field.target, siteRecord, sitePath, NESTED_WRITE_SCOPE, via);
|
|
101
197
|
}
|
|
102
198
|
else {
|
|
103
|
-
|
|
199
|
+
checkUpdateRecord(context, field.target, siteRecord, sitePath);
|
|
104
200
|
}
|
|
105
201
|
}
|
|
106
202
|
}
|
|
107
203
|
}
|
|
108
204
|
}
|
|
109
205
|
}
|
|
110
|
-
export function
|
|
206
|
+
export function recordWriteFactsOf(adapter) {
|
|
207
|
+
return { references: adapter.referentialActions ?? {} };
|
|
208
|
+
}
|
|
209
|
+
export function createRequirementIssues(contract, facts, request, args, argumentsPath) {
|
|
111
210
|
if (!isRecord(args)) {
|
|
112
211
|
return [];
|
|
113
212
|
}
|
|
114
|
-
const context = {
|
|
213
|
+
const context = {
|
|
214
|
+
contract,
|
|
215
|
+
references: facts.references,
|
|
216
|
+
issues: [],
|
|
217
|
+
};
|
|
115
218
|
const scope = resolveWriteScope(lookupResource(contract, request.resource), request);
|
|
116
219
|
if (request.family === "create" && written(args, "data")) {
|
|
117
220
|
const data = args.data;
|
|
@@ -126,13 +229,13 @@ export function missingCreateValues(contract, table, request, args, argumentsPat
|
|
|
126
229
|
}
|
|
127
230
|
if (request.family === "upsert") {
|
|
128
231
|
checkCreateRecord(context, request.resource, args.create, [...argumentsPath, "create"], scope, undefined);
|
|
129
|
-
|
|
232
|
+
checkUpdateRecord(context, request.resource, args.update, [
|
|
130
233
|
...argumentsPath,
|
|
131
234
|
"update",
|
|
132
235
|
]);
|
|
133
236
|
}
|
|
134
237
|
if (request.family === "update") {
|
|
135
|
-
|
|
238
|
+
checkUpdateRecord(context, request.resource, args.data, [
|
|
136
239
|
...argumentsPath,
|
|
137
240
|
"data",
|
|
138
241
|
]);
|
|
@@ -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,63 +1,105 @@
|
|
|
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.
|
|
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:
|
|
9
10
|
* diagnostics are never sent to the caller.
|
|
10
11
|
*/
|
|
11
|
-
export type
|
|
12
|
+
export type AvOperationDiagnostic = {
|
|
12
13
|
readonly kind: "operation";
|
|
13
14
|
readonly error: unknown;
|
|
14
|
-
readonly code:
|
|
15
|
-
readonly
|
|
15
|
+
readonly code: AvOperationErrorCode;
|
|
16
|
+
readonly origin: AvRequestOrigin;
|
|
16
17
|
readonly resource: string;
|
|
17
|
-
readonly family:
|
|
18
|
+
readonly family: AvOperationFamily;
|
|
18
19
|
readonly variant: string;
|
|
19
20
|
readonly requestId: string;
|
|
20
21
|
readonly operation?: number;
|
|
22
|
+
/**
|
|
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
|
+
* internal (`A3xxx`) code: the developer's own failure, whose message and
|
|
26
|
+
* issues the caller never receives. Absent for a failure the framework did not
|
|
27
|
+
* expect.
|
|
28
|
+
*/
|
|
29
|
+
readonly deliberate?: true;
|
|
21
30
|
};
|
|
22
31
|
/**
|
|
23
32
|
* One unplanned failure of a transaction: the raw error, the code the caller
|
|
24
33
|
* received, and the step it is blamed on (`operation`) when there is one.
|
|
25
34
|
*/
|
|
26
|
-
export type
|
|
35
|
+
export type AvTransactionDiagnostic = {
|
|
27
36
|
readonly kind: "transaction";
|
|
28
37
|
readonly error: unknown;
|
|
29
|
-
readonly code:
|
|
30
|
-
readonly
|
|
38
|
+
readonly code: AvOperationErrorCode;
|
|
39
|
+
readonly origin: AvRequestOrigin;
|
|
31
40
|
readonly requestId: string;
|
|
32
41
|
readonly operation?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Never present: only an operation diagnostic is marked `deliberate`. Declared
|
|
44
|
+
* so the mark can be read on any {@link AvDiagnostic}.
|
|
45
|
+
*/
|
|
46
|
+
readonly deliberate?: never;
|
|
33
47
|
};
|
|
34
|
-
/**
|
|
35
|
-
|
|
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;
|
|
36
67
|
/**
|
|
37
68
|
* Receives a diagnostic for every unplanned failure. Set once, as the root
|
|
38
69
|
* configuration's `diagnostics`.
|
|
39
70
|
*/
|
|
40
|
-
export type
|
|
71
|
+
export type AvDiagnosticsSink = (diagnostic: AvDiagnostic) => void | Promise<void>;
|
|
41
72
|
/**
|
|
42
73
|
* The channel as the runtime holds it: bound to one request, told the raw
|
|
43
74
|
* error and the code being emitted. Total by construction — it returns
|
|
44
75
|
* before the sink has finished and swallows everything the sink does.
|
|
45
76
|
*/
|
|
46
|
-
export type DiagnosticsReporter = (error: unknown, code:
|
|
77
|
+
export type DiagnosticsReporter = (error: unknown, code: AvOperationErrorCode, marks?: DiagnosticMarks) => void;
|
|
78
|
+
/** What a report states about its error beyond the code: today, whether it was deliberate. */
|
|
79
|
+
export type DiagnosticMarks = Pick<AvOperationDiagnostic, "deliberate">;
|
|
47
80
|
/** The identifying half of a diagnostic, captured once per request. */
|
|
48
|
-
type OperationDiagnosticIdentity = Omit<
|
|
49
|
-
type TransactionDiagnosticIdentity = Omit<
|
|
81
|
+
type OperationDiagnosticIdentity = Omit<AvOperationDiagnostic, "error" | "code">;
|
|
82
|
+
type TransactionDiagnosticIdentity = Omit<AvTransactionDiagnostic, "error" | "code">;
|
|
50
83
|
/** The diagnostics channel bound to one diagnostic identity. */
|
|
51
|
-
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;
|
|
52
94
|
/** Records the sink `framework` was configured with; called once, at construction. */
|
|
53
|
-
export declare function recordDiagnosticsSink(framework: object, sink:
|
|
95
|
+
export declare function recordDiagnosticsSink(framework: object, sink: AvDiagnosticsSink | undefined): void;
|
|
54
96
|
/** The sink `framework` was configured with, or `undefined` for none. */
|
|
55
|
-
export declare function diagnosticsSinkOf(framework: object):
|
|
97
|
+
export declare function diagnosticsSinkOf(framework: object): AvDiagnosticsSink | undefined;
|
|
56
98
|
/**
|
|
57
99
|
* Binds the configured sink to one operation request. The sink is not awaited,
|
|
58
100
|
* and nothing it throws or rejects with reaches the response.
|
|
59
101
|
*/
|
|
60
|
-
export declare function createDiagnosticsReporter(sink:
|
|
102
|
+
export declare function createDiagnosticsReporter(sink: AvDiagnosticsSink | undefined, request: FrameworkOperationRequest, operation?: number): DiagnosticsReporter;
|
|
61
103
|
/** The diagnostics channel of one transaction request. */
|
|
62
104
|
export type TransactionDiagnosticsChannel = {
|
|
63
105
|
/** A plan-level report; `operation` attributes it to a recorded failing index. */
|
|
@@ -66,5 +108,5 @@ export type TransactionDiagnosticsChannel = {
|
|
|
66
108
|
readonly operation: (request: FrameworkOperationRequest, operation: number) => DiagnosticsReporter;
|
|
67
109
|
};
|
|
68
110
|
/** Binds the configured sink to one transaction request and its plan operations. */
|
|
69
|
-
export declare function createTransactionDiagnosticsChannel(sink:
|
|
111
|
+
export declare function createTransactionDiagnosticsChannel(sink: AvDiagnosticsSink | undefined, request: FrameworkTransactionRequest): TransactionDiagnosticsChannel;
|
|
70
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) &&
|
|
@@ -10,9 +12,16 @@ export function createReporter(sink, identity) {
|
|
|
10
12
|
if (sink === undefined) {
|
|
11
13
|
return IGNORE_DIAGNOSTIC;
|
|
12
14
|
}
|
|
13
|
-
return (error, code) => {
|
|
15
|
+
return (error, code, marks) => {
|
|
14
16
|
try {
|
|
15
|
-
const settled = sink(
|
|
17
|
+
const settled = sink(identity.kind === "operation"
|
|
18
|
+
? {
|
|
19
|
+
...identity,
|
|
20
|
+
error,
|
|
21
|
+
code,
|
|
22
|
+
...(marks?.deliberate === true ? { deliberate: true } : {}),
|
|
23
|
+
}
|
|
24
|
+
: { ...identity, error, code });
|
|
16
25
|
if (isThenable(settled)) {
|
|
17
26
|
settled.then(undefined, () => undefined);
|
|
18
27
|
}
|
|
@@ -23,6 +32,28 @@ export function createReporter(sink, identity) {
|
|
|
23
32
|
};
|
|
24
33
|
}
|
|
25
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
|
+
}
|
|
26
57
|
export function recordDiagnosticsSink(framework, sink) {
|
|
27
58
|
if (sink !== undefined) {
|
|
28
59
|
CONFIGURED_SINKS.set(framework, sink);
|
|
@@ -36,7 +67,7 @@ export function createDiagnosticsReporter(sink, request, operation) {
|
|
|
36
67
|
try {
|
|
37
68
|
identity = {
|
|
38
69
|
kind: "operation",
|
|
39
|
-
|
|
70
|
+
origin: request.origin,
|
|
40
71
|
resource: request.resource,
|
|
41
72
|
family: request.family,
|
|
42
73
|
variant: request.variant,
|
|
@@ -54,7 +85,7 @@ export function createTransactionDiagnosticsChannel(sink, request) {
|
|
|
54
85
|
try {
|
|
55
86
|
identity = {
|
|
56
87
|
kind: "transaction",
|
|
57
|
-
|
|
88
|
+
origin: request.origin,
|
|
58
89
|
requestId: request.requestId,
|
|
59
90
|
};
|
|
60
91
|
}
|
|
@@ -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. */
|
|
@@ -20,6 +21,8 @@ export declare class AdapterBoundary {
|
|
|
20
21
|
export declare const SERIALIZATION_FAILURE_MESSAGE = "Result serialization failed.";
|
|
21
22
|
/** Where a standalone operation's arguments sit in a framework issue path. */
|
|
22
23
|
export declare const OPERATION_ARGUMENTS_PATH: readonly (string | number)[];
|
|
24
|
+
/** Where one plan step sits in a framework issue path: its node in the request. */
|
|
25
|
+
export declare function planStepPath(index: number): readonly (string | number)[];
|
|
23
26
|
/** Where one plan operation's arguments sit in a framework issue path. */
|
|
24
27
|
export declare function planOperationArgumentsPath(index: number): readonly (string | number)[];
|
|
25
28
|
/**
|
|
@@ -31,18 +34,80 @@ export type CallerArgumentsView = {
|
|
|
31
34
|
readonly path: readonly (string | number)[];
|
|
32
35
|
readonly arguments: unknown;
|
|
33
36
|
};
|
|
37
|
+
/**
|
|
38
|
+
* The longest issue message a developer's code may send to the caller, in UTF-16
|
|
39
|
+
* code units. A longer one, or one with no visible character, is replaced by the
|
|
40
|
+
* framework's text for its code and reported to the diagnostics channel.
|
|
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
|
+
};
|
|
34
53
|
/**
|
|
35
54
|
* Final framework sanitization, shared by every boundary. A deliberate
|
|
36
|
-
* {@link
|
|
55
|
+
* {@link AvError} carries its own stable outcome; anything else is
|
|
37
56
|
* replaced by a generic cause so no provider text, stack, path, or secret
|
|
38
57
|
* can cross the response boundary. Total: it never throws.
|
|
39
58
|
*/
|
|
40
|
-
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>;
|
|
41
65
|
/**
|
|
42
66
|
* Post-validation exception flow: effective filters are stored as `[root...,
|
|
43
67
|
* scoped...]`, so reverse iteration tries scoped filters in reverse registration
|
|
44
|
-
* order, then root filters in reverse
|
|
45
|
-
*
|
|
46
|
-
*
|
|
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.
|
|
47
73
|
*/
|
|
48
|
-
export declare function resolveOperationFailure(error: unknown, filters: readonly
|
|
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.
|
|
90
|
+
*/
|
|
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 {};
|