@aventara/core 1.0.0-rc.0 → 1.0.0-rc.10
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 +2068 -1
- package/ERRORS.md +142 -0
- package/README.md +485 -60
- 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 +33 -11
- package/dist/adapters/adapter-identifier.d.ts +15 -6
- package/dist/adapters/adapter-identifier.js +6 -1
- 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 +21 -6
- package/dist/adapters/adapter-resource.d.ts +23 -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 +9 -8
- 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 +23 -17
- package/dist/compiler/contract.compiler.js +753 -443
- 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/compiler/managed-elsewhere.projector.d.ts +52 -0
- package/dist/compiler/managed-elsewhere.projector.js +179 -0
- package/dist/compiler/managed-elsewhere.validator.d.ts +9 -0
- package/dist/compiler/managed-elsewhere.validator.js +74 -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 +73 -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 +98 -31
- package/dist/config/config.resolver.js +173 -44
- package/dist/config/config.validator.d.ts +7 -7
- package/dist/config/config.validator.js +792 -69
- package/dist/config/define-resource.d.ts +53 -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 +4 -3
- package/dist/config/exact-framework-config.d.ts +325 -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 +148 -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 +127 -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/access-route.rules.d.ts +10 -0
- package/dist/contracts/access-route.rules.js +45 -0
- package/dist/contracts/capability.d.ts +37 -12
- package/dist/contracts/capability.js +20 -0
- package/dist/contracts/client-contract-structure.validator.d.ts +621 -114
- package/dist/contracts/client-contract-structure.validator.js +189 -10
- package/dist/contracts/contract-access.d.ts +29 -0
- package/dist/contracts/contract-access.js +1 -0
- package/dist/contracts/contract-canonicalizer.d.ts +27 -3
- package/dist/contracts/contract-canonicalizer.js +168 -29
- package/dist/contracts/contract-hash.d.ts +11 -7
- package/dist/contracts/contract-hash.js +4 -3
- 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 +51 -17
- 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 +109 -42
- package/dist/contracts/identifier.d.ts +4 -4
- package/dist/contracts/json-schema.projector.d.ts +11 -0
- package/dist/contracts/json-schema.projector.js +78 -0
- 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 +17 -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/access-facade.d.ts +116 -0
- package/dist/framework/access-facade.js +120 -0
- package/dist/framework/contract-view.d.ts +315 -145
- package/dist/framework/framework-construction.error.d.ts +21 -11
- package/dist/framework/framework-construction.error.js +20 -4
- package/dist/framework/framework.d.ts +71 -26
- package/dist/framework/framework.factory.d.ts +8 -6
- package/dist/framework/framework.factory.js +150 -38
- package/dist/framework/operation-facade.d.ts +192 -54
- package/dist/framework/operation-facade.js +10 -1
- package/dist/index.d.ts +67 -50
- package/dist/index.js +7 -6
- package/dist/internal.d.ts +20 -10
- package/dist/internal.js +9 -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 +381 -228
- package/dist/operations/operation-call.d.ts +31 -28
- package/dist/operations/operation-identity.d.ts +10 -10
- package/dist/operations/operation-result.d.ts +25 -23
- package/dist/operations/operation-validator-core.d.ts +6 -6
- package/dist/operations/operation-validator-core.js +172 -38
- package/dist/operations/operation-validator.d.ts +10 -10
- package/dist/operations/projection-scope.resolver.d.ts +6 -6
- package/dist/operations/structural-limits.walker.d.ts +7 -7
- 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/policy/access-provider.interface.d.ts +91 -0
- package/dist/policy/access-provider.interface.js +1 -0
- package/dist/policy/access-provider.registry.d.ts +17 -0
- package/dist/policy/access-provider.registry.js +15 -0
- package/dist/policy/access-question.d.ts +20 -0
- package/dist/policy/access-question.js +1 -0
- package/dist/policy/access-question.registry.d.ts +5 -0
- package/dist/policy/access-question.registry.js +19 -0
- package/dist/policy/access-question.runtime.d.ts +36 -0
- package/dist/policy/access-question.runtime.js +297 -0
- package/dist/policy/access-verb.table.d.ts +56 -0
- package/dist/policy/access-verb.table.js +21 -0
- package/dist/policy/access-verbs.d.ts +46 -0
- package/dist/policy/access-verbs.js +1 -0
- package/dist/policy/policy-admission.d.ts +20 -0
- package/dist/policy/policy-admission.js +409 -0
- package/dist/policy/policy-after-update.runtime.d.ts +79 -0
- package/dist/policy/policy-after-update.runtime.js +208 -0
- package/dist/policy/policy-condition.d.ts +15 -0
- package/dist/policy/policy-condition.js +36 -0
- package/dist/policy/policy-engine.d.ts +205 -0
- package/dist/policy/policy-engine.js +1 -0
- package/dist/policy/policy-named-rows.d.ts +18 -0
- package/dist/policy/policy-named-rows.js +51 -0
- package/dist/policy/policy-nested-write.runtime.d.ts +44 -0
- package/dist/policy/policy-nested-write.runtime.js +545 -0
- package/dist/policy/policy-read.runtime.d.ts +81 -0
- package/dist/policy/policy-read.runtime.js +503 -0
- package/dist/policy/policy-reference-write.runtime.d.ts +51 -0
- package/dist/policy/policy-reference-write.runtime.js +345 -0
- package/dist/policy/policy-request.d.ts +41 -0
- package/dist/policy/policy-request.js +63 -0
- package/dist/policy/policy-session.d.ts +106 -0
- package/dist/policy/policy-session.js +295 -0
- package/dist/policy/policy-startup.validator.d.ts +10 -0
- package/dist/policy/policy-startup.validator.js +112 -0
- package/dist/policy/policy-write.runtime.d.ts +39 -0
- package/dist/policy/policy-write.runtime.js +532 -0
- package/dist/prebuilt/core-version.generated.d.ts +2 -0
- package/dist/prebuilt/core-version.generated.js +1 -0
- package/dist/prebuilt/prebuilt-changes.d.ts +29 -0
- package/dist/prebuilt/prebuilt-changes.js +65 -0
- package/dist/prebuilt/prebuilt-contracts.d.ts +40 -0
- package/dist/prebuilt/prebuilt-contracts.emitter.d.ts +16 -0
- package/dist/prebuilt/prebuilt-contracts.emitter.js +50 -0
- package/dist/prebuilt/prebuilt-contracts.js +1 -0
- package/dist/prebuilt/prebuilt-contracts.loader.d.ts +19 -0
- package/dist/prebuilt/prebuilt-contracts.loader.js +77 -0
- package/dist/prebuilt/prebuilt-inputs.fingerprint.d.ts +16 -0
- package/dist/prebuilt/prebuilt-inputs.fingerprint.js +229 -0
- package/dist/protocol/absent-route.responder.d.ts +17 -34
- package/dist/protocol/absent-route.responder.js +53 -20
- package/dist/protocol/contract-document.responder.d.ts +5 -4
- package/dist/protocol/contract-document.responder.js +2 -2
- package/dist/protocol/http-request.decoder.d.ts +33 -13
- package/dist/protocol/http-request.decoder.js +34 -11
- package/dist/protocol/http-request.reader.d.ts +9 -6
- package/dist/protocol/http-request.reader.js +1 -0
- 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-headers.d.ts +3 -3
- package/dist/protocol/protocol-surface.d.ts +10 -5
- package/dist/protocol/protocol-surface.js +7 -0
- package/dist/protocol/protocol.binder.d.ts +66 -28
- package/dist/protocol/protocol.binder.js +16 -10
- package/dist/protocol/protocol.handler.d.ts +34 -14
- package/dist/protocol/protocol.handler.js +122 -18
- 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 -7
- package/dist/runtime/caller-data.copier.js +30 -17
- package/dist/runtime/caller-data.door.d.ts +18 -11
- package/dist/runtime/caller-data.door.js +6 -4
- package/dist/runtime/computed-read-runtime.d.ts +12 -6
- package/dist/runtime/computed-read-runtime.js +271 -71
- 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 +60 -0
- package/dist/runtime/context-executor.runtime.js +277 -0
- package/dist/runtime/core-class.brand.d.ts +10 -0
- package/dist/runtime/core-class.brand.js +21 -0
- package/dist/runtime/create-requirement.d.ts +34 -79
- package/dist/runtime/create-requirement.js +205 -74
- package/dist/runtime/decimal.d.ts +16 -2
- package/dist/runtime/decimal.js +22 -1
- package/dist/runtime/diagnostics-reporter.d.ts +91 -30
- package/dist/runtime/diagnostics-reporter.js +37 -1
- package/dist/runtime/error-boundary.d.ts +73 -9
- package/dist/runtime/error-boundary.js +57 -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 +18 -2
- package/dist/runtime/field-check.evaluator.d.ts +27 -0
- package/dist/runtime/field-check.evaluator.js +521 -0
- package/dist/runtime/field-compute.d.ts +65 -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 +29 -0
- package/dist/runtime/field-validator.runtime.js +126 -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 +32 -2
- package/dist/runtime/framework-warning.emitter.d.ts +6 -0
- package/dist/runtime/framework-warning.emitter.js +8 -0
- 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 +26 -0
- package/dist/runtime/level-lifecycle.runtime.js +40 -0
- package/dist/runtime/misuse-reporter.d.ts +12 -12
- package/dist/runtime/mutation-planner.d.ts +20 -16
- 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 +45 -11
- package/dist/runtime/operation-response.d.ts +17 -17
- package/dist/runtime/operation-runtime.d.ts +133 -27
- package/dist/runtime/operation-runtime.js +576 -84
- package/dist/runtime/outcome-mapper.d.ts +17 -5
- package/dist/runtime/outcome-mapper.js +23 -6
- package/dist/runtime/output-validator.d.ts +11 -11
- 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 +221 -34
- package/dist/runtime/readonly-value.d.ts +47 -0
- package/dist/runtime/readonly-value.js +189 -0
- package/dist/runtime/referential-action.d.ts +1 -1
- 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 +33 -25
- package/dist/runtime/scalar-runtime.js +105 -38
- 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 +8 -3
- 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 +9 -8
- package/dist/transactions/transaction-integrity-error.d.ts +6 -6
- package/dist/transactions/transaction-integrity-error.js +7 -2
- package/dist/transactions/transaction-plan-assembler.d.ts +30 -13
- package/dist/transactions/transaction-plan-assembler.js +184 -32
- package/dist/transactions/transaction-plan-validator.d.ts +50 -25
- 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 +21 -3
- package/dist/transactions/transaction-reference-resolver.js +26 -14
- package/dist/transactions/transaction-reference-validator.d.ts +74 -4
- package/dist/transactions/transaction-reference-validator.js +129 -71
- package/dist/transactions/transaction-reference.d.ts +14 -14
- package/dist/transactions/transaction-reference.js +5 -0
- package/dist/transactions/transaction-request.d.ts +22 -9
- package/dist/transactions/transaction-response.d.ts +6 -6
- package/dist/transactions/transaction-runtime.d.ts +12 -8
- package/dist/transactions/transaction-runtime.js +218 -50
- package/dist/transactions/transaction-settlement.runtime.d.ts +52 -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 +4 -2
- package/dist/transactions/transaction-slot-writer.js +2 -2
- package/dist/transactions/transaction-stage.runtime.d.ts +83 -0
- package/dist/transactions/transaction-stage.runtime.js +126 -0
- package/package.json +11 -9
- 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, isAvDecimal } 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
|
+
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({
|
|
@@ -231,10 +238,9 @@ function normalizeScalarAtom(contract, field, value, origin, path, allowNull) {
|
|
|
231
238
|
break;
|
|
232
239
|
case "decimal":
|
|
233
240
|
if (origin === "application") {
|
|
234
|
-
normalized =
|
|
235
|
-
value
|
|
236
|
-
|
|
237
|
-
: { ok: false, issues: [typeIssue(path, "an Aventara Decimal")] };
|
|
241
|
+
normalized = isAvDecimal(value)
|
|
242
|
+
? { ok: true, value }
|
|
243
|
+
: { ok: false, issues: [typeIssue(path, "an Aventara Decimal")] };
|
|
238
244
|
}
|
|
239
245
|
else if (typeof value !== "string") {
|
|
240
246
|
normalized = {
|
|
@@ -244,7 +250,7 @@ function normalizeScalarAtom(contract, field, value, origin, path, allowNull) {
|
|
|
244
250
|
}
|
|
245
251
|
else {
|
|
246
252
|
try {
|
|
247
|
-
normalized = { ok: true, value: new
|
|
253
|
+
normalized = { ok: true, value: new AvDecimal(value) };
|
|
248
254
|
}
|
|
249
255
|
catch {
|
|
250
256
|
normalized = {
|
|
@@ -359,9 +365,21 @@ export function normalizeScalarFieldValue(contract, field, value, origin, path)
|
|
|
359
365
|
});
|
|
360
366
|
return issues.length > 0
|
|
361
367
|
? { ok: false, issues }
|
|
362
|
-
: { ok: true, value: normalized };
|
|
368
|
+
: heldToFormat(field, { ok: true, value: normalized }, origin, path);
|
|
363
369
|
}
|
|
364
|
-
return normalizeScalarAtom(contract, field, value, origin === "runtime" ? "application" : origin, path, field.nullable);
|
|
370
|
+
return heldToFormat(field, normalizeScalarAtom(contract, field, value, origin === "runtime" ? "application" : origin, path, field.nullable), origin, path);
|
|
371
|
+
}
|
|
372
|
+
function heldToFormat(field, normalized, origin, path) {
|
|
373
|
+
const format = field.format;
|
|
374
|
+
if (origin !== "runtime" ||
|
|
375
|
+
!normalized.ok ||
|
|
376
|
+
format === undefined ||
|
|
377
|
+
format === "uuid" ||
|
|
378
|
+
!isNamedFormat(format)) {
|
|
379
|
+
return normalized;
|
|
380
|
+
}
|
|
381
|
+
const issues = fieldCheckIssues([{ check: "string_format", format }], normalized.value, "string", path, field.list);
|
|
382
|
+
return issues.length === 0 ? normalized : { ok: false, issues };
|
|
365
383
|
}
|
|
366
384
|
export function jsonShapeIssues(field, value, path, position = "value") {
|
|
367
385
|
if (field.json === undefined || value === null || value === undefined) {
|
|
@@ -385,7 +403,6 @@ function normalizeWrittenValue(contract, field, value, origin, path, issues) {
|
|
|
385
403
|
issues.push(...result.issues);
|
|
386
404
|
return undefined;
|
|
387
405
|
}
|
|
388
|
-
issues.push(...jsonShapeIssues(field, result.value, path));
|
|
389
406
|
return result.value;
|
|
390
407
|
}
|
|
391
408
|
function normalizeWrittenElement(contract, field, value, origin, path, issues) {
|
|
@@ -394,7 +411,6 @@ function normalizeWrittenElement(contract, field, value, origin, path, issues) {
|
|
|
394
411
|
issues.push(...result.issues);
|
|
395
412
|
return undefined;
|
|
396
413
|
}
|
|
397
|
-
issues.push(...jsonShapeIssues(field, result.value, path, "entry"));
|
|
398
414
|
return result.value;
|
|
399
415
|
}
|
|
400
416
|
const SCALAR_ATOM_COPIERS = {
|
|
@@ -429,6 +445,11 @@ export function copyScalarFieldValue(field, value) {
|
|
|
429
445
|
function normalizeListElement(contract, field, value, origin, path) {
|
|
430
446
|
return normalizeScalarAtom(contract, field, value, origin, path, false);
|
|
431
447
|
}
|
|
448
|
+
function normalizeFilterEntry(contract, field, value, origin, path) {
|
|
449
|
+
return value === undefined
|
|
450
|
+
? { ok: false, issues: [unsentReadValueIssue(path)] }
|
|
451
|
+
: normalizeListElement(contract, field, value, origin, path);
|
|
452
|
+
}
|
|
432
453
|
function mergeResult(result, issues) {
|
|
433
454
|
if (result.ok) {
|
|
434
455
|
return result.value;
|
|
@@ -436,7 +457,7 @@ function mergeResult(result, issues) {
|
|
|
436
457
|
issues.push(...result.issues);
|
|
437
458
|
return undefined;
|
|
438
459
|
}
|
|
439
|
-
|
|
460
|
+
const REFERENCE_OPERANDS = Object.freeze({
|
|
440
461
|
equals: "value",
|
|
441
462
|
not: "value",
|
|
442
463
|
lt: "nonNullValue",
|
|
@@ -465,10 +486,40 @@ const NULL_OPERAND_OPERATORS = new Set([
|
|
|
465
486
|
"arrayStartsWith",
|
|
466
487
|
"arrayEndsWith",
|
|
467
488
|
]);
|
|
489
|
+
const KEYWORD_OPERANDS = Object.freeze({
|
|
490
|
+
mode: (operand, path, issues) => {
|
|
491
|
+
if (!FILTER_MODES.includes(operand)) {
|
|
492
|
+
issues.push(typeIssue(path, '"default", "sensitive" or "insensitive"'));
|
|
493
|
+
}
|
|
494
|
+
},
|
|
495
|
+
isEmpty: (operand, path, issues) => {
|
|
496
|
+
if (typeof operand !== "boolean") {
|
|
497
|
+
issues.push(typeIssue(path, "a boolean"));
|
|
498
|
+
}
|
|
499
|
+
},
|
|
500
|
+
path: (operand, path, issues) => {
|
|
501
|
+
if (!Array.isArray(operand)) {
|
|
502
|
+
issues.push(typeIssue(path, "an array of strings"));
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
for (let index = 0; index < operand.length; index += 1) {
|
|
506
|
+
if (operand[index] === undefined) {
|
|
507
|
+
issues.push(unsentReadValueIssue([...path, index]));
|
|
508
|
+
}
|
|
509
|
+
else if (typeof operand[index] !== "string") {
|
|
510
|
+
issues.push(typeIssue([...path, index], "a string"));
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
},
|
|
514
|
+
});
|
|
468
515
|
function normalizeScalarFilter(contract, field, value, origin, path, issues, references = false) {
|
|
469
516
|
if (isKeptReference(references, value)) {
|
|
470
517
|
return value;
|
|
471
518
|
}
|
|
519
|
+
if (value === undefined) {
|
|
520
|
+
issues.push(unsentReadValueIssue(path));
|
|
521
|
+
return value;
|
|
522
|
+
}
|
|
472
523
|
if (!isPlainRecord(value)) {
|
|
473
524
|
return mergeResult(normalizeScalarFieldValue(contract, field, value, origin, path), issues);
|
|
474
525
|
}
|
|
@@ -479,11 +530,17 @@ function normalizeScalarFilter(contract, field, value, origin, path, issues, ref
|
|
|
479
530
|
const normalized = cloneRecord(value);
|
|
480
531
|
for (const [operator, operand] of Object.entries(value)) {
|
|
481
532
|
const operandPath = [...path, operator];
|
|
533
|
+
if (operand === undefined) {
|
|
534
|
+
issues.push(unsentReadValueIssue(operandPath));
|
|
535
|
+
continue;
|
|
536
|
+
}
|
|
482
537
|
if (operand === null && !acceptsNullOperand(operator)) {
|
|
483
538
|
issues.push(typeIssue(operandPath, "non-null"));
|
|
484
539
|
continue;
|
|
485
540
|
}
|
|
486
|
-
|
|
541
|
+
const keyword = lookupOwn(KEYWORD_OPERANDS, operator);
|
|
542
|
+
if (keyword !== undefined) {
|
|
543
|
+
keyword(operand, operandPath, issues);
|
|
487
544
|
continue;
|
|
488
545
|
}
|
|
489
546
|
if (referenceOperandShape(operator) !== undefined &&
|
|
@@ -499,14 +556,14 @@ function normalizeScalarFilter(contract, field, value, origin, path, issues, ref
|
|
|
499
556
|
issues.push(typeIssue(operandPath, "an array"));
|
|
500
557
|
continue;
|
|
501
558
|
}
|
|
502
|
-
normalized[operator] = operand.map((entry, index) => mergeResult(
|
|
559
|
+
normalized[operator] = operand.map((entry, index) => mergeResult(normalizeFilterEntry(contract, field, entry, origin, [
|
|
503
560
|
...operandPath,
|
|
504
561
|
index,
|
|
505
562
|
]), issues));
|
|
506
563
|
continue;
|
|
507
564
|
}
|
|
508
565
|
if (operator === "has") {
|
|
509
|
-
normalized[operator] = mergeResult(
|
|
566
|
+
normalized[operator] = mergeResult(normalizeFilterEntry(contract, field, operand, origin, operandPath), issues);
|
|
510
567
|
continue;
|
|
511
568
|
}
|
|
512
569
|
if (operator === "hasEvery" || operator === "hasSome") {
|
|
@@ -514,7 +571,7 @@ function normalizeScalarFilter(contract, field, value, origin, path, issues, ref
|
|
|
514
571
|
issues.push(typeIssue(operandPath, "an array"));
|
|
515
572
|
continue;
|
|
516
573
|
}
|
|
517
|
-
normalized[operator] = operand.map((entry, index) => mergeResult(
|
|
574
|
+
normalized[operator] = operand.map((entry, index) => mergeResult(normalizeFilterEntry(contract, field, entry, origin, [
|
|
518
575
|
...operandPath,
|
|
519
576
|
index,
|
|
520
577
|
]), issues));
|
|
@@ -523,6 +580,12 @@ function normalizeScalarFilter(contract, field, value, origin, path, issues, ref
|
|
|
523
580
|
if ("scalar" in field.type &&
|
|
524
581
|
field.type.scalar === "json" &&
|
|
525
582
|
(operator.startsWith("string") || operator.startsWith("array"))) {
|
|
583
|
+
if (operator.startsWith("string")) {
|
|
584
|
+
if (typeof operand !== "string") {
|
|
585
|
+
issues.push(typeIssue(operandPath, "a string"));
|
|
586
|
+
}
|
|
587
|
+
continue;
|
|
588
|
+
}
|
|
526
589
|
const jsonResult = normalizeJsonValue(operand, operandPath, new Set());
|
|
527
590
|
normalized[operator] = mergeResult(jsonResult, issues);
|
|
528
591
|
continue;
|
|
@@ -587,6 +650,10 @@ function normalizeUniqueSelector(contract, resourceName, selector, origin, path,
|
|
|
587
650
|
const normalized = cloneRecord(selector);
|
|
588
651
|
for (const [fieldName, value] of Object.entries(selector)) {
|
|
589
652
|
const field = lookupField(resource, fieldName);
|
|
653
|
+
if (field?.kind === "scalar" && value === undefined) {
|
|
654
|
+
issues.push(unsentReadValueIssue([...path, fieldName]));
|
|
655
|
+
continue;
|
|
656
|
+
}
|
|
590
657
|
if (field?.kind === "scalar" && !isKeptReference(references, value)) {
|
|
591
658
|
normalized[fieldName] = mergeResult(normalizeScalarFieldValue(contract, field, value, origin, [
|
|
592
659
|
...path,
|
|
@@ -679,9 +746,9 @@ function normalizeRelationMutation(contract, edge, value, origin, path, issues,
|
|
|
679
746
|
const normalized = cloneRecord(value);
|
|
680
747
|
for (const [directive, operand] of Object.entries(value)) {
|
|
681
748
|
const directivePath = [...path, directive];
|
|
682
|
-
const
|
|
683
|
-
|
|
684
|
-
|
|
749
|
+
const listed = edge.cardinality === "many" && Array.isArray(operand);
|
|
750
|
+
const entries = listed ? operand : [operand];
|
|
751
|
+
const entryPath = (index) => listed ? [...directivePath, index] : directivePath;
|
|
685
752
|
if (directive === "$create") {
|
|
686
753
|
normalized[directive] =
|
|
687
754
|
edge.cardinality === "many" && Array.isArray(operand)
|
|
@@ -714,8 +781,8 @@ function normalizeRelationMutation(contract, edge, value, origin, path, issues,
|
|
|
714
781
|
}
|
|
715
782
|
return {
|
|
716
783
|
...entry,
|
|
717
|
-
where: normalizeUniqueSelector(contract, edge.target, entry.where, origin, [...
|
|
718
|
-
create: normalizeMutationData(contract, edge.target, entry.create, origin, [...
|
|
784
|
+
where: normalizeUniqueSelector(contract, edge.target, entry.where, origin, [...entryPath(index), "where"], issues, references),
|
|
785
|
+
create: normalizeMutationData(contract, edge.target, entry.create, origin, [...entryPath(index), "create"], issues, references),
|
|
719
786
|
};
|
|
720
787
|
});
|
|
721
788
|
normalized[directive] =
|
|
@@ -733,10 +800,10 @@ function normalizeRelationMutation(contract, edge, value, origin, path, issues,
|
|
|
733
800
|
...entry,
|
|
734
801
|
...(entry.where !== undefined
|
|
735
802
|
? {
|
|
736
|
-
where: normalizeWhere(contract, edge.target, entry.where, origin, [...
|
|
803
|
+
where: normalizeWhere(contract, edge.target, entry.where, origin, [...entryPath(index), "where"], issues, references),
|
|
737
804
|
}
|
|
738
805
|
: {}),
|
|
739
|
-
data: normalizeMutationData(contract, edge.target, entry.data, origin, [...
|
|
806
|
+
data: normalizeMutationData(contract, edge.target, entry.data, origin, [...entryPath(index), "data"], issues, references),
|
|
740
807
|
};
|
|
741
808
|
});
|
|
742
809
|
normalized[directive] =
|
|
@@ -752,7 +819,7 @@ function normalizeRelationMutation(contract, edge, value, origin, path, issues,
|
|
|
752
819
|
}
|
|
753
820
|
return {
|
|
754
821
|
...entry,
|
|
755
|
-
where: normalizeWhere(contract, edge.target, entry.where, origin, [...
|
|
822
|
+
where: normalizeWhere(contract, edge.target, entry.where, origin, [...entryPath(index), "where"], issues, references),
|
|
756
823
|
};
|
|
757
824
|
});
|
|
758
825
|
normalized[directive] =
|
|
@@ -770,11 +837,11 @@ function normalizeRelationMutation(contract, edge, value, origin, path, issues,
|
|
|
770
837
|
...entry,
|
|
771
838
|
...(entry.where !== undefined
|
|
772
839
|
? {
|
|
773
|
-
where: normalizeUniqueSelector(contract, edge.target, entry.where, origin, [...
|
|
840
|
+
where: normalizeUniqueSelector(contract, edge.target, entry.where, origin, [...entryPath(index), "where"], issues, references),
|
|
774
841
|
}
|
|
775
842
|
: {}),
|
|
776
|
-
create: normalizeMutationData(contract, edge.target, entry.create, origin, [...
|
|
777
|
-
update: normalizeMutationData(contract, edge.target, entry.update, origin, [...
|
|
843
|
+
create: normalizeMutationData(contract, edge.target, entry.create, origin, [...entryPath(index), "create"], issues, references),
|
|
844
|
+
update: normalizeMutationData(contract, edge.target, entry.update, origin, [...entryPath(index), "update"], issues, references),
|
|
778
845
|
};
|
|
779
846
|
});
|
|
780
847
|
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 { isAvDecimal } 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,9 +27,11 @@ 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
|
|
30
|
+
return isAvDecimal(value) ? value.toString() : value;
|
|
31
31
|
case "datetime":
|
|
32
|
-
return value instanceof Date
|
|
32
|
+
return value instanceof Date && !Number.isNaN(value.getTime())
|
|
33
|
+
? value.toISOString()
|
|
34
|
+
: value;
|
|
33
35
|
case "bytes":
|
|
34
36
|
return value instanceof Uint8Array ? encodeBase64(value) : value;
|
|
35
37
|
default:
|
|
@@ -282,6 +284,9 @@ function isUniqueOperation(operation) {
|
|
|
282
284
|
operation.family === "upsert"));
|
|
283
285
|
}
|
|
284
286
|
export function encodeOperationArgumentsForWire(contract, operation, args) {
|
|
287
|
+
if (!isPlainRecord(args)) {
|
|
288
|
+
return args;
|
|
289
|
+
}
|
|
285
290
|
const encoded = cloneRecord(args);
|
|
286
291
|
if (hasOwnWireProperty(args, "where")) {
|
|
287
292
|
encoded.where = isUniqueOperation(operation)
|
|
@@ -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,
|