@aventara/core 0.1.0-pilot.1 → 0.1.0-pilot.2
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/dist/adapters/adapter-field.d.ts +4 -4
- package/dist/adapters/adapter-resource.d.ts +10 -12
- package/dist/adapters/adapter.interface.d.ts +20 -10
- package/dist/compiler/contract-compiler-diagnostic.d.ts +3 -4
- package/dist/compiler/contract.compiler.d.ts +5 -4
- package/dist/compiler/contract.compiler.js +0 -132
- package/dist/config/config.resolver.d.ts +2 -2
- package/dist/config/config.resolver.js +0 -5
- package/dist/config/config.validator.d.ts +3 -3
- package/dist/config/config.validator.js +0 -8
- package/dist/config/define-fields.d.ts +2 -7
- package/dist/config/define-fields.js +0 -15
- package/dist/config/effective-fields.d.ts +4 -8
- package/dist/config/entrypoint.normalizer.d.ts +7 -7
- package/dist/config/entrypoint.normalizer.js +0 -22
- package/dist/config/framework-behaviors-config.d.ts +6 -6
- package/dist/config/framework-config.d.ts +3 -5
- package/dist/config/framework-restrictions-config.d.ts +19 -29
- package/dist/config/pipeline-config.d.ts +8 -18
- package/dist/contracts/capability.d.ts +18 -21
- package/dist/contracts/capability.js +0 -75
- package/dist/contracts/client-contract-structure.validator.d.ts +15 -22
- package/dist/contracts/client-contract-structure.validator.js +0 -27
- package/dist/contracts/contract-canonicalizer.js +0 -96
- package/dist/contracts/contract-hash.js +0 -2
- package/dist/contracts/contract-limits.js +0 -1
- package/dist/contracts/contract-lookup.js +0 -10
- package/dist/contracts/contract-protocol.js +0 -10
- package/dist/contracts/field.d.ts +23 -26
- package/dist/contracts/field.js +0 -107
- package/dist/contracts/lifecycle-trait.js +0 -5
- package/dist/contracts/resource-operations.d.ts +17 -18
- package/dist/contracts/resource-operations.js +0 -63
- package/dist/contracts/scalar-value-type.d.ts +12 -22
- package/dist/contracts/scalar.js +0 -1
- package/dist/contracts/wire-scalar-format.d.ts +20 -20
- package/dist/contracts/wire-scalar-format.js +0 -26
- package/dist/framework/contract-view.d.ts +7 -8
- package/dist/framework/framework-construction.error.js +0 -1
- package/dist/framework/framework.d.ts +26 -27
- package/dist/framework/framework.factory.js +0 -49
- package/dist/framework/operation-facade.js +0 -17
- package/dist/operations/operation-arguments.d.ts +36 -46
- package/dist/operations/operation-boolean-nodes.js +0 -16
- package/dist/operations/operation-call.d.ts +4 -9
- package/dist/operations/operation-identity.js +0 -1
- package/dist/operations/operation-nesting.js +0 -5
- package/dist/operations/operation-result.d.ts +4 -4
- package/dist/operations/operation-validator-core.d.ts +2 -2
- package/dist/operations/operation-validator-core.js +6 -71
- package/dist/operations/operation-validator.d.ts +4 -4
- package/dist/operations/operation-validator.js +0 -12
- package/dist/operations/projection-scope.resolver.d.ts +8 -10
- package/dist/operations/projection-scope.resolver.js +0 -35
- package/dist/operations/validation-code.d.ts +11 -18
- package/dist/operations/validation-code.js +0 -24
- package/dist/operations/write-scope.resolver.d.ts +4 -7
- package/dist/operations/write-scope.resolver.js +0 -37
- package/dist/protocol/absent-route.responder.d.ts +33 -48
- package/dist/protocol/absent-route.responder.js +0 -55
- package/dist/protocol/av-protocol.d.ts +6 -6
- package/dist/protocol/av-protocol.js +0 -10
- package/dist/protocol/contract-document.responder.d.ts +15 -18
- package/dist/protocol/contract-document.responder.js +0 -33
- package/dist/protocol/http-request.decoder.d.ts +55 -61
- package/dist/protocol/http-request.decoder.js +0 -62
- package/dist/protocol/http-request.reader.d.ts +12 -13
- package/dist/protocol/http-request.reader.js +0 -45
- package/dist/protocol/http-response.encoder.d.ts +17 -18
- package/dist/protocol/http-response.encoder.js +0 -59
- package/dist/protocol/http-status.table.d.ts +7 -11
- package/dist/protocol/http-status.table.js +1 -15
- package/dist/protocol/index.d.ts +5 -5
- package/dist/protocol/index.js +0 -9
- package/dist/protocol/operation-response.guard.d.ts +12 -19
- package/dist/protocol/operation-response.guard.js +0 -29
- package/dist/protocol/protocol-failure.d.ts +21 -26
- package/dist/protocol/protocol-failure.js +0 -12
- package/dist/protocol/protocol-headers.d.ts +25 -30
- package/dist/protocol/protocol-headers.js +0 -66
- package/dist/protocol/protocol-surface.d.ts +25 -29
- package/dist/protocol/protocol-surface.js +0 -19
- package/dist/protocol/protocol.binder.d.ts +58 -71
- package/dist/protocol/protocol.binder.js +0 -8
- package/dist/protocol/protocol.handler.d.ts +28 -32
- package/dist/protocol/protocol.handler.js +0 -43
- package/dist/runtime/computed-read-runtime.js +0 -29
- package/dist/runtime/create-requirement.d.ts +65 -0
- package/dist/runtime/create-requirement.js +141 -0
- package/dist/runtime/decimal.d.ts +2 -2
- package/dist/runtime/decimal.js +0 -8
- package/dist/runtime/diagnostics-reporter.d.ts +6 -6
- package/dist/runtime/diagnostics-reporter.js +0 -35
- package/dist/runtime/error-boundary.d.ts +3 -3
- package/dist/runtime/error-boundary.js +2 -167
- package/dist/runtime/execution-options.d.ts +4 -4
- package/dist/runtime/field-behavior.d.ts +6 -9
- package/dist/runtime/framework-error.js +0 -4
- package/dist/runtime/mutation-planner.d.ts +5 -6
- package/dist/runtime/mutation-planner.js +0 -23
- package/dist/runtime/operation-response.d.ts +1 -1
- package/dist/runtime/operation-response.js +1 -17
- package/dist/runtime/operation-runtime.d.ts +24 -22
- package/dist/runtime/operation-runtime.js +18 -52
- package/dist/runtime/outcome-mapper.js +0 -22
- package/dist/runtime/output-validator.js +0 -1
- package/dist/runtime/pipe-output.validator.d.ts +48 -0
- package/dist/runtime/pipe-output.validator.js +79 -0
- package/dist/runtime/pipeline.d.ts +20 -26
- package/dist/runtime/referential-action.d.ts +14 -19
- package/dist/runtime/referential-action.js +0 -23
- package/dist/runtime/request-id.js +0 -21
- package/dist/runtime/scalar-runtime.d.ts +14 -16
- package/dist/runtime/scalar-runtime.js +12 -57
- package/dist/transactions/deferred-operation.d.ts +9 -14
- package/dist/transactions/operation-arguments-encoder.d.ts +0 -1
- package/dist/transactions/operation-arguments-encoder.js +0 -14
- package/dist/transactions/operation-fingerprint.js +0 -1
- package/dist/transactions/transaction-envelope.js +0 -14
- package/dist/transactions/transaction-integrity-error.d.ts +10 -11
- package/dist/transactions/transaction-integrity-error.js +0 -5
- package/dist/transactions/transaction-plan-assembler.d.ts +0 -1
- package/dist/transactions/transaction-plan-assembler.js +0 -35
- package/dist/transactions/transaction-plan-validator.d.ts +5 -5
- package/dist/transactions/transaction-plan-validator.js +0 -63
- package/dist/transactions/transaction-reference-resolver.d.ts +12 -13
- package/dist/transactions/transaction-reference-resolver.js +0 -16
- package/dist/transactions/transaction-reference-validator.js +0 -8
- package/dist/transactions/transaction-reference.d.ts +19 -43
- package/dist/transactions/transaction-reference.js +0 -11
- package/dist/transactions/transaction-request.d.ts +4 -5
- package/dist/transactions/transaction-response.d.ts +1 -1
- package/dist/transactions/transaction-runtime.d.ts +2 -3
- package/dist/transactions/transaction-runtime.js +5 -44
- package/dist/transactions/transaction-slot-path-error.d.ts +10 -11
- package/dist/transactions/transaction-slot-path-error.js +0 -7
- package/dist/transactions/transaction-slot-writer.d.ts +12 -12
- package/dist/transactions/transaction-slot-writer.js +0 -34
- package/package.json +2 -2
|
@@ -6,6 +6,7 @@ import type { ResolvedFrameworkConfig } from "../config/config.resolver.js";
|
|
|
6
6
|
import type { Contract } from "../contracts/contract.js";
|
|
7
7
|
import type { OperationValidationOptions, SemanticOperationArguments } from "../operations/operation-validator.js";
|
|
8
8
|
import type { FrameworkTransactionRequest } from "../transactions/transaction-request.js";
|
|
9
|
+
import { type CreateRequirementTable } from "./create-requirement.js";
|
|
9
10
|
import type { DiagnosticsReporter } from "./diagnostics-reporter.js";
|
|
10
11
|
import type { ClientProtocolIdentity, FrameworkOperationRequest, OperationExecutionRequest } from "./operation-request.js";
|
|
11
12
|
import type { OperationFailureResponse, OperationResponse } from "./operation-response.js";
|
|
@@ -15,12 +16,14 @@ export type OperationRuntimeDependencies<M extends AdapterModel> = {
|
|
|
15
16
|
readonly config: ResolvedFrameworkConfig<M>;
|
|
16
17
|
};
|
|
17
18
|
/**
|
|
18
|
-
* What a validated operation's pipeline needs: everything except the root
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* type (C-724).
|
|
19
|
+
* What a validated operation's pipeline needs: everything except the root Adapter.
|
|
20
|
+
* Its single Adapter call goes through the executor passed beside it, so inside a
|
|
21
|
+
* transaction plan the root Adapter is unreachable by type.
|
|
22
22
|
*/
|
|
23
|
-
export type OperationPipelineDependencies<M extends AdapterModel> = Omit<OperationRuntimeDependencies<M>, "adapter"
|
|
23
|
+
export type OperationPipelineDependencies<M extends AdapterModel> = Omit<OperationRuntimeDependencies<M>, "adapter"> & {
|
|
24
|
+
/** The Adapter's create requirements, read once at construction. */
|
|
25
|
+
readonly createRequirements: CreateRequirementTable;
|
|
26
|
+
};
|
|
24
27
|
/**
|
|
25
28
|
* The executor core owns no diagnostics channel: the framework factory owns
|
|
26
29
|
* it and hands in one reporter already bound to this request, so every
|
|
@@ -35,11 +38,11 @@ export declare function createOperationRuntime<M extends AdapterModel>(dependenc
|
|
|
35
38
|
/** Validates the request-level protocol identity shared by both execution seams. */
|
|
36
39
|
export declare function validateProtocolIdentity(contracts: FrameworkContracts, request: FrameworkOperationRequest | FrameworkTransactionRequest): OperationFailureResponse | undefined;
|
|
37
40
|
/**
|
|
38
|
-
* The stale-client check
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
41
|
+
* The stale-client check on one client protocol identity: the protocol version
|
|
42
|
+
* first (`A2006`), then the ClientContract hash (`A2005`). Exact match only. The
|
|
43
|
+
* one implementation — the protocol's decoders and absence answers
|
|
44
|
+
* (`@aventara/core/protocol`) call it too, so a stale client hears the same
|
|
45
|
+
* envelope whichever layer answers.
|
|
43
46
|
*/
|
|
44
47
|
export declare function protocolIdentityFailure(contracts: FrameworkContracts, protocol: ClientProtocolIdentity): OperationFailureResponse | undefined;
|
|
45
48
|
export type ValidatedOperationArguments = {
|
|
@@ -53,23 +56,22 @@ export type ValidatedOperationArguments = {
|
|
|
53
56
|
export declare function validateOperationRequest(contract: Contract, request: FrameworkOperationRequest, options?: OperationValidationOptions): ValidatedOperationArguments;
|
|
54
57
|
/**
|
|
55
58
|
* Everything after the Framework Validation Layer: the developer/runtime path
|
|
56
|
-
* wrapped in the post-validation error boundary. Validation failures never
|
|
57
|
-
*
|
|
59
|
+
* wrapped in the post-validation error boundary. Validation failures never reach
|
|
60
|
+
* this function, so developer filters never see them.
|
|
58
61
|
*
|
|
59
|
-
* `executor` is the operation's single Adapter call site
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
62
|
+
* `executor` is the operation's single Adapter call site: standalone execution
|
|
63
|
+
* passes the Adapter itself, a transaction plan passes the transaction-scoped
|
|
64
|
+
* executor its Adapter callback received. Every call owns one AdapterBoundary, so
|
|
65
|
+
* A3001/A3000 origin stays classified per operation.
|
|
63
66
|
*
|
|
64
|
-
* The parameter types keep two values out of reach: `dependencies` carries no
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
67
|
+
* The parameter types keep two values out of reach: `dependencies` carries no root
|
|
68
|
+
* Adapter, so the executor is the only Adapter this function can call, and
|
|
69
|
+
* `request` carries no `arguments`, so no stage can read the unvalidated view
|
|
70
|
+
* instead of `validatedArguments`.
|
|
68
71
|
*
|
|
69
72
|
* `argumentsPath` is the framework's own address for these arguments —
|
|
70
73
|
* `["arguments"]` standalone, `["operations", i, "args"]` inside a plan. The
|
|
71
74
|
* response boundary needs it to decide whether a thrower-supplied issue path
|
|
72
|
-
* denotes the caller's own arguments or is unvouched text
|
|
73
|
-
* decision 4).
|
|
75
|
+
* denotes the caller's own arguments or is unvouched text.
|
|
74
76
|
*/
|
|
75
77
|
export declare function executeValidatedOperation<M extends AdapterModel>(dependencies: OperationPipelineDependencies<M>, request: OperationExecutionRequest, contract: Contract, validatedArguments: unknown, argumentsPath: readonly (string | number)[], executor: AdapterOperationExecutor<M>, report: DiagnosticsReporter): Promise<OperationResponse>;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { AVENTARA_PROTOCOL_VERSION } from "../contracts/contract-protocol.js";
|
|
2
2
|
import { validateOperationArguments } from "../operations/operation-validator.js";
|
|
3
3
|
import { materializeReadOperation, planReadOperation, } from "./computed-read-runtime.js";
|
|
4
|
+
import { missingCreateValues, } from "./create-requirement.js";
|
|
4
5
|
import { AdapterBoundary, OPERATION_ARGUMENTS_PATH, resolveOperationFailure, sanitizeOperationFailure, } from "./error-boundary.js";
|
|
5
6
|
import { applyWriteFieldBehaviors, stripVirtualMutationInput, } from "./mutation-planner.js";
|
|
6
7
|
import { internalFailure, operationFailure } from "./operation-response.js";
|
|
7
8
|
import { mapOperationOutcome, mapValidationOutcome } from "./outcome-mapper.js";
|
|
8
9
|
import { validateOperationOutput } from "./output-validator.js";
|
|
10
|
+
import { refusePipeOutput } from "./pipe-output.validator.js";
|
|
9
11
|
import { normalizeOperationScalarValues } from "./scalar-runtime.js";
|
|
10
|
-
/** Selects the Contract of the request's execution scope for both execution seams. */
|
|
11
12
|
export function activeContract(contracts, request) {
|
|
12
13
|
return request.scope === "application"
|
|
13
14
|
? contracts.application
|
|
@@ -35,13 +36,6 @@ function forbidden() {
|
|
|
35
36
|
message: "Operation denied by a framework guard.",
|
|
36
37
|
});
|
|
37
38
|
}
|
|
38
|
-
/**
|
|
39
|
-
* Output validation is framework validation (spec 16.5), so its failure is
|
|
40
|
-
* framework-owned however it arrives. Reading the result can itself throw -
|
|
41
|
-
* an Adapter row may carry an accessor that explodes - and without this
|
|
42
|
-
* boundary that throw would leave through the post-validation boundary and be
|
|
43
|
-
* offered to developer filters, which could relabel it as any outcome.
|
|
44
|
-
*/
|
|
45
39
|
function outputAccepted(contract, request, projection, data, report) {
|
|
46
40
|
try {
|
|
47
41
|
return validateOperationOutput(contract, request, projection, data).ok;
|
|
@@ -51,8 +45,12 @@ function outputAccepted(contract, request, projection, data, report) {
|
|
|
51
45
|
return false;
|
|
52
46
|
}
|
|
53
47
|
}
|
|
54
|
-
/** Creates the transport-independent operation executor owned by core. */
|
|
55
48
|
export function createOperationRuntime(dependencies) {
|
|
49
|
+
const pipelineDependencies = {
|
|
50
|
+
contracts: dependencies.contracts,
|
|
51
|
+
config: dependencies.config,
|
|
52
|
+
createRequirements: dependencies.adapter.createRequirements ?? {},
|
|
53
|
+
};
|
|
56
54
|
return async (request, report) => {
|
|
57
55
|
let validated;
|
|
58
56
|
try {
|
|
@@ -67,14 +65,9 @@ export function createOperationRuntime(dependencies) {
|
|
|
67
65
|
if (!validated.ok) {
|
|
68
66
|
return validated.response;
|
|
69
67
|
}
|
|
70
|
-
return executeValidatedOperation(
|
|
68
|
+
return executeValidatedOperation(pipelineDependencies, request, validated.contract, validated.arguments, OPERATION_ARGUMENTS_PATH, dependencies.adapter, report);
|
|
71
69
|
};
|
|
72
70
|
}
|
|
73
|
-
/**
|
|
74
|
-
* The Framework Validation Layer (spec 16), inside its own boundary: an
|
|
75
|
-
* unexpected throw here is sanitized directly and reaches zero developer
|
|
76
|
-
* filters, exactly like a validation failure (spec 16.5, 17.3).
|
|
77
|
-
*/
|
|
78
71
|
function validateOperation(dependencies, request) {
|
|
79
72
|
const protocolFailure = validateProtocolIdentity(dependencies.contracts, request);
|
|
80
73
|
if (protocolFailure !== undefined) {
|
|
@@ -87,19 +80,11 @@ function validateOperation(dependencies, request) {
|
|
|
87
80
|
}
|
|
88
81
|
return { ok: true, contract, arguments: validation.arguments };
|
|
89
82
|
}
|
|
90
|
-
/** Validates the request-level protocol identity shared by both execution seams. */
|
|
91
83
|
export function validateProtocolIdentity(contracts, request) {
|
|
92
84
|
return request.scope === "client"
|
|
93
85
|
? protocolIdentityFailure(contracts, request.protocol)
|
|
94
86
|
: undefined;
|
|
95
87
|
}
|
|
96
|
-
/**
|
|
97
|
-
* The stale-client check (§19.4, cross-phase invariant 15) on one client
|
|
98
|
-
* protocol identity: the protocol version first (`A2006`), then the
|
|
99
|
-
* ClientContract hash (`A2005`). Exact match only. The one implementation —
|
|
100
|
-
* the protocol's decoders and absence answers (`@aventara/core/protocol`) call
|
|
101
|
-
* it too, so a stale client hears the same envelope whichever layer answers.
|
|
102
|
-
*/
|
|
103
88
|
export function protocolIdentityFailure(contracts, protocol) {
|
|
104
89
|
if (protocol.version !== AVENTARA_PROTOCOL_VERSION) {
|
|
105
90
|
return operationFailure("A2006", {
|
|
@@ -113,7 +98,6 @@ export function protocolIdentityFailure(contracts, protocol) {
|
|
|
113
98
|
}
|
|
114
99
|
return undefined;
|
|
115
100
|
}
|
|
116
|
-
/** Reusable per-operation Framework Validation Layer argument seam. */
|
|
117
101
|
export function validateOperationRequest(contract, request, options) {
|
|
118
102
|
const validation = validateOperationArguments(contract, request, options);
|
|
119
103
|
if (!validation.ok) {
|
|
@@ -130,27 +114,6 @@ export function validateOperationRequest(contract, request, options) {
|
|
|
130
114
|
function rejected(response) {
|
|
131
115
|
return { ok: false, response };
|
|
132
116
|
}
|
|
133
|
-
/**
|
|
134
|
-
* Everything after the Framework Validation Layer: the developer/runtime path
|
|
135
|
-
* wrapped in the post-validation error boundary. Validation failures never
|
|
136
|
-
* reach this function, so developer filters never see them.
|
|
137
|
-
*
|
|
138
|
-
* `executor` is the operation's single Adapter call site (D-706): standalone
|
|
139
|
-
* execution passes the Adapter itself, a transaction plan passes the
|
|
140
|
-
* transaction-scoped executor its Adapter callback received. Every call owns
|
|
141
|
-
* one AdapterBoundary, so A3001/A3000 origin stays classified per operation.
|
|
142
|
-
*
|
|
143
|
-
* The parameter types keep two values out of reach: `dependencies` carries no
|
|
144
|
-
* root Adapter, so the executor is the only Adapter this function can call,
|
|
145
|
-
* and `request` carries no `arguments`, so no stage can read the unvalidated
|
|
146
|
-
* view instead of `validatedArguments`.
|
|
147
|
-
*
|
|
148
|
-
* `argumentsPath` is the framework's own address for these arguments —
|
|
149
|
-
* `["arguments"]` standalone, `["operations", i, "args"]` inside a plan. The
|
|
150
|
-
* response boundary needs it to decide whether a thrower-supplied issue path
|
|
151
|
-
* denotes the caller's own arguments or is unvouched text (ADR 0008
|
|
152
|
-
* decision 4).
|
|
153
|
-
*/
|
|
154
117
|
export async function executeValidatedOperation(dependencies, request, contract, validatedArguments, argumentsPath, executor, report) {
|
|
155
118
|
const scopeConfig = activeScopeConfig(dependencies.config, request);
|
|
156
119
|
const pipelines = scopeConfig.pipelines;
|
|
@@ -169,13 +132,22 @@ export async function executeValidatedOperation(dependencies, request, contract,
|
|
|
169
132
|
return forbidden();
|
|
170
133
|
}
|
|
171
134
|
}
|
|
172
|
-
for (const pipe of pipelines.pipes) {
|
|
135
|
+
for (const [index, pipe] of pipelines.pipes.entries()) {
|
|
173
136
|
const nextArgs = await pipe(args, pipelineContext(contract, request, args));
|
|
174
137
|
if (nextArgs !== undefined) {
|
|
175
138
|
args = nextArgs;
|
|
176
139
|
}
|
|
140
|
+
const refused = refusePipeOutput({ core: dependencies.contracts.core, active: contract }, request, args, pipe, index);
|
|
141
|
+
if (refused !== undefined) {
|
|
142
|
+
report(refused.error, "A3004");
|
|
143
|
+
return refused.response;
|
|
144
|
+
}
|
|
177
145
|
}
|
|
178
146
|
args = await applyWriteFieldBehaviors({ core: dependencies.contracts.core, active: contract }, scopeConfig.behaviors, request, args, () => pipelineContext(contract, request, args));
|
|
147
|
+
const missing = missingCreateValues(contract, dependencies.createRequirements, request, args, argumentsPath);
|
|
148
|
+
if (missing.length > 0) {
|
|
149
|
+
return mapValidationOutcome(missing);
|
|
150
|
+
}
|
|
179
151
|
for (const hook of pipelines.hooks.before) {
|
|
180
152
|
await hook(pipelineContext(contract, request, args));
|
|
181
153
|
}
|
|
@@ -189,12 +161,6 @@ export async function executeValidatedOperation(dependencies, request, contract,
|
|
|
189
161
|
let invoke = async () => {
|
|
190
162
|
const readPlan = planReadOperation(dependencies.contracts.core, contract, scopeConfig.behaviors, request, args);
|
|
191
163
|
const adapterArguments = await stripVirtualMutationInput({ core: dependencies.contracts.core, active: contract }, request, readPlan.arguments);
|
|
192
|
-
// `family` and `variant` are a correlated pair, so they travel as one
|
|
193
|
-
// OperationIdentity value: naming them separately would let any family
|
|
194
|
-
// pair with any variant. Only `resource` is cast, and only to `M`'s
|
|
195
|
-
// key union - the runtime check standing in for the compiler is
|
|
196
|
-
// `validateOperationArguments`, which has already rejected any
|
|
197
|
-
// resource name the active Contract does not carry.
|
|
198
164
|
const identity = request;
|
|
199
165
|
const adapterData = await adapterBoundary.execute(() => executor.execute({
|
|
200
166
|
...identity,
|
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
import { internalFailure, operationFailure, operationNoMatch, operationSuccess, } from "./operation-response.js";
|
|
2
|
-
/**
|
|
3
|
-
* Spec section 13.2 success table, resource-agnostic. The mapped key type
|
|
4
|
-
* makes the compiler reject a missing or unknown variant.
|
|
5
|
-
*/
|
|
6
2
|
const OUTCOME_TABLE = {
|
|
7
3
|
"find.first": { success: "A1000", absence: "no-match" },
|
|
8
4
|
"find.unique": { success: "A1000", absence: "not-found" },
|
|
@@ -21,12 +17,6 @@ const OUTCOME_TABLE = {
|
|
|
21
17
|
"delete.count": { success: "A1007" },
|
|
22
18
|
"upsert.unique": { success: "A1008" },
|
|
23
19
|
};
|
|
24
|
-
/**
|
|
25
|
-
* `family` and `variant` are correlated on `OperationIdentity`, but the
|
|
26
|
-
* template built from them is not: it spans every family/variant pair, of
|
|
27
|
-
* which most are not operations. So the lookup is a genuine miss-or-hit and
|
|
28
|
-
* says so, rather than asserting a key it cannot prove.
|
|
29
|
-
*/
|
|
30
20
|
function outcomeRule(operation) {
|
|
31
21
|
const table = OUTCOME_TABLE;
|
|
32
22
|
return table[`${operation.family}.${operation.variant}`];
|
|
@@ -43,11 +33,6 @@ function absenceOutcome(absence) {
|
|
|
43
33
|
return internalFailure();
|
|
44
34
|
}
|
|
45
35
|
}
|
|
46
|
-
/**
|
|
47
|
-
* Maps one validated operation result to its stable outcome envelope. The
|
|
48
|
-
* result must already have passed output validation, so `null` can only
|
|
49
|
-
* reach a variant whose cardinality admits it.
|
|
50
|
-
*/
|
|
51
36
|
export function mapOperationOutcome(operation, data) {
|
|
52
37
|
const rule = outcomeRule(operation);
|
|
53
38
|
if (rule === undefined) {
|
|
@@ -57,12 +42,6 @@ export function mapOperationOutcome(operation, data) {
|
|
|
57
42
|
? absenceOutcome(rule.absence)
|
|
58
43
|
: operationSuccess(data, rule.success);
|
|
59
44
|
}
|
|
60
|
-
/**
|
|
61
|
-
* Spec section 13.2 failure table for the Framework Validation Layer: which
|
|
62
|
-
* A-code a set of validation issues reports. The most specific rejection
|
|
63
|
-
* wins - an unknown Resource before an unavailable operation, and a
|
|
64
|
-
* structural-limit breach before an ordinary argument rejection.
|
|
65
|
-
*/
|
|
66
45
|
function validationCode(issues) {
|
|
67
46
|
if (issues.some((issue) => issue.path?.[0] === "resource")) {
|
|
68
47
|
return "A2001";
|
|
@@ -84,7 +63,6 @@ function validationCode(issues) {
|
|
|
84
63
|
}
|
|
85
64
|
return "A2004";
|
|
86
65
|
}
|
|
87
|
-
/** Maps framework validation issues to their stable failure envelope. */
|
|
88
66
|
export function mapValidationOutcome(issues) {
|
|
89
67
|
return operationFailure(validationCode(issues), {
|
|
90
68
|
message: "Operation arguments failed framework validation.",
|
|
@@ -168,7 +168,6 @@ function validateProjection(contract, operation, projection, value) {
|
|
|
168
168
|
? validateExactRecord(contract, value, projection, ["data"])
|
|
169
169
|
: { ok: true };
|
|
170
170
|
}
|
|
171
|
-
/** Validate final operation output against fixed cardinality and executed projection. */
|
|
172
171
|
export function validateOperationOutput(contract, operation, projection, value) {
|
|
173
172
|
const cardinality = validateOperationOutputCardinality(operation, value);
|
|
174
173
|
return cardinality.ok
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Contract, CoreContract } from "../contracts/contract.js";
|
|
2
|
+
import type { OperationIdentity } from "../operations/operation-identity.js";
|
|
3
|
+
import type { ValidationIssue } from "../operations/validation-code.js";
|
|
4
|
+
import type { OperationFailureResponse } from "./operation-response.js";
|
|
5
|
+
/**
|
|
6
|
+
* The check a pipe's output passes before it can reach the Adapter.
|
|
7
|
+
*
|
|
8
|
+
* The request was validated against the caller's own Contract. A pipe then
|
|
9
|
+
* rewrites it, and may legitimately write what the caller cannot: a field the
|
|
10
|
+
* client Contract hides (a password hash, an owner id taken from the session),
|
|
11
|
+
* a directive the caller's scope does not advertise. So the rewritten arguments
|
|
12
|
+
* are held to the **server's** rules — the Core Contract, plus the fields the
|
|
13
|
+
* active scope itself adds (they are virtual: computed, then stripped before
|
|
14
|
+
* the Adapter call) — in the values' runtime forms (`bigint`, `Date`,
|
|
15
|
+
* `Decimal`, `Uint8Array`), which is what every pipe receives.
|
|
16
|
+
*
|
|
17
|
+
* A refusal is the server's defect, not the caller's: `A3004
|
|
18
|
+
* PIPE_OUTPUT_INVALID`, a 500 that tells the caller no more than any internal
|
|
19
|
+
* failure does — {@link PIPE_OUTPUT_FAILURE_MESSAGE}, and the step in a plan.
|
|
20
|
+
* The pipe, the operation, the first offending field and its V-code go to the
|
|
21
|
+
* diagnostics channel only, as a {@link PipeOutputError}: they name server
|
|
22
|
+
* internals — a pipe's function name, a field the caller's Contract hides.
|
|
23
|
+
*/
|
|
24
|
+
/** The one text every `A3004` carries on the wire. */
|
|
25
|
+
export declare const PIPE_OUTPUT_FAILURE_MESSAGE = "A server pipeline produced invalid arguments.";
|
|
26
|
+
/** The error the diagnostics channel receives for a refused pipe output. */
|
|
27
|
+
export declare class PipeOutputError extends Error {
|
|
28
|
+
readonly issues: readonly ValidationIssue[];
|
|
29
|
+
readonly name = "PipeOutputError";
|
|
30
|
+
constructor(message: string, issues: readonly ValidationIssue[]);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* `undefined` when the pipe's output passes the server's rules; otherwise the
|
|
34
|
+
* `A3004` failure, and the error the diagnostics channel is told.
|
|
35
|
+
*/
|
|
36
|
+
export declare function refusePipeOutput(contracts: {
|
|
37
|
+
readonly core: CoreContract;
|
|
38
|
+
readonly active: Contract;
|
|
39
|
+
}, request: OperationIdentity & {
|
|
40
|
+
readonly resource: string;
|
|
41
|
+
}, args: unknown,
|
|
42
|
+
/** The pipe that produced `args`, named in the message by its function name. */
|
|
43
|
+
pipe: unknown,
|
|
44
|
+
/** Its position in the effective pipe list (root pipes first). */
|
|
45
|
+
index: number): {
|
|
46
|
+
readonly response: OperationFailureResponse;
|
|
47
|
+
readonly error: PipeOutputError;
|
|
48
|
+
} | undefined;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { validateOperationArguments } from "../operations/operation-validator.js";
|
|
2
|
+
import { operationFailure } from "./operation-response.js";
|
|
3
|
+
import { normalizeOperationScalarValues } from "./scalar-runtime.js";
|
|
4
|
+
export const PIPE_OUTPUT_FAILURE_MESSAGE = "A server pipeline produced invalid arguments.";
|
|
5
|
+
function serverContract(core, active) {
|
|
6
|
+
const resources = {};
|
|
7
|
+
for (const [name, resource] of Object.entries(core.resources)) {
|
|
8
|
+
const scoped = Object.hasOwn(active.resources, name)
|
|
9
|
+
? active.resources[name]
|
|
10
|
+
: undefined;
|
|
11
|
+
const added = scoped === undefined
|
|
12
|
+
? {}
|
|
13
|
+
: Object.fromEntries(Object.entries(scoped.fields).filter(([field]) => !Object.hasOwn(resource.fields, field)));
|
|
14
|
+
resources[name] =
|
|
15
|
+
Object.keys(added).length === 0
|
|
16
|
+
? resource
|
|
17
|
+
: { ...resource, fields: { ...resource.fields, ...added } };
|
|
18
|
+
}
|
|
19
|
+
return { ...core, resources };
|
|
20
|
+
}
|
|
21
|
+
const SERVER_VIEWS = new WeakMap();
|
|
22
|
+
function serverContractFor(core, active) {
|
|
23
|
+
let view = SERVER_VIEWS.get(active);
|
|
24
|
+
if (view === undefined) {
|
|
25
|
+
view = serverContract(core, active);
|
|
26
|
+
SERVER_VIEWS.set(active, view);
|
|
27
|
+
}
|
|
28
|
+
return view;
|
|
29
|
+
}
|
|
30
|
+
function serverIssues(contract, request, args) {
|
|
31
|
+
const validation = validateOperationArguments(contract, {
|
|
32
|
+
...request,
|
|
33
|
+
arguments: args,
|
|
34
|
+
});
|
|
35
|
+
if (!validation.ok) {
|
|
36
|
+
return validation.issues;
|
|
37
|
+
}
|
|
38
|
+
const normalization = normalizeOperationScalarValues(contract, { ...request, arguments: validation.arguments }, "application");
|
|
39
|
+
return normalization.ok ? [] : normalization.issues;
|
|
40
|
+
}
|
|
41
|
+
function pipeLabel(pipe, index) {
|
|
42
|
+
let name;
|
|
43
|
+
try {
|
|
44
|
+
name = pipe.name;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
name = undefined;
|
|
48
|
+
}
|
|
49
|
+
return typeof name === "string" && name !== ""
|
|
50
|
+
? `pipes[${index}] "${name}"`
|
|
51
|
+
: `pipes[${index}] (anonymous)`;
|
|
52
|
+
}
|
|
53
|
+
function fieldOf(issue) {
|
|
54
|
+
const path = issue.path ?? [];
|
|
55
|
+
const relative = path[0] === "arguments" ? path.slice(1) : path;
|
|
56
|
+
return relative.length === 0 ? "(arguments)" : relative.join(".");
|
|
57
|
+
}
|
|
58
|
+
export class PipeOutputError extends Error {
|
|
59
|
+
issues;
|
|
60
|
+
name = "PipeOutputError";
|
|
61
|
+
constructor(message, issues) {
|
|
62
|
+
super(message);
|
|
63
|
+
this.issues = issues;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export function refusePipeOutput(contracts, request, args, pipe, index) {
|
|
67
|
+
const issues = serverIssues(serverContractFor(contracts.core, contracts.active), request, args);
|
|
68
|
+
const [first] = issues;
|
|
69
|
+
if (first === undefined) {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
const message = `Pipe ${pipeLabel(pipe, index)} returned arguments for ${request.resource}.${request.family}.${request.variant} that the server contract refuses at "${fieldOf(first)}" (${first.code}: ${first.message})`;
|
|
73
|
+
return {
|
|
74
|
+
response: operationFailure("A3004", {
|
|
75
|
+
message: PIPE_OUTPUT_FAILURE_MESSAGE,
|
|
76
|
+
}),
|
|
77
|
+
error: new PipeOutputError(message, issues),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
@@ -5,16 +5,13 @@ import type { Contract } from "../contracts/contract.js";
|
|
|
5
5
|
import type { OperationFamily } from "../operations/operation-identity.js";
|
|
6
6
|
import type { FrameworkError } from "./framework-error.js";
|
|
7
7
|
/**
|
|
8
|
-
* What a pipeline is told about the HTTP request a client-origin operation
|
|
9
|
-
*
|
|
10
|
-
* (F-609; the architect, Phase 10 Q7; ADR 0010). Specification §17.2 states
|
|
11
|
-
* this shape, and developers may read it in their pipelines: the verb, always
|
|
12
|
-
* `POST` on a framework route, and the request's headers.
|
|
8
|
+
* What a pipeline is told about the HTTP request a client-origin operation arrived
|
|
9
|
+
* on — a **deliberate exception** to core's transport-agnosticism.
|
|
13
10
|
*
|
|
14
|
-
* Core never parses HTTP to fill it. `@aventara/core/protocol`'s decoders do,
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
11
|
+
* Core never parses HTTP to fill it. `@aventara/core/protocol`'s decoders do, with
|
|
12
|
+
* header names **lower-cased** and a repeated header's values joined with `", "`
|
|
13
|
+
* (RFC 9110 §5.3), so a pipeline reads one spelling. An application-scope request
|
|
14
|
+
* carries none (`ClientOperationRequest.transport` is optional).
|
|
18
15
|
*/
|
|
19
16
|
export type PipelineTransportContext = {
|
|
20
17
|
readonly method: "POST";
|
|
@@ -23,27 +20,24 @@ export type PipelineTransportContext = {
|
|
|
23
20
|
/**
|
|
24
21
|
* What a pipeline callback is told about the operation it is wrapping.
|
|
25
22
|
*
|
|
26
|
-
* `resource` reads its key set from the **AdapterModel**, not from a
|
|
27
|
-
* `Contract
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
23
|
+
* `resource` reads its key set from the **AdapterModel**, not from a `Contract`:
|
|
24
|
+
* `Contract["resources"]` is an open `Record<string, …>`, so the `C extends
|
|
25
|
+
* Contract` parameter this type used to take could never name the Resources an
|
|
26
|
+
* author actually has — it erased to `string`. `M` can name them, and
|
|
27
|
+
* configuration cannot add Resources, so `M` is the whole answer.
|
|
31
28
|
*
|
|
32
|
-
*
|
|
33
|
-
* and this type has none: `contract` is passive compiled data, `args` is
|
|
34
|
-
* `unknown` until Phase 9 (F-701), and `resource` comes from `M` alone. A
|
|
35
|
-
* `Cfg` parameter here would be referenced nowhere — `biome` flags it
|
|
29
|
+
* A `Cfg` parameter here would be referenced nowhere — `biome` flags it
|
|
36
30
|
* (`lint/correctness/noUnusedVariables`) and it would encode no semantic
|
|
37
|
-
* dependency. `FrameworkScopeConfig` already has the precedent one line
|
|
38
|
-
*
|
|
31
|
+
* dependency. `FrameworkScopeConfig` already has the precedent one line above
|
|
32
|
+
* `pipelines`: `fields` takes `M` only.
|
|
39
33
|
*
|
|
40
|
-
* `contract` stays the erased {@link Contract} deliberately: a compiled
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
34
|
+
* `contract` stays the erased {@link Contract} deliberately: a compiled Contract
|
|
35
|
+
* is passive semantic data whose result "stays untyped by design". Threading
|
|
36
|
+
* configuration into it would rebuild the authoring-config-to-compiled-contract
|
|
37
|
+
* bridge this work bypasses.
|
|
44
38
|
*
|
|
45
|
-
* Under the default `M` the key set degenerates to `string`, so an
|
|
46
|
-
*
|
|
39
|
+
* Under the default `M` the key set degenerates to `string`, so an unannotated
|
|
40
|
+
* `PipelineContext` is what it was before.
|
|
47
41
|
*/
|
|
48
42
|
export type PipelineContext<M extends AdapterModel = AdapterModel> = {
|
|
49
43
|
readonly contract: Contract;
|
|
@@ -1,35 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Core's referential-action vocabulary, and the transitive cascade closure the
|
|
3
|
-
* transaction planner reads
|
|
3
|
+
* transaction planner reads.
|
|
4
4
|
*
|
|
5
5
|
* The facts are an Adapter's: which relation edges exist, and what deleting a
|
|
6
|
-
* referenced row does to the rows that reference it.
|
|
7
|
-
* core's — the architect rejected keeping it below the seam on 2026-10-02,
|
|
8
|
-
* because every Adapter would then re-implement it. So the words here are
|
|
6
|
+
* referenced row does to the rows that reference it. So the words here are
|
|
9
7
|
* Aventara's, stated as the effect on the referencing rows, and an Adapter
|
|
10
8
|
* translates its own provider's vocabulary into them.
|
|
11
9
|
*
|
|
12
|
-
* None of this enters a Contract. It is not part of the semantic model a
|
|
13
|
-
*
|
|
14
|
-
*
|
|
10
|
+
* None of this enters a Contract. It is not part of the semantic model a Contract
|
|
11
|
+
* is compiled from, so it moves no Contract value and no hash; it is a planning
|
|
12
|
+
* fact, read once when the Framework is constructed.
|
|
15
13
|
*/
|
|
16
14
|
/**
|
|
17
|
-
* What deleting a referenced row does to the rows that reference it.
|
|
18
|
-
* words are the architect's (binding, 2026-10-04), and mirror SQL's
|
|
19
|
-
* referential actions one to one, so no adapter has to choose between two of
|
|
20
|
-
* them:
|
|
15
|
+
* What deleting a referenced row does to the rows that reference it.
|
|
21
16
|
*
|
|
22
|
-
* - `cascade` — they are deleted with it, and their own referencing rows in
|
|
23
|
-
*
|
|
17
|
+
* - `cascade` — they are deleted with it, and their own referencing rows in turn
|
|
18
|
+
* (SQL `ON DELETE CASCADE`).
|
|
24
19
|
* - `restrict` — the delete is refused while they reference it (`RESTRICT`).
|
|
25
20
|
* - `noAction` — the delete is refused while they reference it (`NO ACTION`).
|
|
26
|
-
* Measured identical to `restrict` on both pilot engines
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
21
|
+
* Measured identical to `restrict` on both pilot engines: neither declares the
|
|
22
|
+
* constraint `DEFERRABLE`, so the end-of-statement check answers one delete
|
|
23
|
+
* exactly as `RESTRICT` does. It stays a distinct word because it is a distinct
|
|
24
|
+
* schema fact.
|
|
30
25
|
* - `setNull` — they are kept, the reference set to null (`SET NULL`).
|
|
31
|
-
* - `setDefault` — they are kept, the reference set to its column default
|
|
32
|
-
*
|
|
26
|
+
* - `setDefault` — they are kept, the reference set to its column default (`SET
|
|
27
|
+
* DEFAULT`).
|
|
33
28
|
*
|
|
34
29
|
* Only `cascade` takes rows away, so only `cascade` is followed by the closure.
|
|
35
30
|
*/
|
|
@@ -1,26 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Core's referential-action vocabulary, and the transitive cascade closure the
|
|
3
|
-
* transaction planner reads (F-806, Phase 9 S10).
|
|
4
|
-
*
|
|
5
|
-
* The facts are an Adapter's: which relation edges exist, and what deleting a
|
|
6
|
-
* referenced row does to the rows that reference it. The reasoning over them is
|
|
7
|
-
* core's — the architect rejected keeping it below the seam on 2026-10-02,
|
|
8
|
-
* because every Adapter would then re-implement it. So the words here are
|
|
9
|
-
* Aventara's, stated as the effect on the referencing rows, and an Adapter
|
|
10
|
-
* translates its own provider's vocabulary into them.
|
|
11
|
-
*
|
|
12
|
-
* None of this enters a Contract. It is not part of the semantic model a
|
|
13
|
-
* Contract is compiled from, so it moves no Contract value and no hash; it is a
|
|
14
|
-
* planning fact, read once when the Framework is constructed.
|
|
15
|
-
*/
|
|
16
1
|
const NO_CASCADE = new Set();
|
|
17
|
-
/**
|
|
18
|
-
* Builds the closure over an Adapter's table, once. An absent table is the
|
|
19
|
-
* answer of an Adapter that cannot state its referential actions; it is
|
|
20
|
-
* believed, so nothing cascades.
|
|
21
|
-
*/
|
|
22
2
|
export function resolveCascadeClosure(table) {
|
|
23
|
-
// target → the Resources a delete of it cascades into, one hop.
|
|
24
3
|
const removedBy = new Map();
|
|
25
4
|
for (const [resource, edges] of Object.entries(table ?? {})) {
|
|
26
5
|
for (const edge of edges) {
|
|
@@ -41,8 +20,6 @@ export function resolveCascadeClosure(table) {
|
|
|
41
20
|
const closure = new Set();
|
|
42
21
|
const frontier = [...(removedBy.get(resource) ?? [])];
|
|
43
22
|
for (let next = frontier.pop(); next !== undefined; next = frontier.pop()) {
|
|
44
|
-
// The visited set is what makes a self-referential or cyclic cascade
|
|
45
|
-
// terminate: each Resource is expanded at most once.
|
|
46
23
|
if (closure.has(next)) {
|
|
47
24
|
continue;
|
|
48
25
|
}
|
|
@@ -1,27 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The one place core mints a request id (Q10 = B; F-833). The typed façades and
|
|
3
|
-
* the typed transaction runner call it when the caller supplies no usable id.
|
|
4
|
-
* It is internal: neither the main entry nor `@aventara/core/protocol` exports
|
|
5
|
-
* a minting helper. A host's correlation id reaches core as data —
|
|
6
|
-
* `ExecutionOptions.requestId` in process, or the `requestId` of a request the
|
|
7
|
-
* protocol decoders build from an adopted `Aventara-Request-Id` (Phase 10 S7,
|
|
8
|
-
* which mints through this module when none was adopted).
|
|
9
|
-
*/
|
|
10
1
|
function createRequestId() {
|
|
11
2
|
return globalThis.crypto.randomUUID();
|
|
12
3
|
}
|
|
13
|
-
/**
|
|
14
|
-
* The request id of one façade call or transaction run: the caller's
|
|
15
|
-
* `ExecutionOptions.requestId` when it is a non-empty string, otherwise a minted
|
|
16
|
-
* one. Nothing is refused (the call runs either way); the empty string is read
|
|
17
|
-
* as absent, because it names nothing a log line or a diagnostic could be
|
|
18
|
-
* correlated by.
|
|
19
|
-
*
|
|
20
|
-
* Read as `unknown` because the façades are total for untyped callers too: a
|
|
21
|
-
* value the type refuses — a non-string id, a non-object options argument, a
|
|
22
|
-
* getter that throws — is ignored rather than carried into a `string` slot or
|
|
23
|
-
* thrown out of a call that must resolve.
|
|
24
|
-
*/
|
|
25
4
|
export function requestIdOf(options) {
|
|
26
5
|
if (typeof options === "object" && options !== null) {
|
|
27
6
|
let requestId;
|
|
@@ -20,14 +20,13 @@ export type ScalarValueNormalizationResult = {
|
|
|
20
20
|
};
|
|
21
21
|
type Path = readonly (string | number)[];
|
|
22
22
|
/**
|
|
23
|
-
* The one discriminant between an argument OBJECT and a VALUE wherever a
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* another.
|
|
23
|
+
* The one discriminant between an argument OBJECT and a VALUE wherever a position
|
|
24
|
+
* admits both — a filter position above all: a **plain** record is an operator
|
|
25
|
+
* object, and anything else — a `Date`, a core `Decimal`, a `Uint8Array` — is a
|
|
26
|
+
* value, which equality shorthand then holds to the field's scalar. The validator
|
|
27
|
+
* (`operation-validator-core.ts`) reads a filter position through this same
|
|
28
|
+
* answer, and an adapter's filter translation is expected to, so a position cannot
|
|
29
|
+
* be operators to one reader and a value to another.
|
|
31
30
|
*/
|
|
32
31
|
export declare function isPlainRecord(value: unknown): value is Readonly<Record<string, unknown>>;
|
|
33
32
|
/**
|
|
@@ -36,14 +35,13 @@ export declare function isPlainRecord(value: unknown): value is Readonly<Record<
|
|
|
36
35
|
*/
|
|
37
36
|
export declare function normalizeScalarFieldValue(contract: Contract, field: ScalarField<Contract>, value: unknown, scope: RequestOrigin | "runtime", path: Path): ScalarValueNormalizationResult;
|
|
38
37
|
/**
|
|
39
|
-
* Copies one validated runtime value of a scalar field into a value the
|
|
40
|
-
*
|
|
41
|
-
* `
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* declaring its copy.
|
|
38
|
+
* Copies one validated runtime value of a scalar field into a value the framework
|
|
39
|
+
* owns, per scalar codec: `datetime` → a new `Date`, `bytes` → a sliced
|
|
40
|
+
* `Uint8Array`, `json` → a structured deep copy, and a list → a new array of
|
|
41
|
+
* copied items. `decimal` keeps its identity, and strings, numbers, booleans,
|
|
42
|
+
* bigints, enum members and `null` are immutable and returned unchanged. {@link
|
|
43
|
+
* SCALAR_ATOM_COPIERS} is exhaustive over {@link BuiltInScalar}, so a new codec
|
|
44
|
+
* cannot reach this function without declaring its copy.
|
|
47
45
|
*/
|
|
48
46
|
export declare function copyScalarFieldValue(field: ScalarField<Contract>, value: unknown): unknown;
|
|
49
47
|
/**
|