@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,4 +1,4 @@
|
|
|
1
|
-
const ORIGINS = ["application", "client"];
|
|
1
|
+
const ORIGINS = ["application", "client", "agent"];
|
|
2
2
|
const OPERATION_IDENTITY_MEMBERS = ["resource", "family", "variant"];
|
|
3
3
|
export function validateOperationEnvelope(request) {
|
|
4
4
|
if (!isRecord(request)) {
|
|
@@ -29,7 +29,7 @@ function originAndIdentityIssues(request) {
|
|
|
29
29
|
issues.push(issue(["origin"], "V1001", "Request origin must be a string."));
|
|
30
30
|
}
|
|
31
31
|
else if (!ORIGINS.includes(origin)) {
|
|
32
|
-
issues.push(issue(["origin"], "V1002", 'Request origin must be "application" or "
|
|
32
|
+
issues.push(issue(["origin"], "V1002", 'Request origin must be "application", "client" or "agent".'));
|
|
33
33
|
}
|
|
34
34
|
const requestId = request.requestId;
|
|
35
35
|
if (requestId === undefined || requestId === "") {
|
|
@@ -38,8 +38,13 @@ function originAndIdentityIssues(request) {
|
|
|
38
38
|
else if (typeof requestId !== "string") {
|
|
39
39
|
issues.push(issue(["requestId"], "V1001", "Request id must be a string."));
|
|
40
40
|
}
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
const state = request.state;
|
|
42
|
+
if (state !== undefined &&
|
|
43
|
+
(typeof state !== "object" || state === null || Array.isArray(state))) {
|
|
44
|
+
issues.push(issue(["state"], "V1001", "Request state must be an object."));
|
|
45
|
+
}
|
|
46
|
+
if (origin === "client" || origin === "agent") {
|
|
47
|
+
issues.push(...protocolIssues(request.protocol, origin));
|
|
43
48
|
if (request.transport !== undefined) {
|
|
44
49
|
issues.push(...transportIssues(request.transport));
|
|
45
50
|
}
|
|
@@ -47,16 +52,16 @@ function originAndIdentityIssues(request) {
|
|
|
47
52
|
else if (origin === "application") {
|
|
48
53
|
for (const member of ["protocol", "transport"]) {
|
|
49
54
|
if (request[member] !== undefined) {
|
|
50
|
-
issues.push(issue([member], "V1005", `Property "${member}" belongs to a client request, not an application one.`));
|
|
55
|
+
issues.push(issue([member], "V1005", `Property "${member}" belongs to a client or agent request, not an application one.`));
|
|
51
56
|
}
|
|
52
57
|
}
|
|
53
58
|
}
|
|
54
59
|
return issues;
|
|
55
60
|
}
|
|
56
|
-
function protocolIssues(protocol) {
|
|
61
|
+
function protocolIssues(protocol, origin) {
|
|
57
62
|
if (protocol === undefined) {
|
|
58
63
|
return [
|
|
59
|
-
issue(["protocol"], "V1000",
|
|
64
|
+
issue(["protocol"], "V1000", `Required property "protocol" is missing from ${origin === "client" ? "a client" : "an agent"} request.`),
|
|
60
65
|
];
|
|
61
66
|
}
|
|
62
67
|
if (!isRecord(protocol)) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The request id of one call or transaction run: the caller's
|
|
3
|
-
* `
|
|
3
|
+
* `AvExecutionOptions.requestId` when it is a non-empty string, otherwise a new
|
|
4
4
|
* one. Any other value is ignored.
|
|
5
5
|
*/
|
|
6
6
|
export declare function requestIdOf(options: unknown): string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The per-request state every stage reads and writes as `ctx.$state`. Empty
|
|
3
|
+
* until the application declares its members by module augmentation:
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* declare module "@aventara/core" {
|
|
7
|
+
* interface AvState {
|
|
8
|
+
* user?: { id: string; roles: string[] };
|
|
9
|
+
* }
|
|
10
|
+
* }
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export interface AvState {
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AvState } from "./request-state.js";
|
|
2
|
+
/**
|
|
3
|
+
* The state of one request: the seed when it is an object, otherwise a fresh
|
|
4
|
+
* `{}`. A seed that is not an object is ignored, as an unusable request id is.
|
|
5
|
+
*/
|
|
6
|
+
export declare function requestStateOf(seed: unknown): AvState;
|
|
7
|
+
/**
|
|
8
|
+
* The state an in-process call's `AvExecutionOptions` seeds, or `undefined`.
|
|
9
|
+
* Read as `unknown`, like the request id: a façade is total for untyped
|
|
10
|
+
* callers, so a getter that throws or a value that is not an object is ignored.
|
|
11
|
+
*/
|
|
12
|
+
export declare function stateOptionOf(options: unknown): AvState | undefined;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function requestStateOf(seed) {
|
|
2
|
+
return typeof seed === "object" && seed !== null && !Array.isArray(seed)
|
|
3
|
+
? seed
|
|
4
|
+
: {};
|
|
5
|
+
}
|
|
6
|
+
export function stateOptionOf(options) {
|
|
7
|
+
if (typeof options !== "object" || options === null) {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
let state;
|
|
11
|
+
try {
|
|
12
|
+
state = options.state;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
return typeof state === "object" && state !== null && !Array.isArray(state)
|
|
18
|
+
? state
|
|
19
|
+
: undefined;
|
|
20
|
+
}
|
|
@@ -1,41 +1,56 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
5
|
-
import type {
|
|
1
|
+
import type { AvRequestOrigin } from "../config/config-layer.js";
|
|
2
|
+
import type { AvScalarFilterOperator } from "../contracts/capability.js";
|
|
3
|
+
import type { AvContract } from "../contracts/contract.js";
|
|
4
|
+
import type { AvScalarField } from "../contracts/field.js";
|
|
5
|
+
import type { AvOperationIdentity } from "../operations/operation-identity.js";
|
|
6
6
|
import type { OperationValidationOptions, SemanticOperationArguments } from "../operations/operation-validator.js";
|
|
7
|
-
import type {
|
|
7
|
+
import type { AvValidationIssue } from "../operations/validation-code.js";
|
|
8
8
|
import { type TransactionSlotShape } from "../transactions/transaction-reference.js";
|
|
9
9
|
export type ScalarNormalizationResult = {
|
|
10
10
|
readonly ok: true;
|
|
11
11
|
readonly arguments: SemanticOperationArguments;
|
|
12
12
|
} | {
|
|
13
13
|
readonly ok: false;
|
|
14
|
-
readonly issues: readonly
|
|
14
|
+
readonly issues: readonly AvValidationIssue[];
|
|
15
15
|
};
|
|
16
16
|
export type ScalarValueNormalizationResult = {
|
|
17
17
|
readonly ok: true;
|
|
18
18
|
readonly value: unknown;
|
|
19
19
|
} | {
|
|
20
20
|
readonly ok: false;
|
|
21
|
-
readonly issues: readonly
|
|
21
|
+
readonly issues: readonly AvValidationIssue[];
|
|
22
22
|
};
|
|
23
23
|
type Path = readonly (string | number)[];
|
|
24
24
|
/**
|
|
25
25
|
* The one discriminant between an argument OBJECT and a VALUE wherever a position
|
|
26
26
|
* admits both — a filter position above all: a **plain** record is an operator object,
|
|
27
|
-
* and anything else — a `Date`, a core `
|
|
27
|
+
* and anything else — a `Date`, a core `AvDecimal`, a `Uint8Array` — is a value, which
|
|
28
28
|
* equality shorthand then holds to the field's scalar. The validator (`operation-
|
|
29
29
|
* validator-core.ts`) reads a filter position through this same answer, and an
|
|
30
30
|
* adapter's filter translation is expected to, so a position cannot be operators to
|
|
31
31
|
* one reader and a value to another.
|
|
32
32
|
*/
|
|
33
33
|
export declare function isPlainRecord(value: unknown): value is Readonly<Record<string, unknown>>;
|
|
34
|
+
/**
|
|
35
|
+
* An operation argument's JSON value is bounded by `maxJsonDepth`, which the
|
|
36
|
+
* structural walk enforces before this runs; a `$sql` step's parameter is not
|
|
37
|
+
* bounded by it. The traversal therefore carries its own stack on the heap: a
|
|
38
|
+
* payload deep enough to exhaust the call stack must still normalize rather
|
|
39
|
+
* than become an internal failure.
|
|
40
|
+
*
|
|
41
|
+
* `seen` holds the ancestors of the value being visited, so a repeated
|
|
42
|
+
* sibling reference is legal and only a genuine cycle is rejected.
|
|
43
|
+
*
|
|
44
|
+
* Every node it emits is typed {@link AvJsonValue}, so the public type and what
|
|
45
|
+
* this traversal produces are one fact: a branch that emitted anything else
|
|
46
|
+
* would not compile.
|
|
47
|
+
*/
|
|
48
|
+
export declare function normalizeJsonValue(value: unknown, path: Path, seen: Set<object>): ScalarValueNormalizationResult;
|
|
34
49
|
/**
|
|
35
50
|
* Normalizes one field value to Aventara's provider-neutral runtime form.
|
|
36
51
|
* `runtime` is used for framework-produced values regardless of request origin.
|
|
37
52
|
*/
|
|
38
|
-
export declare function normalizeScalarFieldValue(contract:
|
|
53
|
+
export declare function normalizeScalarFieldValue(contract: AvContract, field: AvScalarField<AvContract>, value: unknown, origin: AvRequestOrigin | "runtime", path: Path): ScalarValueNormalizationResult;
|
|
39
54
|
/**
|
|
40
55
|
* Every way a normalized value written to `field` does not conform to the field's
|
|
41
56
|
* Json Shape, each at its full path; none for an unshaped field or a `null`.
|
|
@@ -45,17 +60,17 @@ export declare function normalizeScalarFieldValue(contract: Contract, field: Sca
|
|
|
45
60
|
* @throws Error when the field carries a shape no checker is bound to — a Contract
|
|
46
61
|
* the Framework did not compile.
|
|
47
62
|
*/
|
|
48
|
-
export declare function jsonShapeIssues(field:
|
|
63
|
+
export declare function jsonShapeIssues(field: AvScalarField<AvContract>, value: unknown, path: Path, position?: "value" | "entry"): readonly AvValidationIssue[];
|
|
49
64
|
/**
|
|
50
65
|
* Copies one validated runtime value of a scalar field into a value the framework
|
|
51
66
|
* owns, per scalar codec: `datetime` → a new `Date`, `bytes` → a sliced `Uint8Array`,
|
|
52
67
|
* `json` → a structured deep copy, and a list → a new array of copied items. `decimal`
|
|
53
68
|
* keeps its identity, and strings, numbers, booleans, bigints, enum members and `null`
|
|
54
69
|
* are immutable and returned unchanged. {@link SCALAR_ATOM_COPIERS} is exhaustive over
|
|
55
|
-
* {@link
|
|
70
|
+
* {@link AvBuiltInScalar}, so a new codec cannot reach this function without declaring
|
|
56
71
|
* its copy.
|
|
57
72
|
*/
|
|
58
|
-
export declare function copyScalarFieldValue(field:
|
|
73
|
+
export declare function copyScalarFieldValue(field: AvScalarField<AvContract>, value: unknown): unknown;
|
|
59
74
|
/**
|
|
60
75
|
* The operators of a step's own filter whose operand is a reference position, and
|
|
61
76
|
* the shape each holds — the one table the normalization below and the reference
|
|
@@ -63,7 +78,7 @@ export declare function copyScalarFieldValue(field: ScalarField<Contract>, value
|
|
|
63
78
|
* nested operator object. Not here, so never a reference: `mode`, `isEmpty`, `path`
|
|
64
79
|
* and a `json` field's `string*`/`array*` operators, which take no field value.
|
|
65
80
|
*/
|
|
66
|
-
export declare const REFERENCE_OPERANDS: Readonly<Partial<Record<
|
|
81
|
+
export declare const REFERENCE_OPERANDS: Readonly<Partial<Record<AvScalarFilterOperator, TransactionSlotShape>>>;
|
|
67
82
|
/** The shape of `operator`'s operand when it is a reference position. */
|
|
68
83
|
export declare function referenceOperandShape(operator: string): TransactionSlotShape | undefined;
|
|
69
84
|
/**
|
|
@@ -76,8 +91,8 @@ export type NormalizationWrite = "copy" | "in-place";
|
|
|
76
91
|
* Normalizes every scalar leaf in one structurally valid standard operation.
|
|
77
92
|
* Client wire values are decoded; application values are validated in runtime form.
|
|
78
93
|
*/
|
|
79
|
-
export declare function normalizeOperationScalarValues(contract:
|
|
94
|
+
export declare function normalizeOperationScalarValues(contract: AvContract, request: AvOperationIdentity & {
|
|
80
95
|
readonly resource: string;
|
|
81
96
|
readonly arguments: SemanticOperationArguments;
|
|
82
|
-
}, origin:
|
|
97
|
+
}, origin: AvRequestOrigin, options?: OperationValidationOptions, write?: NormalizationWrite): ScalarNormalizationResult;
|
|
83
98
|
export {};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { shapeOfField } from "../avz/json-shape.registry.js";
|
|
1
2
|
import { lookupField, lookupOwn, lookupResource, } from "../contracts/contract-lookup.js";
|
|
2
3
|
import { decodeBase64, WIRE_SCALAR_PATTERNS, } from "../contracts/wire-scalar-format.js";
|
|
3
|
-
import { shapeOfField } from "../json/json-shape.registry.js";
|
|
4
4
|
import { routeTransactionReferenceCandidate, } from "../transactions/transaction-reference.js";
|
|
5
|
-
import {
|
|
5
|
+
import { AvDecimal } from "./decimal.js";
|
|
6
6
|
const INT_MIN = -(2 ** 31);
|
|
7
7
|
const INT_MAX = 2 ** 31 - 1;
|
|
8
8
|
const BIGINT_MIN = -(2n ** 63n);
|
|
@@ -39,7 +39,7 @@ function materializeJsonPath(root, link) {
|
|
|
39
39
|
segments.reverse();
|
|
40
40
|
return [...root, ...segments];
|
|
41
41
|
}
|
|
42
|
-
function normalizeJsonValue(value, path, seen) {
|
|
42
|
+
export function normalizeJsonValue(value, path, seen) {
|
|
43
43
|
const issues = [];
|
|
44
44
|
let root;
|
|
45
45
|
const stack = [
|
|
@@ -232,7 +232,7 @@ function normalizeScalarAtom(contract, field, value, origin, path, allowNull) {
|
|
|
232
232
|
case "decimal":
|
|
233
233
|
if (origin === "application") {
|
|
234
234
|
normalized =
|
|
235
|
-
value instanceof
|
|
235
|
+
value instanceof AvDecimal
|
|
236
236
|
? { ok: true, value }
|
|
237
237
|
: { ok: false, issues: [typeIssue(path, "an Aventara Decimal")] };
|
|
238
238
|
}
|
|
@@ -244,7 +244,7 @@ function normalizeScalarAtom(contract, field, value, origin, path, allowNull) {
|
|
|
244
244
|
}
|
|
245
245
|
else {
|
|
246
246
|
try {
|
|
247
|
-
normalized = { ok: true, value: new
|
|
247
|
+
normalized = { ok: true, value: new AvDecimal(value) };
|
|
248
248
|
}
|
|
249
249
|
catch {
|
|
250
250
|
normalized = {
|
|
@@ -385,7 +385,6 @@ function normalizeWrittenValue(contract, field, value, origin, path, issues) {
|
|
|
385
385
|
issues.push(...result.issues);
|
|
386
386
|
return undefined;
|
|
387
387
|
}
|
|
388
|
-
issues.push(...jsonShapeIssues(field, result.value, path));
|
|
389
388
|
return result.value;
|
|
390
389
|
}
|
|
391
390
|
function normalizeWrittenElement(contract, field, value, origin, path, issues) {
|
|
@@ -394,7 +393,6 @@ function normalizeWrittenElement(contract, field, value, origin, path, issues) {
|
|
|
394
393
|
issues.push(...result.issues);
|
|
395
394
|
return undefined;
|
|
396
395
|
}
|
|
397
|
-
issues.push(...jsonShapeIssues(field, result.value, path, "entry"));
|
|
398
396
|
return result.value;
|
|
399
397
|
}
|
|
400
398
|
const SCALAR_ATOM_COPIERS = {
|
|
@@ -679,9 +677,9 @@ function normalizeRelationMutation(contract, edge, value, origin, path, issues,
|
|
|
679
677
|
const normalized = cloneRecord(value);
|
|
680
678
|
for (const [directive, operand] of Object.entries(value)) {
|
|
681
679
|
const directivePath = [...path, directive];
|
|
682
|
-
const
|
|
683
|
-
|
|
684
|
-
|
|
680
|
+
const listed = edge.cardinality === "many" && Array.isArray(operand);
|
|
681
|
+
const entries = listed ? operand : [operand];
|
|
682
|
+
const entryPath = (index) => listed ? [...directivePath, index] : directivePath;
|
|
685
683
|
if (directive === "$create") {
|
|
686
684
|
normalized[directive] =
|
|
687
685
|
edge.cardinality === "many" && Array.isArray(operand)
|
|
@@ -714,8 +712,8 @@ function normalizeRelationMutation(contract, edge, value, origin, path, issues,
|
|
|
714
712
|
}
|
|
715
713
|
return {
|
|
716
714
|
...entry,
|
|
717
|
-
where: normalizeUniqueSelector(contract, edge.target, entry.where, origin, [...
|
|
718
|
-
create: normalizeMutationData(contract, edge.target, entry.create, origin, [...
|
|
715
|
+
where: normalizeUniqueSelector(contract, edge.target, entry.where, origin, [...entryPath(index), "where"], issues, references),
|
|
716
|
+
create: normalizeMutationData(contract, edge.target, entry.create, origin, [...entryPath(index), "create"], issues, references),
|
|
719
717
|
};
|
|
720
718
|
});
|
|
721
719
|
normalized[directive] =
|
|
@@ -733,10 +731,10 @@ function normalizeRelationMutation(contract, edge, value, origin, path, issues,
|
|
|
733
731
|
...entry,
|
|
734
732
|
...(entry.where !== undefined
|
|
735
733
|
? {
|
|
736
|
-
where: normalizeWhere(contract, edge.target, entry.where, origin, [...
|
|
734
|
+
where: normalizeWhere(contract, edge.target, entry.where, origin, [...entryPath(index), "where"], issues, references),
|
|
737
735
|
}
|
|
738
736
|
: {}),
|
|
739
|
-
data: normalizeMutationData(contract, edge.target, entry.data, origin, [...
|
|
737
|
+
data: normalizeMutationData(contract, edge.target, entry.data, origin, [...entryPath(index), "data"], issues, references),
|
|
740
738
|
};
|
|
741
739
|
});
|
|
742
740
|
normalized[directive] =
|
|
@@ -752,7 +750,7 @@ function normalizeRelationMutation(contract, edge, value, origin, path, issues,
|
|
|
752
750
|
}
|
|
753
751
|
return {
|
|
754
752
|
...entry,
|
|
755
|
-
where: normalizeWhere(contract, edge.target, entry.where, origin, [...
|
|
753
|
+
where: normalizeWhere(contract, edge.target, entry.where, origin, [...entryPath(index), "where"], issues, references),
|
|
756
754
|
};
|
|
757
755
|
});
|
|
758
756
|
normalized[directive] =
|
|
@@ -770,11 +768,11 @@ function normalizeRelationMutation(contract, edge, value, origin, path, issues,
|
|
|
770
768
|
...entry,
|
|
771
769
|
...(entry.where !== undefined
|
|
772
770
|
? {
|
|
773
|
-
where: normalizeUniqueSelector(contract, edge.target, entry.where, origin, [...
|
|
771
|
+
where: normalizeUniqueSelector(contract, edge.target, entry.where, origin, [...entryPath(index), "where"], issues, references),
|
|
774
772
|
}
|
|
775
773
|
: {}),
|
|
776
|
-
create: normalizeMutationData(contract, edge.target, entry.create, origin, [...
|
|
777
|
-
update: normalizeMutationData(contract, edge.target, entry.update, origin, [...
|
|
774
|
+
create: normalizeMutationData(contract, edge.target, entry.create, origin, [...entryPath(index), "create"], issues, references),
|
|
775
|
+
update: normalizeMutationData(contract, edge.target, entry.update, origin, [...entryPath(index), "update"], issues, references),
|
|
778
776
|
};
|
|
779
777
|
});
|
|
780
778
|
normalized[directive] =
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
import type { TransactionReference } from "./transaction-reference.js";
|
|
5
|
-
import type { TransactionCommittedResponse } from "./transaction-response.js";
|
|
1
|
+
import type { AvOperationIdentity } from "../operations/operation-identity.js";
|
|
2
|
+
import type { AvExecutionOptions } from "../runtime/execution-options.js";
|
|
3
|
+
import type { AvTransactionReference } from "./transaction-reference.js";
|
|
6
4
|
/** An operation fingerprint: `fp1:` and a hash of the operation and its arguments. */
|
|
7
5
|
export type OperationFingerprint = `fp1:${string}`;
|
|
8
6
|
/** One serializable transaction-plan operation node. */
|
|
9
|
-
export type DeferredOperation =
|
|
7
|
+
export type DeferredOperation = AvOperationIdentity & {
|
|
10
8
|
readonly resource: string;
|
|
11
9
|
readonly args: unknown;
|
|
12
10
|
readonly fingerprint: OperationFingerprint;
|
|
@@ -17,34 +15,51 @@ export type TransactionPlan = {
|
|
|
17
15
|
};
|
|
18
16
|
declare const OPERATION_RESULT: unique symbol;
|
|
19
17
|
declare const OPERATION_HANDLE: unique symbol;
|
|
18
|
+
/** The origin a handle's builder gives it: `appTx`'s or `clientTx`'s. */
|
|
19
|
+
type HandleOrigin = "application" | "client";
|
|
20
|
+
type AnyOrigin = any;
|
|
20
21
|
/** Standard-library shapes that are objects but never a projected result row. */
|
|
21
22
|
export type BuiltinNonRow = Date | RegExp | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown> | PromiseLike<unknown> | ArrayBufferView;
|
|
22
23
|
/**
|
|
23
24
|
* The single row behind a result type, or `never` when the result is not one
|
|
24
25
|
* referenceable row.
|
|
25
26
|
*/
|
|
26
|
-
export type
|
|
27
|
+
export type AvSingleRowResult<T> = NonNullable<T> extends readonly unknown[] ? never : NonNullable<T> extends (...args: never[]) => unknown ? never : NonNullable<T> extends BuiltinNonRow ? never : NonNullable<T> extends object ? Extract<keyof NonNullable<T>, string> extends never ? never : NonNullable<T> : never;
|
|
27
28
|
/** The field names a result row can be referenced by. */
|
|
28
|
-
export type
|
|
29
|
+
export type AvReferenceableField<T> = Extract<keyof AvSingleRowResult<T>, string>;
|
|
29
30
|
/** Builds a `$ref` to one field of this handle's row, typed as that field. */
|
|
30
|
-
export type
|
|
31
|
+
export type AvReferenceBuilder<T> = <F extends AvReferenceableField<T>>(field: F) => AvTransactionReference<AvSingleRowResult<T>[F]>;
|
|
31
32
|
/** Contributes `$ref` only where the result is a referenceable single row. */
|
|
32
|
-
export type
|
|
33
|
-
|
|
33
|
+
export type AvOperationReferenceSurface<T> = [AvSingleRowResult<T>] extends [
|
|
34
|
+
never
|
|
35
|
+
] ? {} : {
|
|
36
|
+
readonly $ref: AvReferenceBuilder<T>;
|
|
34
37
|
};
|
|
35
|
-
/**
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
/**
|
|
39
|
+
* The opaque part of every deferred-operation handle: the result type `T` its
|
|
40
|
+
* transaction slot resolves to, and the origin of the builder that made it
|
|
41
|
+
* (`appTx` is `"application"`, `clientTx` is `"client"`; left out, either).
|
|
42
|
+
* Type-level only: a handle holds neither at runtime.
|
|
43
|
+
*/
|
|
44
|
+
export interface AvOperationHandle<T, Origin extends HandleOrigin = AnyOrigin> {
|
|
45
|
+
readonly [OPERATION_HANDLE]: Origin;
|
|
38
46
|
readonly [OPERATION_RESULT]?: T;
|
|
39
|
-
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* An opaque deferred-operation handle: its result type and origin
|
|
50
|
+
* ({@link AvOperationHandle}), and `$ref` where the result is one row.
|
|
51
|
+
*/
|
|
52
|
+
export type AvOperation<T, Origin extends HandleOrigin = AnyOrigin> = AvOperationHandle<T, Origin> & AvOperationReferenceSurface<T>;
|
|
40
53
|
/** Ordered results of a tuple of handles, positionally typed. */
|
|
41
|
-
export type
|
|
42
|
-
readonly [I in keyof Ops]: Ops[I] extends
|
|
54
|
+
export type AvTransactionResults<Ops extends readonly AvOperation<unknown>[]> = {
|
|
55
|
+
readonly [I in keyof Ops]: Ops[I] extends AvOperation<infer R> ? R : never;
|
|
43
56
|
};
|
|
44
57
|
/**
|
|
45
58
|
* `framework.transaction`'s type. It infers the handle tuple without `as const`
|
|
46
|
-
* and resolves
|
|
47
|
-
*
|
|
59
|
+
* and resolves each handle's result in plan order once the transaction
|
|
60
|
+
* committed, or throws its failure as the `AvError` subclass of the code's class
|
|
61
|
+
* (`cause.operation` names the failing step). The handles are all `appTx`
|
|
62
|
+
* handles or all `clientTx` handles: a list that mixes them is a type error.
|
|
48
63
|
*/
|
|
49
|
-
export type
|
|
64
|
+
export type AvTransactionRunner = <const Ops extends readonly AvOperation<unknown, "application">[] | readonly AvOperation<unknown, "client">[]>(operations: Ops, options?: AvExecutionOptions) => Promise<AvTransactionResults<Ops>>;
|
|
50
65
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { AvContract } from "../contracts/contract.js";
|
|
2
|
+
import type { AvOperationIdentity } from "../operations/operation-identity.js";
|
|
3
3
|
import type { SemanticOperationArguments } from "../operations/operation-validator.js";
|
|
4
4
|
/** Encodes validated application arguments into the wire scalar form. */
|
|
5
|
-
export declare function encodeOperationArgumentsForWire(contract:
|
|
5
|
+
export declare function encodeOperationArgumentsForWire(contract: AvContract, operation: AvOperationIdentity & {
|
|
6
6
|
readonly resource: string;
|
|
7
7
|
}, args: SemanticOperationArguments): unknown;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
|
|
2
2
|
import { encodeBase64 } from "../contracts/wire-scalar-format.js";
|
|
3
|
-
import {
|
|
3
|
+
import { AvDecimal } from "../runtime/decimal.js";
|
|
4
4
|
import { isRelationMutationDirective, RELATION_MUTATION_RECORD_SITES, } from "../runtime/mutation-planner.js";
|
|
5
5
|
import { isTransactionReferenceCandidate } from "./transaction-reference.js";
|
|
6
6
|
function isPlainRecord(value) {
|
|
@@ -27,7 +27,7 @@ function encodeScalarAtom(field, value) {
|
|
|
27
27
|
case "bigint":
|
|
28
28
|
return typeof value === "bigint" ? value.toString(10) : value;
|
|
29
29
|
case "decimal":
|
|
30
|
-
return value instanceof
|
|
30
|
+
return value instanceof AvDecimal ? value.toString() : value;
|
|
31
31
|
case "datetime":
|
|
32
32
|
return value instanceof Date ? value.toISOString() : value;
|
|
33
33
|
case "bytes":
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { AvAdapterSqlValue } from "../adapters/adapter-sql-statement.js";
|
|
2
|
+
import type { AvContract } from "../contracts/contract.js";
|
|
3
|
+
import type { AvScalarField } from "../contracts/field.js";
|
|
4
|
+
import type { AvCallerDataError } from "../runtime/caller-data.copier.js";
|
|
5
|
+
import type { AvOperation } from "./deferred-operation.js";
|
|
6
|
+
import type { AvTransactionReference } from "./transaction-reference.js";
|
|
7
|
+
/**
|
|
8
|
+
* One value an `appTx.$sql` template binds: a primitive, a `Date`, an `AvDecimal`, a
|
|
9
|
+
* `Uint8Array`, a JSON value (a plain object or array, bound as JSON text — cast it,
|
|
10
|
+
* `${value}::jsonb`), or a `$ref` to an earlier step's field, resolved when the
|
|
11
|
+
* earlier steps have run and then bound like any other value.
|
|
12
|
+
*/
|
|
13
|
+
export type SqlStatementValue = AvAdapterSqlValue | AvTransactionReference;
|
|
14
|
+
/**
|
|
15
|
+
* `framework.appTx.$sql`: a developer SQL step, written only as a tagged template —
|
|
16
|
+
* ``framework.appTx.$sql`select pgmq.send('jobs', jsonb_build_object('id', ${ref}))` ``.
|
|
17
|
+
* Every interpolated value is bound as a parameter, never spliced into the text, so
|
|
18
|
+
* the text is static: a table or column name cannot come from a value.
|
|
19
|
+
*
|
|
20
|
+
* The step runs in plan order inside the same database transaction as the other
|
|
21
|
+
* steps; its entry in the committed `data` is the rows the statement returned,
|
|
22
|
+
* typed `Row[]` (`unknown[]` unless `Row` is given). A later step cannot `$ref` a
|
|
23
|
+
* SQL step's rows. No guard, pipe, hook, interceptor or filter runs around it: it
|
|
24
|
+
* has no Resource or operation for one to wrap.
|
|
25
|
+
*/
|
|
26
|
+
export type SqlStatementBuilder = <Row = unknown>(strings: TemplateStringsArray, ...values: readonly SqlStatementValue[]) => AvOperation<Row[], "application">;
|
|
27
|
+
/** One value of a planned SQL step, as the typed runner bound it. */
|
|
28
|
+
export type PlannedSqlValue = {
|
|
29
|
+
readonly kind: "value";
|
|
30
|
+
readonly value: unknown;
|
|
31
|
+
}
|
|
32
|
+
/** A `$ref` placeholder standing as the whole value: the source's position and field. */
|
|
33
|
+
| {
|
|
34
|
+
readonly kind: "reference";
|
|
35
|
+
readonly operation: number;
|
|
36
|
+
readonly field: string;
|
|
37
|
+
}
|
|
38
|
+
/** A `$ref` placeholder found inside a value, at `path` within it: refused. */
|
|
39
|
+
| {
|
|
40
|
+
readonly kind: "misplaced-reference";
|
|
41
|
+
readonly path: readonly (string | number)[];
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* A SQL step as the typed runner hands it to the validator, unvalidated: the
|
|
45
|
+
* template's static text (`undefined` when the call was no genuine tagged
|
|
46
|
+
* template), its values with each `$ref` bound to its source's position, or why the
|
|
47
|
+
* builder could not copy the values.
|
|
48
|
+
*/
|
|
49
|
+
export type PlannedSqlStatement = {
|
|
50
|
+
readonly strings: readonly string[] | undefined;
|
|
51
|
+
readonly values: readonly PlannedSqlValue[];
|
|
52
|
+
readonly refused?: AvCallerDataError;
|
|
53
|
+
};
|
|
54
|
+
/** One validated value of a SQL step: bound as it is, or resolved from a `$ref`. */
|
|
55
|
+
export type ValidatedSqlValue = {
|
|
56
|
+
readonly kind: "value";
|
|
57
|
+
readonly value: AvAdapterSqlValue;
|
|
58
|
+
} | {
|
|
59
|
+
readonly kind: "reference";
|
|
60
|
+
readonly operation: number;
|
|
61
|
+
readonly field: string;
|
|
62
|
+
/** The source field, under its own step's Contract: what the value is read as. */
|
|
63
|
+
readonly source: AvScalarField<AvContract>;
|
|
64
|
+
};
|
|
65
|
+
/** A SQL step the Framework Validation Layer accepted. */
|
|
66
|
+
export type ValidatedSqlStatement = {
|
|
67
|
+
readonly kind: "sql";
|
|
68
|
+
readonly index: number;
|
|
69
|
+
readonly strings: readonly string[];
|
|
70
|
+
readonly values: readonly ValidatedSqlValue[];
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* The static text of a genuine tagged template, read once and copied, or
|
|
74
|
+
* `undefined` when `strings` is not one or does not fit `valueCount` values.
|
|
75
|
+
* Total: a hostile value is `undefined`, never a throw.
|
|
76
|
+
*/
|
|
77
|
+
export declare function readSqlTemplate(strings: unknown, valueCount: number): readonly string[] | undefined;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
function ownData(target, key) {
|
|
2
|
+
const descriptor = Object.getOwnPropertyDescriptor(target, key);
|
|
3
|
+
return descriptor !== undefined && "value" in descriptor
|
|
4
|
+
? descriptor.value
|
|
5
|
+
: undefined;
|
|
6
|
+
}
|
|
7
|
+
function frozenStrings(value, length) {
|
|
8
|
+
if (!Array.isArray(value) || !Object.isFrozen(value)) {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
const size = ownData(value, "length");
|
|
12
|
+
if (typeof size !== "number" ||
|
|
13
|
+
size < 1 ||
|
|
14
|
+
(length !== undefined && size !== length)) {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
const strings = [];
|
|
18
|
+
for (let index = 0; index < size; index += 1) {
|
|
19
|
+
const entry = ownData(value, String(index));
|
|
20
|
+
if (typeof entry !== "string") {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
strings.push(entry);
|
|
24
|
+
}
|
|
25
|
+
return strings;
|
|
26
|
+
}
|
|
27
|
+
export function readSqlTemplate(strings, valueCount) {
|
|
28
|
+
try {
|
|
29
|
+
if (typeof strings !== "object" || strings === null) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
const raw = Object.getOwnPropertyDescriptor(strings, "raw");
|
|
33
|
+
if (raw === undefined || raw.enumerable || !("value" in raw)) {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
const cooked = frozenStrings(strings, valueCount + 1);
|
|
37
|
+
if (cooked === undefined) {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
return frozenStrings(raw.value, cooked.length) === undefined
|
|
41
|
+
? undefined
|
|
42
|
+
: Object.freeze(cooked);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { AvAdapterSqlValue } from "../adapters/adapter-sql-statement.js";
|
|
2
|
+
import type { AvValidationIssue } from "../operations/validation-code.js";
|
|
3
|
+
import type { MisuseReporter } from "../runtime/misuse-reporter.js";
|
|
4
|
+
import type { AvOperationFailureResponse } from "../runtime/operation-response.js";
|
|
5
|
+
import type { PlannedSqlStatement, ValidatedSqlStatement } from "./sql-statement.js";
|
|
6
|
+
import type { ValidatedTransactionStep } from "./transaction-plan-validator.js";
|
|
7
|
+
type Path = readonly (string | number)[];
|
|
8
|
+
export type SqlStatementValidation = {
|
|
9
|
+
readonly ok: true;
|
|
10
|
+
readonly statement: ValidatedSqlStatement;
|
|
11
|
+
} | {
|
|
12
|
+
readonly ok: false;
|
|
13
|
+
readonly response: AvOperationFailureResponse;
|
|
14
|
+
};
|
|
15
|
+
/** What validating a SQL step needs from the plan around it. */
|
|
16
|
+
export type SqlStatementValidationContext = {
|
|
17
|
+
/** The step's position in the plan. */
|
|
18
|
+
readonly index: number;
|
|
19
|
+
/** The steps validated before it, by position. */
|
|
20
|
+
readonly earlier: readonly ValidatedTransactionStep[];
|
|
21
|
+
/** Whether the Adapter declares `sqlStatements`. */
|
|
22
|
+
readonly available: boolean;
|
|
23
|
+
readonly misuse: MisuseReporter;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* One bindable value of a SQL step, in its runtime form, or the issues that refuse
|
|
27
|
+
* it: a primitive (a `number` only when finite), a valid `Date`, an `AvDecimal`, a
|
|
28
|
+
* `Uint8Array`, or a JSON value — a plain object or array, held to the same rules
|
|
29
|
+
* as a `json` field's value. `undefined` and anything else are no value to bind.
|
|
30
|
+
*/
|
|
31
|
+
export declare function normalizeSqlValue(value: unknown, path: Path): {
|
|
32
|
+
readonly ok: true;
|
|
33
|
+
readonly value: AvAdapterSqlValue;
|
|
34
|
+
} | {
|
|
35
|
+
readonly ok: false;
|
|
36
|
+
readonly issues: readonly AvValidationIssue[];
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Validates one SQL step: the Adapter runs SQL statements, the call was a genuine
|
|
40
|
+
* tagged template, its values could be copied, every value is bindable, and every
|
|
41
|
+
* `$ref` stands as a whole value and reads one field of an earlier single-row step.
|
|
42
|
+
*/
|
|
43
|
+
export declare function validateSqlStatement(statement: PlannedSqlStatement, context: SqlStatementValidationContext): SqlStatementValidation;
|
|
44
|
+
export {};
|