@aventara/core 1.0.0-rc.0 → 1.0.0-rc.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/CHANGELOG.md +1434 -0
- package/ERRORS.md +142 -0
- package/README.md +247 -57
- package/dist/adapters/adapter-discovery-diagnostic.d.ts +4 -4
- package/dist/adapters/adapter-discovery-diagnostic.guidance.d.ts +6 -0
- package/dist/adapters/adapter-discovery-diagnostic.guidance.js +7 -0
- package/dist/adapters/adapter-field.d.ts +25 -11
- package/dist/adapters/adapter-identifier.d.ts +6 -6
- package/dist/adapters/adapter-model.d.ts +18 -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 +59 -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-diagnostic.guidance.d.ts +6 -0
- package/dist/compiler/contract-compiler-diagnostic.guidance.js +97 -0
- package/dist/compiler/contract.compiler.d.ts +18 -18
- package/dist/compiler/contract.compiler.js +637 -442
- 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/computed-fields.d.ts +62 -0
- package/dist/config/computed-fields.js +80 -0
- package/dist/config/config-diagnostic.d.ts +11 -4
- package/dist/config/config-diagnostic.guidance.d.ts +6 -0
- package/dist/config/config-diagnostic.guidance.js +32 -0
- 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 +308 -0
- package/dist/config/field-compute.resolver.d.ts +21 -0
- package/dist/config/field-compute.resolver.js +123 -0
- package/dist/config/field-pipeline-config.d.ts +47 -0
- package/dist/config/forced-operation.validator.d.ts +10 -0
- package/dist/config/forced-operation.validator.js +66 -0
- package/dist/config/framework-config.d.ts +111 -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 +122 -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 +21 -12
- package/dist/contracts/capability.js +2 -0
- package/dist/contracts/client-contract-structure.validator.d.ts +388 -63
- package/dist/contracts/client-contract-structure.validator.js +156 -10
- package/dist/contracts/contract-canonicalizer.d.ts +26 -3
- package/dist/contracts/contract-canonicalizer.js +156 -29
- 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 +81 -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 +19 -10
- package/dist/framework/framework-construction.error.js +7 -3
- package/dist/framework/framework.d.ts +47 -23
- package/dist/framework/framework.factory.d.ts +8 -6
- package/dist/framework/framework.factory.js +49 -22
- package/dist/framework/operation-facade.d.ts +123 -52
- package/dist/framework/operation-facade.js +9 -1
- package/dist/index.d.ts +57 -50
- package/dist/index.js +7 -6
- package/dist/internal.d.ts +17 -10
- package/dist/internal.js +4 -1
- package/dist/operations/database-refusal.d.ts +51 -0
- package/dist/operations/database-refusal.js +45 -0
- package/dist/operations/operation-arguments.d.ts +343 -207
- 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 +99 -6
- 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.guidance.d.ts +6 -0
- package/dist/operations/validation-code.guidance.js +90 -0
- package/dist/operations/validation-code.js +4 -0
- package/dist/operations/write-scope.resolver.d.ts +10 -6
- package/dist/operations/write-scope.resolver.js +2 -0
- 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 +91 -17
- 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 +22 -5
- package/dist/runtime/caller-data.copier.js +31 -14
- package/dist/runtime/caller-data.door.d.ts +17 -11
- 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 +76 -50
- package/dist/runtime/computed-value.error.d.ts +7 -6
- package/dist/runtime/computed-value.error.js +5 -4
- 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 +44 -79
- package/dist/runtime/create-requirement.js +213 -73
- package/dist/runtime/decimal.d.ts +2 -2
- package/dist/runtime/decimal.js +1 -1
- package/dist/runtime/diagnostics-reporter.d.ts +54 -27
- package/dist/runtime/diagnostics-reporter.js +24 -0
- package/dist/runtime/error-boundary.d.ts +65 -8
- package/dist/runtime/error-boundary.js +49 -19
- package/dist/runtime/error-guidance.d.ts +12 -0
- package/dist/runtime/error-guidance.js +1 -0
- package/dist/runtime/error.catalog.d.ts +49 -0
- package/dist/runtime/error.catalog.js +49 -0
- 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 +37 -0
- package/dist/runtime/field-stage.runtime.js +147 -0
- package/dist/runtime/field-validator.runtime.d.ts +19 -0
- package/dist/runtime/field-validator.runtime.js +92 -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 +11 -6
- package/dist/runtime/level-lifecycle.runtime.d.ts +25 -0
- package/dist/runtime/level-lifecycle.runtime.js +39 -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 +48 -35
- package/dist/runtime/nested-write.walker.d.ts +32 -0
- package/dist/runtime/nested-write.walker.js +73 -0
- package/dist/runtime/operation-code.guidance.d.ts +6 -0
- package/dist/runtime/operation-code.guidance.js +167 -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 +127 -25
- package/dist/runtime/operation-runtime.js +441 -78
- 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 +16 -6
- package/dist/runtime/pipe-output.validator.d.ts +43 -18
- package/dist/runtime/pipe-output.validator.js +15 -13
- package/dist/runtime/pipeline.d.ts +223 -34
- package/dist/runtime/readonly-value.d.ts +43 -0
- package/dist/runtime/readonly-value.js +150 -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 +35 -16
- package/dist/runtime/scalar-runtime.js +102 -34
- package/dist/runtime/unsent-value.normalizer.d.ts +15 -0
- package/dist/runtime/unsent-value.normalizer.js +128 -0
- 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/operation-fingerprint.js +2 -2
- package/dist/transactions/sql-statement.d.ts +85 -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 +167 -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 +169 -32
- package/dist/transactions/transaction-plan-validator.d.ts +45 -20
- package/dist/transactions/transaction-plan-validator.js +96 -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 +76 -4
- package/dist/transactions/transaction-reference-validator.js +129 -71
- package/dist/transactions/transaction-reference.d.ts +13 -13
- package/dist/transactions/transaction-reference.js +5 -0
- 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 +191 -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 +82 -0
- package/dist/transactions/transaction-stage.runtime.js +126 -0
- package/package.json +9 -7
- 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,13 +1,20 @@
|
|
|
1
|
+
import { shapeOfField } from "../avz/json-shape.registry.js";
|
|
2
|
+
import { AVZ_FORMATS } from "../config/framework-field-definition.js";
|
|
3
|
+
import { FILTER_MODES, } from "../contracts/capability.js";
|
|
1
4
|
import { lookupField, lookupOwn, lookupResource, } from "../contracts/contract-lookup.js";
|
|
2
5
|
import { decodeBase64, WIRE_SCALAR_PATTERNS, } from "../contracts/wire-scalar-format.js";
|
|
3
|
-
import { shapeOfField } from "../json/json-shape.registry.js";
|
|
4
6
|
import { routeTransactionReferenceCandidate, } from "../transactions/transaction-reference.js";
|
|
5
|
-
import {
|
|
7
|
+
import { AvDecimal } from "./decimal.js";
|
|
8
|
+
import { fieldCheckIssues } from "./field-check.evaluator.js";
|
|
6
9
|
const INT_MIN = -(2 ** 31);
|
|
7
10
|
const INT_MAX = 2 ** 31 - 1;
|
|
8
11
|
const BIGINT_MIN = -(2n ** 63n);
|
|
9
12
|
const BIGINT_MAX = 2n ** 63n - 1n;
|
|
10
13
|
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
14
|
+
const NAMED_FORMATS = new Set(AVZ_FORMATS);
|
|
15
|
+
function isNamedFormat(format) {
|
|
16
|
+
return NAMED_FORMATS.has(format);
|
|
17
|
+
}
|
|
11
18
|
function isRecord(value) {
|
|
12
19
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
13
20
|
}
|
|
@@ -24,6 +31,10 @@ function issue(code, path, message) {
|
|
|
24
31
|
function typeIssue(path, expected) {
|
|
25
32
|
return issue("V1001", path, `Value must be ${expected}.`);
|
|
26
33
|
}
|
|
34
|
+
export const UNSENT_READ_VALUE_MESSAGE = "Value must not be undefined: it would be left out, and the request would reach more rows.";
|
|
35
|
+
export function unsentReadValueIssue(path) {
|
|
36
|
+
return issue("V1001", path, UNSENT_READ_VALUE_MESSAGE);
|
|
37
|
+
}
|
|
27
38
|
function formatIssue(path, expected) {
|
|
28
39
|
return issue("V1003", path, `Value must use ${expected}.`);
|
|
29
40
|
}
|
|
@@ -39,7 +50,7 @@ function materializeJsonPath(root, link) {
|
|
|
39
50
|
segments.reverse();
|
|
40
51
|
return [...root, ...segments];
|
|
41
52
|
}
|
|
42
|
-
function normalizeJsonValue(value, path, seen) {
|
|
53
|
+
export function normalizeJsonValue(value, path, seen) {
|
|
43
54
|
const issues = [];
|
|
44
55
|
let root;
|
|
45
56
|
const stack = [
|
|
@@ -83,18 +94,14 @@ function normalizeJsonValue(value, path, seen) {
|
|
|
83
94
|
const normalized = [];
|
|
84
95
|
task.emit(normalized);
|
|
85
96
|
stack.push({ kind: "leave", container: current });
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
entries.push([index, entry]);
|
|
89
|
-
});
|
|
90
|
-
for (let cursor = entries.length - 1; cursor >= 0; cursor -= 1) {
|
|
91
|
-
const entry = entries[cursor];
|
|
97
|
+
for (let index = current.length - 1; index >= 0; index -= 1) {
|
|
98
|
+
const entry = current[index];
|
|
92
99
|
stack.push({
|
|
93
100
|
kind: "visit",
|
|
94
|
-
value: entry
|
|
95
|
-
link: { parent: task.link, segment:
|
|
101
|
+
value: entry === undefined ? null : entry,
|
|
102
|
+
link: { parent: task.link, segment: index },
|
|
96
103
|
emit: (child) => {
|
|
97
|
-
normalized
|
|
104
|
+
normalized[index] = child;
|
|
98
105
|
},
|
|
99
106
|
});
|
|
100
107
|
}
|
|
@@ -112,7 +119,7 @@ function normalizeJsonValue(value, path, seen) {
|
|
|
112
119
|
const normalized = {};
|
|
113
120
|
task.emit(normalized);
|
|
114
121
|
stack.push({ kind: "leave", container: current });
|
|
115
|
-
const entries = Object.entries(current);
|
|
122
|
+
const entries = Object.entries(current).filter((entry) => entry[1] !== undefined);
|
|
116
123
|
for (let cursor = entries.length - 1; cursor >= 0; cursor -= 1) {
|
|
117
124
|
const entry = entries[cursor];
|
|
118
125
|
stack.push({
|
|
@@ -232,7 +239,7 @@ function normalizeScalarAtom(contract, field, value, origin, path, allowNull) {
|
|
|
232
239
|
case "decimal":
|
|
233
240
|
if (origin === "application") {
|
|
234
241
|
normalized =
|
|
235
|
-
value instanceof
|
|
242
|
+
value instanceof AvDecimal
|
|
236
243
|
? { ok: true, value }
|
|
237
244
|
: { ok: false, issues: [typeIssue(path, "an Aventara Decimal")] };
|
|
238
245
|
}
|
|
@@ -244,7 +251,7 @@ function normalizeScalarAtom(contract, field, value, origin, path, allowNull) {
|
|
|
244
251
|
}
|
|
245
252
|
else {
|
|
246
253
|
try {
|
|
247
|
-
normalized = { ok: true, value: new
|
|
254
|
+
normalized = { ok: true, value: new AvDecimal(value) };
|
|
248
255
|
}
|
|
249
256
|
catch {
|
|
250
257
|
normalized = {
|
|
@@ -359,9 +366,21 @@ export function normalizeScalarFieldValue(contract, field, value, origin, path)
|
|
|
359
366
|
});
|
|
360
367
|
return issues.length > 0
|
|
361
368
|
? { ok: false, issues }
|
|
362
|
-
: { ok: true, value: normalized };
|
|
369
|
+
: heldToFormat(field, { ok: true, value: normalized }, origin, path);
|
|
370
|
+
}
|
|
371
|
+
return heldToFormat(field, normalizeScalarAtom(contract, field, value, origin === "runtime" ? "application" : origin, path, field.nullable), origin, path);
|
|
372
|
+
}
|
|
373
|
+
function heldToFormat(field, normalized, origin, path) {
|
|
374
|
+
const format = field.format;
|
|
375
|
+
if (origin !== "runtime" ||
|
|
376
|
+
!normalized.ok ||
|
|
377
|
+
format === undefined ||
|
|
378
|
+
format === "uuid" ||
|
|
379
|
+
!isNamedFormat(format)) {
|
|
380
|
+
return normalized;
|
|
363
381
|
}
|
|
364
|
-
|
|
382
|
+
const issues = fieldCheckIssues([{ check: "string_format", format }], normalized.value, "string", path, field.list);
|
|
383
|
+
return issues.length === 0 ? normalized : { ok: false, issues };
|
|
365
384
|
}
|
|
366
385
|
export function jsonShapeIssues(field, value, path, position = "value") {
|
|
367
386
|
if (field.json === undefined || value === null || value === undefined) {
|
|
@@ -385,7 +404,6 @@ function normalizeWrittenValue(contract, field, value, origin, path, issues) {
|
|
|
385
404
|
issues.push(...result.issues);
|
|
386
405
|
return undefined;
|
|
387
406
|
}
|
|
388
|
-
issues.push(...jsonShapeIssues(field, result.value, path));
|
|
389
407
|
return result.value;
|
|
390
408
|
}
|
|
391
409
|
function normalizeWrittenElement(contract, field, value, origin, path, issues) {
|
|
@@ -394,7 +412,6 @@ function normalizeWrittenElement(contract, field, value, origin, path, issues) {
|
|
|
394
412
|
issues.push(...result.issues);
|
|
395
413
|
return undefined;
|
|
396
414
|
}
|
|
397
|
-
issues.push(...jsonShapeIssues(field, result.value, path, "entry"));
|
|
398
415
|
return result.value;
|
|
399
416
|
}
|
|
400
417
|
const SCALAR_ATOM_COPIERS = {
|
|
@@ -429,6 +446,11 @@ export function copyScalarFieldValue(field, value) {
|
|
|
429
446
|
function normalizeListElement(contract, field, value, origin, path) {
|
|
430
447
|
return normalizeScalarAtom(contract, field, value, origin, path, false);
|
|
431
448
|
}
|
|
449
|
+
function normalizeFilterEntry(contract, field, value, origin, path) {
|
|
450
|
+
return value === undefined
|
|
451
|
+
? { ok: false, issues: [unsentReadValueIssue(path)] }
|
|
452
|
+
: normalizeListElement(contract, field, value, origin, path);
|
|
453
|
+
}
|
|
432
454
|
function mergeResult(result, issues) {
|
|
433
455
|
if (result.ok) {
|
|
434
456
|
return result.value;
|
|
@@ -465,10 +487,40 @@ const NULL_OPERAND_OPERATORS = new Set([
|
|
|
465
487
|
"arrayStartsWith",
|
|
466
488
|
"arrayEndsWith",
|
|
467
489
|
]);
|
|
490
|
+
const KEYWORD_OPERANDS = Object.freeze({
|
|
491
|
+
mode: (operand, path, issues) => {
|
|
492
|
+
if (!FILTER_MODES.includes(operand)) {
|
|
493
|
+
issues.push(typeIssue(path, '"default", "sensitive" or "insensitive"'));
|
|
494
|
+
}
|
|
495
|
+
},
|
|
496
|
+
isEmpty: (operand, path, issues) => {
|
|
497
|
+
if (typeof operand !== "boolean") {
|
|
498
|
+
issues.push(typeIssue(path, "a boolean"));
|
|
499
|
+
}
|
|
500
|
+
},
|
|
501
|
+
path: (operand, path, issues) => {
|
|
502
|
+
if (!Array.isArray(operand)) {
|
|
503
|
+
issues.push(typeIssue(path, "an array of strings"));
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
for (let index = 0; index < operand.length; index += 1) {
|
|
507
|
+
if (operand[index] === undefined) {
|
|
508
|
+
issues.push(unsentReadValueIssue([...path, index]));
|
|
509
|
+
}
|
|
510
|
+
else if (typeof operand[index] !== "string") {
|
|
511
|
+
issues.push(typeIssue([...path, index], "a string"));
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
},
|
|
515
|
+
});
|
|
468
516
|
function normalizeScalarFilter(contract, field, value, origin, path, issues, references = false) {
|
|
469
517
|
if (isKeptReference(references, value)) {
|
|
470
518
|
return value;
|
|
471
519
|
}
|
|
520
|
+
if (value === undefined) {
|
|
521
|
+
issues.push(unsentReadValueIssue(path));
|
|
522
|
+
return value;
|
|
523
|
+
}
|
|
472
524
|
if (!isPlainRecord(value)) {
|
|
473
525
|
return mergeResult(normalizeScalarFieldValue(contract, field, value, origin, path), issues);
|
|
474
526
|
}
|
|
@@ -479,11 +531,17 @@ function normalizeScalarFilter(contract, field, value, origin, path, issues, ref
|
|
|
479
531
|
const normalized = cloneRecord(value);
|
|
480
532
|
for (const [operator, operand] of Object.entries(value)) {
|
|
481
533
|
const operandPath = [...path, operator];
|
|
534
|
+
if (operand === undefined) {
|
|
535
|
+
issues.push(unsentReadValueIssue(operandPath));
|
|
536
|
+
continue;
|
|
537
|
+
}
|
|
482
538
|
if (operand === null && !acceptsNullOperand(operator)) {
|
|
483
539
|
issues.push(typeIssue(operandPath, "non-null"));
|
|
484
540
|
continue;
|
|
485
541
|
}
|
|
486
|
-
|
|
542
|
+
const keyword = lookupOwn(KEYWORD_OPERANDS, operator);
|
|
543
|
+
if (keyword !== undefined) {
|
|
544
|
+
keyword(operand, operandPath, issues);
|
|
487
545
|
continue;
|
|
488
546
|
}
|
|
489
547
|
if (referenceOperandShape(operator) !== undefined &&
|
|
@@ -499,14 +557,14 @@ function normalizeScalarFilter(contract, field, value, origin, path, issues, ref
|
|
|
499
557
|
issues.push(typeIssue(operandPath, "an array"));
|
|
500
558
|
continue;
|
|
501
559
|
}
|
|
502
|
-
normalized[operator] = operand.map((entry, index) => mergeResult(
|
|
560
|
+
normalized[operator] = operand.map((entry, index) => mergeResult(normalizeFilterEntry(contract, field, entry, origin, [
|
|
503
561
|
...operandPath,
|
|
504
562
|
index,
|
|
505
563
|
]), issues));
|
|
506
564
|
continue;
|
|
507
565
|
}
|
|
508
566
|
if (operator === "has") {
|
|
509
|
-
normalized[operator] = mergeResult(
|
|
567
|
+
normalized[operator] = mergeResult(normalizeFilterEntry(contract, field, operand, origin, operandPath), issues);
|
|
510
568
|
continue;
|
|
511
569
|
}
|
|
512
570
|
if (operator === "hasEvery" || operator === "hasSome") {
|
|
@@ -514,7 +572,7 @@ function normalizeScalarFilter(contract, field, value, origin, path, issues, ref
|
|
|
514
572
|
issues.push(typeIssue(operandPath, "an array"));
|
|
515
573
|
continue;
|
|
516
574
|
}
|
|
517
|
-
normalized[operator] = operand.map((entry, index) => mergeResult(
|
|
575
|
+
normalized[operator] = operand.map((entry, index) => mergeResult(normalizeFilterEntry(contract, field, entry, origin, [
|
|
518
576
|
...operandPath,
|
|
519
577
|
index,
|
|
520
578
|
]), issues));
|
|
@@ -523,6 +581,12 @@ function normalizeScalarFilter(contract, field, value, origin, path, issues, ref
|
|
|
523
581
|
if ("scalar" in field.type &&
|
|
524
582
|
field.type.scalar === "json" &&
|
|
525
583
|
(operator.startsWith("string") || operator.startsWith("array"))) {
|
|
584
|
+
if (operator.startsWith("string")) {
|
|
585
|
+
if (typeof operand !== "string") {
|
|
586
|
+
issues.push(typeIssue(operandPath, "a string"));
|
|
587
|
+
}
|
|
588
|
+
continue;
|
|
589
|
+
}
|
|
526
590
|
const jsonResult = normalizeJsonValue(operand, operandPath, new Set());
|
|
527
591
|
normalized[operator] = mergeResult(jsonResult, issues);
|
|
528
592
|
continue;
|
|
@@ -587,6 +651,10 @@ function normalizeUniqueSelector(contract, resourceName, selector, origin, path,
|
|
|
587
651
|
const normalized = cloneRecord(selector);
|
|
588
652
|
for (const [fieldName, value] of Object.entries(selector)) {
|
|
589
653
|
const field = lookupField(resource, fieldName);
|
|
654
|
+
if (field?.kind === "scalar" && value === undefined) {
|
|
655
|
+
issues.push(unsentReadValueIssue([...path, fieldName]));
|
|
656
|
+
continue;
|
|
657
|
+
}
|
|
590
658
|
if (field?.kind === "scalar" && !isKeptReference(references, value)) {
|
|
591
659
|
normalized[fieldName] = mergeResult(normalizeScalarFieldValue(contract, field, value, origin, [
|
|
592
660
|
...path,
|
|
@@ -679,9 +747,9 @@ function normalizeRelationMutation(contract, edge, value, origin, path, issues,
|
|
|
679
747
|
const normalized = cloneRecord(value);
|
|
680
748
|
for (const [directive, operand] of Object.entries(value)) {
|
|
681
749
|
const directivePath = [...path, directive];
|
|
682
|
-
const
|
|
683
|
-
|
|
684
|
-
|
|
750
|
+
const listed = edge.cardinality === "many" && Array.isArray(operand);
|
|
751
|
+
const entries = listed ? operand : [operand];
|
|
752
|
+
const entryPath = (index) => listed ? [...directivePath, index] : directivePath;
|
|
685
753
|
if (directive === "$create") {
|
|
686
754
|
normalized[directive] =
|
|
687
755
|
edge.cardinality === "many" && Array.isArray(operand)
|
|
@@ -714,8 +782,8 @@ function normalizeRelationMutation(contract, edge, value, origin, path, issues,
|
|
|
714
782
|
}
|
|
715
783
|
return {
|
|
716
784
|
...entry,
|
|
717
|
-
where: normalizeUniqueSelector(contract, edge.target, entry.where, origin, [...
|
|
718
|
-
create: normalizeMutationData(contract, edge.target, entry.create, origin, [...
|
|
785
|
+
where: normalizeUniqueSelector(contract, edge.target, entry.where, origin, [...entryPath(index), "where"], issues, references),
|
|
786
|
+
create: normalizeMutationData(contract, edge.target, entry.create, origin, [...entryPath(index), "create"], issues, references),
|
|
719
787
|
};
|
|
720
788
|
});
|
|
721
789
|
normalized[directive] =
|
|
@@ -733,10 +801,10 @@ function normalizeRelationMutation(contract, edge, value, origin, path, issues,
|
|
|
733
801
|
...entry,
|
|
734
802
|
...(entry.where !== undefined
|
|
735
803
|
? {
|
|
736
|
-
where: normalizeWhere(contract, edge.target, entry.where, origin, [...
|
|
804
|
+
where: normalizeWhere(contract, edge.target, entry.where, origin, [...entryPath(index), "where"], issues, references),
|
|
737
805
|
}
|
|
738
806
|
: {}),
|
|
739
|
-
data: normalizeMutationData(contract, edge.target, entry.data, origin, [...
|
|
807
|
+
data: normalizeMutationData(contract, edge.target, entry.data, origin, [...entryPath(index), "data"], issues, references),
|
|
740
808
|
};
|
|
741
809
|
});
|
|
742
810
|
normalized[directive] =
|
|
@@ -752,7 +820,7 @@ function normalizeRelationMutation(contract, edge, value, origin, path, issues,
|
|
|
752
820
|
}
|
|
753
821
|
return {
|
|
754
822
|
...entry,
|
|
755
|
-
where: normalizeWhere(contract, edge.target, entry.where, origin, [...
|
|
823
|
+
where: normalizeWhere(contract, edge.target, entry.where, origin, [...entryPath(index), "where"], issues, references),
|
|
756
824
|
};
|
|
757
825
|
});
|
|
758
826
|
normalized[directive] =
|
|
@@ -770,11 +838,11 @@ function normalizeRelationMutation(contract, edge, value, origin, path, issues,
|
|
|
770
838
|
...entry,
|
|
771
839
|
...(entry.where !== undefined
|
|
772
840
|
? {
|
|
773
|
-
where: normalizeUniqueSelector(contract, edge.target, entry.where, origin, [...
|
|
841
|
+
where: normalizeUniqueSelector(contract, edge.target, entry.where, origin, [...entryPath(index), "where"], issues, references),
|
|
774
842
|
}
|
|
775
843
|
: {}),
|
|
776
|
-
create: normalizeMutationData(contract, edge.target, entry.create, origin, [...
|
|
777
|
-
update: normalizeMutationData(contract, edge.target, entry.update, origin, [...
|
|
844
|
+
create: normalizeMutationData(contract, edge.target, entry.create, origin, [...entryPath(index), "create"], issues, references),
|
|
845
|
+
update: normalizeMutationData(contract, edge.target, entry.update, origin, [...entryPath(index), "update"], issues, references),
|
|
778
846
|
};
|
|
779
847
|
});
|
|
780
848
|
normalized[directive] =
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AvContract } from "../contracts/contract.js";
|
|
2
|
+
import type { AvOperationFamily } from "../operations/operation-identity.js";
|
|
3
|
+
/**
|
|
4
|
+
* One operation's arguments with every write record's unsent fields removed — a
|
|
5
|
+
* field whose value is `undefined`, at any depth of nested write data the
|
|
6
|
+
* Contract's `maxNestingDepth` admits — and
|
|
7
|
+
* nothing else changed (see the module note): `where`, selectors and every other
|
|
8
|
+
* member are left as they are. The same object when nothing was unsent; otherwise
|
|
9
|
+
* a copy of each container on the way, never a write into `args`. Total over
|
|
10
|
+
* malformed input.
|
|
11
|
+
*/
|
|
12
|
+
export declare function withoutUnsentWriteValues(contract: AvContract, request: {
|
|
13
|
+
readonly resource: string;
|
|
14
|
+
readonly family: AvOperationFamily;
|
|
15
|
+
}, args: unknown): unknown;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
|
|
2
|
+
import { isPlainRecord, WRITE_KEYS } from "./field-stage.runtime.js";
|
|
3
|
+
import { isRelationMutationDirective, RELATION_MUTATION_RECORD_SITES, } from "./mutation-planner.js";
|
|
4
|
+
const REMOVE = Symbol("remove");
|
|
5
|
+
const DEPTH_CEILING = 256;
|
|
6
|
+
function rebuilt(record, changes) {
|
|
7
|
+
const copy = Object.getPrototypeOf(record) === null ? Object.create(null) : {};
|
|
8
|
+
for (const key of Object.keys(record)) {
|
|
9
|
+
const value = changes.has(key) ? changes.get(key) : record[key];
|
|
10
|
+
if (value === REMOVE) {
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(copy, key, {
|
|
14
|
+
value,
|
|
15
|
+
writable: true,
|
|
16
|
+
enumerable: true,
|
|
17
|
+
configurable: true,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return copy;
|
|
21
|
+
}
|
|
22
|
+
function eachEntry(value, strip) {
|
|
23
|
+
if (!Array.isArray(value)) {
|
|
24
|
+
return strip(value);
|
|
25
|
+
}
|
|
26
|
+
let copy;
|
|
27
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
28
|
+
if (!(index in value)) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
const entry = value[index];
|
|
32
|
+
const stripped = strip(entry);
|
|
33
|
+
if (stripped !== entry) {
|
|
34
|
+
copy ??= value.slice();
|
|
35
|
+
copy[index] = stripped;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return copy ?? value;
|
|
39
|
+
}
|
|
40
|
+
function stripRecord(walk, resourceName, record, depth) {
|
|
41
|
+
if (depth > walk.depth || !isPlainRecord(record)) {
|
|
42
|
+
return record;
|
|
43
|
+
}
|
|
44
|
+
const resource = lookupResource(walk.contract, resourceName);
|
|
45
|
+
let changes;
|
|
46
|
+
for (const key of Object.keys(record)) {
|
|
47
|
+
const value = record[key];
|
|
48
|
+
if (value === undefined) {
|
|
49
|
+
changes ??= new Map();
|
|
50
|
+
changes.set(key, REMOVE);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
const field = lookupField(resource, key);
|
|
54
|
+
if (field?.kind !== "relation") {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const stripped = stripRelationWrite(walk, field.target, value, depth + 1);
|
|
58
|
+
if (stripped !== value) {
|
|
59
|
+
changes ??= new Map();
|
|
60
|
+
changes.set(key, stripped);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return changes === undefined ? record : rebuilt(record, changes);
|
|
64
|
+
}
|
|
65
|
+
function stripRelationWrite(walk, target, value, depth) {
|
|
66
|
+
if (!isPlainRecord(value)) {
|
|
67
|
+
return value;
|
|
68
|
+
}
|
|
69
|
+
let changes;
|
|
70
|
+
for (const directive of Object.keys(value)) {
|
|
71
|
+
if (!isRelationMutationDirective(directive)) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const sites = RELATION_MUTATION_RECORD_SITES[directive];
|
|
75
|
+
if (sites.length === 0) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const operand = value[directive];
|
|
79
|
+
const next = eachEntry(operand, (entry) => {
|
|
80
|
+
let stripped = entry;
|
|
81
|
+
for (const site of sites) {
|
|
82
|
+
if (site.key === undefined) {
|
|
83
|
+
stripped = stripRecord(walk, target, stripped, depth);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (!isPlainRecord(stripped) || !Object.hasOwn(stripped, site.key)) {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const inner = stripped[site.key];
|
|
90
|
+
const record = stripRecord(walk, target, inner, depth);
|
|
91
|
+
if (record !== inner) {
|
|
92
|
+
stripped = rebuilt(stripped, new Map([[site.key, record]]));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return stripped;
|
|
96
|
+
});
|
|
97
|
+
if (next !== operand) {
|
|
98
|
+
changes ??= new Map();
|
|
99
|
+
changes.set(directive, next);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return changes === undefined ? value : rebuilt(value, changes);
|
|
103
|
+
}
|
|
104
|
+
export function withoutUnsentWriteValues(contract, request, args) {
|
|
105
|
+
const keys = Object.hasOwn(WRITE_KEYS, request.family)
|
|
106
|
+
? WRITE_KEYS[request.family]
|
|
107
|
+
: undefined;
|
|
108
|
+
if (keys === undefined || !isPlainRecord(args)) {
|
|
109
|
+
return args;
|
|
110
|
+
}
|
|
111
|
+
const walk = {
|
|
112
|
+
contract,
|
|
113
|
+
depth: Math.min(contract.limits.maxNestingDepth, DEPTH_CEILING),
|
|
114
|
+
};
|
|
115
|
+
let changes;
|
|
116
|
+
for (const key of keys) {
|
|
117
|
+
if (!Object.hasOwn(args, key)) {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
const value = args[key];
|
|
121
|
+
const next = eachEntry(value, (entry) => stripRecord(walk, request.resource, entry, 0));
|
|
122
|
+
if (next !== value) {
|
|
123
|
+
changes ??= new Map();
|
|
124
|
+
changes.set(key, next);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return changes === undefined ? args : rebuilt(args, changes);
|
|
128
|
+
}
|
|
@@ -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":
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { canonicalizeWireJson } from "../contracts/contract-canonicalizer.js";
|
|
2
2
|
const OPERATION_FINGERPRINT_PATTERN = /^fp1:[A-Za-z0-9_-]{22}$/;
|
|
3
3
|
function encodeBase64Url(bytes) {
|
|
4
4
|
let binary = "";
|
|
@@ -14,7 +14,7 @@ export function isOperationFingerprint(value) {
|
|
|
14
14
|
return typeof value === "string" && OPERATION_FINGERPRINT_PATTERN.test(value);
|
|
15
15
|
}
|
|
16
16
|
export async function computeOperationFingerprint(node) {
|
|
17
|
-
const canonical =
|
|
17
|
+
const canonical = canonicalizeWireJson({
|
|
18
18
|
resource: node.resource,
|
|
19
19
|
family: node.family,
|
|
20
20
|
variant: node.variant,
|