@aventara/core 1.0.0-rc.1 → 1.0.0-rc.11
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 +1022 -16
- package/ERRORS.md +142 -0
- package/README.md +330 -16
- 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 +22 -0
- package/dist/adapters/adapter-identifier.d.ts +9 -0
- package/dist/adapters/adapter-identifier.js +6 -1
- package/dist/adapters/adapter-model.d.ts +9 -0
- package/dist/adapters/adapter-operation.d.ts +18 -3
- package/dist/adapters/adapter-resource.d.ts +5 -0
- package/dist/adapters/adapter.interface.d.ts +10 -0
- package/dist/avz/avz.d.ts +1 -1
- package/dist/avz/json-shape.registry.d.ts +2 -1
- 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 +6 -0
- package/dist/compiler/contract.compiler.js +281 -31
- package/dist/compiler/create-requirements.projector.js +1 -3
- package/dist/compiler/field-validator.compiler.js +1 -3
- 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/cache-stage.factory.d.ts +24 -0
- package/dist/config/cache-stage.factory.js +3 -0
- package/dist/config/computed-fields.d.ts +62 -0
- package/dist/config/computed-fields.js +73 -0
- package/dist/config/config-diagnostic.guidance.d.ts +6 -0
- package/dist/config/config-diagnostic.guidance.js +32 -0
- package/dist/config/config.resolver.d.ts +24 -0
- package/dist/config/config.resolver.js +66 -7
- package/dist/config/config.validator.js +283 -21
- package/dist/config/define-resource.d.ts +1 -5
- package/dist/config/entrypoint.normalizer.d.ts +3 -2
- package/dist/config/exact-framework-config.d.ts +73 -22
- package/dist/config/field-compute.resolver.d.ts +2 -0
- package/dist/config/field-compute.resolver.js +9 -3
- package/dist/config/framework-config.d.ts +53 -15
- package/dist/config/framework-resources-config.d.ts +25 -14
- package/dist/config/pipeline-config.d.ts +20 -4
- package/dist/config/pipeline-tree.resolver.d.ts +2 -2
- package/dist/config/pipeline-tree.resolver.js +2 -3
- package/dist/contracts/access-route.rules.d.ts +10 -0
- package/dist/contracts/access-route.rules.js +45 -0
- package/dist/contracts/canonical-json.writer.d.ts +7 -0
- package/dist/contracts/canonical-json.writer.js +55 -0
- package/dist/contracts/capability.d.ts +26 -1
- package/dist/contracts/capability.js +20 -0
- package/dist/contracts/client-contract-structure.validator.d.ts +365 -89
- package/dist/contracts/client-contract-structure.validator.js +49 -2
- package/dist/contracts/contract-access.d.ts +29 -0
- package/dist/contracts/contract-access.js +1 -0
- package/dist/contracts/contract-canonicalizer.d.ts +9 -1
- package/dist/contracts/contract-canonicalizer.js +35 -4
- package/dist/contracts/contract-hash.d.ts +0 -1
- package/dist/contracts/contract-hash.js +1 -1
- package/dist/contracts/contract-limits.d.ts +6 -0
- package/dist/contracts/contract-limits.js +2 -0
- package/dist/contracts/contract.d.ts +42 -1
- package/dist/contracts/field.d.ts +58 -1
- package/dist/contracts/json-schema.projector.d.ts +11 -0
- package/dist/contracts/json-schema.projector.js +76 -0
- package/dist/contracts/scalar-value-type.d.ts +3 -1
- package/dist/framework/access-facade.d.ts +116 -0
- package/dist/framework/access-facade.js +118 -0
- package/dist/framework/contract-view.d.ts +120 -16
- package/dist/framework/framework-construction.error.d.ts +14 -4
- package/dist/framework/framework-construction.error.js +18 -2
- package/dist/framework/framework.d.ts +26 -5
- package/dist/framework/framework.factory.d.ts +1 -1
- package/dist/framework/framework.factory.js +145 -24
- package/dist/framework/operation-facade.d.ts +141 -13
- package/dist/framework/operation-facade.js +9 -1
- package/dist/framework/operation-set.runner.d.ts +47 -0
- package/dist/framework/operation-set.runner.js +168 -0
- package/dist/index.d.ts +19 -5
- package/dist/index.js +3 -0
- package/dist/internal.d.ts +9 -2
- package/dist/internal.js +8 -0
- package/dist/operations/database-refusal.d.ts +51 -0
- package/dist/operations/database-refusal.js +45 -0
- package/dist/operations/operation-arguments.d.ts +148 -60
- package/dist/operations/operation-call.d.ts +9 -5
- package/dist/operations/operation-result.d.ts +6 -4
- package/dist/operations/operation-validator-core.js +160 -39
- package/dist/operations/operation-validator.d.ts +1 -1
- package/dist/operations/structural-limits.walker.d.ts +1 -1
- package/dist/operations/structural-limits.walker.js +1 -3
- package/dist/operations/validation-code.guidance.d.ts +6 -0
- package/dist/operations/validation-code.guidance.js +90 -0
- package/dist/operations/write-scope.resolver.d.ts +4 -0
- 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 +295 -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 +407 -0
- package/dist/policy/policy-after-update.runtime.d.ts +79 -0
- package/dist/policy/policy-after-update.runtime.js +206 -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 +536 -0
- package/dist/policy/policy-read.runtime.d.ts +81 -0
- package/dist/policy/policy-read.runtime.js +501 -0
- package/dist/policy/policy-reference-write.runtime.d.ts +51 -0
- package/dist/policy/policy-reference-write.runtime.js +336 -0
- package/dist/policy/policy-request.d.ts +72 -0
- package/dist/policy/policy-request.js +115 -0
- package/dist/policy/policy-session.d.ts +106 -0
- package/dist/policy/policy-session.js +293 -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 +530 -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 +63 -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 +75 -0
- package/dist/prebuilt/prebuilt-inputs.fingerprint.d.ts +16 -0
- package/dist/prebuilt/prebuilt-inputs.fingerprint.js +227 -0
- package/dist/protocol/absent-route.responder.d.ts +49 -14
- package/dist/protocol/absent-route.responder.js +92 -15
- package/dist/protocol/contract-document.responder.d.ts +9 -1
- package/dist/protocol/contract-document.responder.js +3 -2
- package/dist/protocol/http-request.decoder.d.ts +52 -3
- package/dist/protocol/http-request.decoder.js +45 -6
- package/dist/protocol/http-request.reader.d.ts +10 -3
- package/dist/protocol/http-request.reader.js +12 -2
- package/dist/protocol/http-response.encoder.d.ts +12 -0
- package/dist/protocol/http-response.encoder.js +17 -3
- package/dist/protocol/operation-response.guard.js +1 -3
- package/dist/protocol/operation-set.decoder.d.ts +48 -0
- package/dist/protocol/operation-set.decoder.js +185 -0
- package/dist/protocol/operation-set.handler.d.ts +27 -0
- package/dist/protocol/operation-set.handler.js +179 -0
- package/dist/protocol/protocol-headers.d.ts +12 -3
- package/dist/protocol/protocol-headers.js +12 -5
- package/dist/protocol/protocol-surface.d.ts +16 -3
- package/dist/protocol/protocol-surface.js +41 -1
- package/dist/protocol/protocol.binder.d.ts +52 -1
- package/dist/protocol/protocol.binder.js +6 -1
- package/dist/protocol/protocol.handler.d.ts +45 -1
- package/dist/protocol/protocol.handler.js +164 -19
- package/dist/protocol/read-cache.responder.d.ts +26 -0
- package/dist/protocol/read-cache.responder.js +47 -0
- package/dist/protocol/read-query.codec.d.ts +34 -0
- package/dist/protocol/read-query.codec.js +125 -0
- package/dist/runtime/caller-data.copier.d.ts +18 -3
- package/dist/runtime/caller-data.copier.js +21 -8
- package/dist/runtime/caller-data.door.d.ts +13 -6
- package/dist/runtime/computed-read-runtime.d.ts +6 -1
- package/dist/runtime/computed-read-runtime.js +229 -48
- package/dist/runtime/computed-value.error.d.ts +3 -2
- package/dist/runtime/computed-value.error.js +3 -2
- package/dist/runtime/context-executor.runtime.d.ts +4 -3
- package/dist/runtime/context-executor.runtime.js +4 -2
- 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 +31 -5
- package/dist/runtime/create-requirement.js +130 -24
- package/dist/runtime/decimal.d.ts +14 -0
- package/dist/runtime/decimal.js +21 -0
- package/dist/runtime/diagnostics-reporter.d.ts +49 -9
- package/dist/runtime/diagnostics-reporter.js +16 -9
- package/dist/runtime/error-boundary.d.ts +9 -2
- package/dist/runtime/error-boundary.js +12 -0
- 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 +8 -0
- package/dist/runtime/field-check.evaluator.d.ts +0 -2
- package/dist/runtime/field-check.evaluator.js +1 -1
- package/dist/runtime/field-compute.d.ts +11 -10
- package/dist/runtime/field-stage.runtime.d.ts +3 -3
- package/dist/runtime/field-stage.runtime.js +9 -11
- package/dist/runtime/field-validator.runtime.d.ts +19 -1
- package/dist/runtime/field-validator.runtime.js +49 -9
- package/dist/runtime/framework-error.js +9 -0
- package/dist/runtime/framework-warning.emitter.d.ts +6 -0
- package/dist/runtime/framework-warning.emitter.js +8 -0
- package/dist/runtime/json-value.d.ts +10 -5
- package/dist/runtime/level-lifecycle.runtime.d.ts +4 -3
- package/dist/runtime/level-lifecycle.runtime.js +3 -5
- package/dist/runtime/mutation-planner.d.ts +1 -6
- package/dist/runtime/mutation-planner.js +4 -17
- package/dist/runtime/nested-write.walker.js +2 -1
- 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 +16 -9
- package/dist/runtime/operation-runtime.d.ts +35 -17
- package/dist/runtime/operation-runtime.js +220 -49
- package/dist/runtime/outcome-mapper.d.ts +2 -1
- package/dist/runtime/output-validator.d.ts +1 -1
- package/dist/runtime/output-validator.js +1 -3
- package/dist/runtime/owned-execution.registry.d.ts +34 -4
- package/dist/runtime/pipe-output.validator.d.ts +10 -0
- package/dist/runtime/pipe-output.validator.js +4 -2
- package/dist/runtime/pipeline.d.ts +52 -23
- package/dist/runtime/readonly-value.d.ts +20 -5
- package/dist/runtime/readonly-value.js +74 -26
- package/dist/runtime/record.guard.d.ts +14 -0
- package/dist/runtime/record.guard.js +10 -0
- package/dist/runtime/referential-action.d.ts +1 -1
- package/dist/runtime/request-envelope.validator.js +13 -10
- package/dist/runtime/scalar-runtime.d.ts +4 -21
- package/dist/runtime/scalar-runtime.js +91 -31
- package/dist/runtime/thenable.guard.d.ts +7 -0
- package/dist/runtime/thenable.guard.js +5 -0
- package/dist/runtime/unsent-value.normalizer.d.ts +15 -0
- package/dist/runtime/unsent-value.normalizer.js +129 -0
- package/dist/transactions/operation-arguments-encoder.js +9 -10
- package/dist/transactions/operation-fingerprint.js +2 -2
- package/dist/transactions/sql-statement.d.ts +10 -2
- package/dist/transactions/sql-statement.validator.d.ts +2 -2
- package/dist/transactions/sql-statement.validator.js +40 -6
- package/dist/transactions/transaction-envelope.d.ts +5 -4
- package/dist/transactions/transaction-integrity-error.js +2 -0
- package/dist/transactions/transaction-plan-assembler.d.ts +12 -5
- package/dist/transactions/transaction-plan-assembler.js +49 -17
- package/dist/transactions/transaction-plan-validator.d.ts +23 -7
- package/dist/transactions/transaction-plan-validator.js +31 -7
- package/dist/transactions/transaction-reference-collector.js +8 -10
- package/dist/transactions/transaction-reference-resolver.d.ts +3 -2
- package/dist/transactions/transaction-reference-resolver.js +1 -3
- package/dist/transactions/transaction-reference-validator.d.ts +43 -3
- package/dist/transactions/transaction-reference-validator.js +83 -57
- package/dist/transactions/transaction-reference.d.ts +1 -1
- package/dist/transactions/transaction-reference.js +5 -0
- package/dist/transactions/transaction-request.d.ts +8 -8
- package/dist/transactions/transaction-runtime.d.ts +5 -2
- package/dist/transactions/transaction-runtime.js +108 -27
- package/dist/transactions/transaction-settlement.runtime.d.ts +4 -3
- package/dist/transactions/transaction-slot-path-error.js +2 -0
- package/dist/transactions/transaction-stage.runtime.d.ts +5 -3
- package/dist/transactions/transaction-stage.runtime.js +8 -7
- package/package.json +6 -5
- package/src/runtime/field-check.evaluator.ts +1 -1
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
import { compileContracts } from "../compiler/contract.compiler.js";
|
|
2
|
-
import {
|
|
1
|
+
import { compileContracts, } from "../compiler/contract.compiler.js";
|
|
2
|
+
import { validateManagedDeletes } from "../compiler/managed-elsewhere.validator.js";
|
|
3
|
+
import { computedFieldsOf, warnOnStaleComputedFields, } from "../config/computed-fields.js";
|
|
4
|
+
import { resolveFrameworkConfig, } from "../config/config.resolver.js";
|
|
3
5
|
import { validateFrameworkConfig } from "../config/config.validator.js";
|
|
4
6
|
import { validateForcedOperations } from "../config/forced-operation.validator.js";
|
|
5
7
|
import { AVENTARA_PROTOCOL_VERSION } from "../contracts/contract-protocol.js";
|
|
6
|
-
import {
|
|
8
|
+
import { recordAccessProvider } from "../policy/access-provider.registry.js";
|
|
9
|
+
import { recordAccessQuestions } from "../policy/access-question.registry.js";
|
|
10
|
+
import { createAccessQuestionAnswerer } from "../policy/access-question.runtime.js";
|
|
11
|
+
import { heldTargetsOf } from "../policy/policy-reference-write.runtime.js";
|
|
12
|
+
import { callerOf, derivePolicyCaller, } from "../policy/policy-request.js";
|
|
13
|
+
import { policyStartupDiagnostics } from "../policy/policy-startup.validator.js";
|
|
14
|
+
import { loadPrebuiltContracts, warnStalePrebuilt, } from "../prebuilt/prebuilt-contracts.loader.js";
|
|
15
|
+
import { copyAtDoor, copyEnvelopeAtDoor, refuseCallerData, } from "../runtime/caller-data.door.js";
|
|
7
16
|
import { createDiagnosticsReporter, createTransactionDiagnosticsChannel, recordDiagnosticsSink, } from "../runtime/diagnostics-reporter.js";
|
|
8
17
|
import { createMisuseReporter, } from "../runtime/misuse-reporter.js";
|
|
9
18
|
import { internalFailure, operationFailure, } from "../runtime/operation-response.js";
|
|
@@ -12,10 +21,13 @@ import { recordOwnedExecution } from "../runtime/owned-execution.registry.js";
|
|
|
12
21
|
import { validateOperationEnvelope, validateTransactionEnvelope, } from "../runtime/request-envelope.validator.js";
|
|
13
22
|
import { requestIdOf } from "../runtime/request-id.js";
|
|
14
23
|
import { stateOptionOf } from "../runtime/request-state.resolver.js";
|
|
24
|
+
import { encodeOperationArgumentsForWire } from "../transactions/operation-arguments-encoder.js";
|
|
15
25
|
import { createTransactionPlanAssembler } from "../transactions/transaction-plan-assembler.js";
|
|
16
26
|
import { createTransactionRuntime } from "../transactions/transaction-runtime.js";
|
|
27
|
+
import { createServerClientAccess } from "./access-facade.js";
|
|
17
28
|
import { AvConstructionError } from "./framework-construction.error.js";
|
|
18
|
-
import { createOperationFacade, createOperationTree, settleOperation, } from "./operation-facade.js";
|
|
29
|
+
import { createAbortableOperationFacade, createOperationFacade, createOperationTree, settleOperation, } from "./operation-facade.js";
|
|
30
|
+
import { runOperationSet } from "./operation-set.runner.js";
|
|
19
31
|
const APPLICATION_SQL_BUILDER = "$sql";
|
|
20
32
|
export async function createFramework(config) {
|
|
21
33
|
const configDiagnostics = validateFrameworkConfig(config);
|
|
@@ -34,14 +46,34 @@ export async function createFramework(config) {
|
|
|
34
46
|
]);
|
|
35
47
|
}
|
|
36
48
|
const resolvedConfig = resolveFrameworkConfig(config);
|
|
37
|
-
|
|
49
|
+
warnOnStaleComputedFields(config.adapter.computedFields, computedFieldsOf({
|
|
50
|
+
trees: resolvedConfig.trees,
|
|
51
|
+
agentExtends: resolvedConfig.agent.parent,
|
|
52
|
+
}));
|
|
53
|
+
const compilation = (config.prebuilt === undefined
|
|
54
|
+
? undefined
|
|
55
|
+
: await prebuiltCompilation(config.prebuilt, model, config, resolvedConfig)) ?? (await compileContracts(model, resolvedConfig));
|
|
38
56
|
if (!compilation.ok) {
|
|
39
57
|
throw new AvConstructionError("contract-compilation", compilation.diagnostics);
|
|
40
58
|
}
|
|
59
|
+
const clashes = serverClientClashes(compilation.contracts);
|
|
60
|
+
if (clashes.length > 0) {
|
|
61
|
+
throw new AvConstructionError("contract-compilation", clashes);
|
|
62
|
+
}
|
|
41
63
|
const forcing = validateForcedOperations(config, compilation.contracts);
|
|
42
64
|
if (forcing.length > 0) {
|
|
43
65
|
throw new AvConstructionError("configuration", forcing);
|
|
44
66
|
}
|
|
67
|
+
const managedDeletes = validateManagedDeletes(compilation.contracts, config.adapter.referentialActions);
|
|
68
|
+
if (managedDeletes.length > 0) {
|
|
69
|
+
throw new AvConstructionError("configuration", managedDeletes);
|
|
70
|
+
}
|
|
71
|
+
if (resolvedConfig.policy !== undefined) {
|
|
72
|
+
const policy = policyStartupDiagnostics(compilation.contracts.core, resolvedConfig.policy, model);
|
|
73
|
+
if (policy.length > 0) {
|
|
74
|
+
throw new AvConstructionError("configuration", policy);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
45
77
|
const runtimeDependencies = {
|
|
46
78
|
adapter: config.adapter,
|
|
47
79
|
contracts: compilation.contracts,
|
|
@@ -51,12 +83,31 @@ export async function createFramework(config) {
|
|
|
51
83
|
const execute = createOperationRuntime(runtimeDependencies, pipelineDependencies);
|
|
52
84
|
const executeTransaction = createTransactionRuntime(runtimeDependencies, pipelineDependencies);
|
|
53
85
|
const misuse = createMisuseReporter(resolvedConfig.misuse);
|
|
54
|
-
const executeOperation = (request) => executeTotally(execute, request, resolvedConfig.diagnostics, "caller");
|
|
86
|
+
const executeOperation = (request, caller) => executeTotally(execute, request, resolvedConfig.diagnostics, "caller", caller);
|
|
87
|
+
const prepareApplicationValues = (request, caller) => ((copy) => () => executeTotally(encodingApplicationValues(execute, compilation.contracts.client, copy), request, resolvedConfig.diagnostics, "caller", caller))(copyArgumentsNow(request.arguments));
|
|
55
88
|
const protocol = {
|
|
56
89
|
version: AVENTARA_PROTOCOL_VERSION,
|
|
57
90
|
hash: compilation.contracts.client.protocol.hash,
|
|
58
91
|
};
|
|
59
92
|
const assembler = createTransactionPlanAssembler(compilation.contracts, protocol, misuse);
|
|
93
|
+
const clientRequest = (resource, identity, args, requestId, state) => ({
|
|
94
|
+
...identity,
|
|
95
|
+
origin: "client",
|
|
96
|
+
protocol,
|
|
97
|
+
requestId,
|
|
98
|
+
...(state === undefined ? {} : { state }),
|
|
99
|
+
resource,
|
|
100
|
+
arguments: args,
|
|
101
|
+
});
|
|
102
|
+
const accessAnswerer = compilation.contracts.client.access === undefined
|
|
103
|
+
? undefined
|
|
104
|
+
: createAccessQuestionAnswerer({
|
|
105
|
+
contracts: compilation.contracts,
|
|
106
|
+
policy: resolvedConfig.policy,
|
|
107
|
+
adapter: config.adapter,
|
|
108
|
+
diagnostics: resolvedConfig.diagnostics,
|
|
109
|
+
misuse,
|
|
110
|
+
});
|
|
60
111
|
const framework = {
|
|
61
112
|
api: resolvedConfig.api,
|
|
62
113
|
mcp: resolvedConfig.mcp,
|
|
@@ -69,35 +120,87 @@ export async function createFramework(config) {
|
|
|
69
120
|
resource,
|
|
70
121
|
arguments: args,
|
|
71
122
|
}), executeOperation),
|
|
72
|
-
client: createOperationFacade(model,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
123
|
+
client: createOperationFacade(model, clientRequest, executeOperation),
|
|
124
|
+
serverClient: withServerClientMembers(createAbortableOperationFacade(model, clientRequest, prepareApplicationValues), (entries, options) => runOperationSet(entries, options, compilation.contracts.client.limits), accessAnswerer === undefined
|
|
125
|
+
? undefined
|
|
126
|
+
: createServerClientAccess({
|
|
127
|
+
contract: compilation.contracts.client,
|
|
128
|
+
answer: accessAnswerer,
|
|
129
|
+
client: config.access?.client,
|
|
130
|
+
state: (input) => config.access.state(input),
|
|
131
|
+
})),
|
|
81
132
|
appTx: Object.freeze({
|
|
82
133
|
...createOperationTree(model, (resource, identity) => (args) => assembler.defer("application", resource, identity, args === undefined ? {} : args)),
|
|
83
134
|
[APPLICATION_SQL_BUILDER]: (strings, ...values) => assembler.deferSql(strings, values),
|
|
84
135
|
}),
|
|
85
136
|
clientTx: createOperationTree(model, (resource, identity) => (args) => assembler.defer("client", resource, identity, args === undefined ? {} : args)),
|
|
137
|
+
serverClientTx: createOperationTree(model, (resource, identity) => (args) => assembler.defer("client", resource, identity, args === undefined ? {} : args, "application")),
|
|
86
138
|
execute: (request) => executeRequestTotally(execute, request, resolvedConfig.diagnostics, misuse),
|
|
87
139
|
executeTransaction: (request) => executeTransactionRequestTotally(executeTransaction, request, resolvedConfig.diagnostics, misuse),
|
|
88
|
-
transaction: (async (operations, options) => settleOperation(await runTransactionTotally(executeTransaction, assembler, operations, requestIdOf(options), stateOptionOf(options), resolvedConfig.diagnostics))),
|
|
140
|
+
transaction: (async (operations, options) => settleOperation(await runTransactionTotally(executeTransaction, assembler, operations, requestIdOf(options), stateOptionOf(options), resolvedConfig.diagnostics, callerOf(options)))),
|
|
89
141
|
};
|
|
90
142
|
recordDiagnosticsSink(framework, resolvedConfig.diagnostics);
|
|
143
|
+
recordAccessProvider(framework, config.access);
|
|
144
|
+
if (accessAnswerer !== undefined) {
|
|
145
|
+
recordAccessQuestions(framework, accessAnswerer);
|
|
146
|
+
}
|
|
91
147
|
recordOwnedExecution(framework, {
|
|
92
|
-
execute: (request) => executeTotally(execute, request, resolvedConfig.diagnostics, "owned"),
|
|
93
|
-
|
|
148
|
+
execute: (request, refused, member) => executeTotally(execute, request, resolvedConfig.diagnostics, refused === undefined ? "owned" : { refused }, member?.caller, member?.key),
|
|
149
|
+
caller: (request) => derivePolicyCaller(resolvedConfig.policy, request),
|
|
150
|
+
executeTransaction: (request, refused) => executeTransactionTotally(executeTransaction, request, resolvedConfig.diagnostics, undefined, refused === undefined
|
|
151
|
+
? { source: "owned" }
|
|
152
|
+
: { source: "owned", refused }),
|
|
94
153
|
});
|
|
154
|
+
if (resolvedConfig.policy !== undefined) {
|
|
155
|
+
await resolvedConfig.policy.engine.hosted?.({
|
|
156
|
+
held: heldTargetsOf(compilation.contracts.core, resolvedConfig.policy.unheld),
|
|
157
|
+
});
|
|
158
|
+
}
|
|
95
159
|
return framework;
|
|
96
160
|
}
|
|
97
|
-
async function
|
|
98
|
-
|
|
161
|
+
async function prebuiltCompilation(prebuilt, model, config, resolved) {
|
|
162
|
+
let loaded;
|
|
163
|
+
try {
|
|
164
|
+
loaded = await loadPrebuiltContracts(prebuilt, model, config, resolved);
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
loaded = {
|
|
168
|
+
ok: false,
|
|
169
|
+
reason: `it could not be read (${error instanceof Error ? error.message : String(error)})`,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
if (!loaded.ok) {
|
|
173
|
+
warnStalePrebuilt(loaded.reason);
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
return { ok: true, contracts: loaded.contracts };
|
|
177
|
+
}
|
|
178
|
+
function copyArgumentsNow(args) {
|
|
99
179
|
try {
|
|
100
|
-
return
|
|
180
|
+
return copyAtDoor(args);
|
|
181
|
+
}
|
|
182
|
+
catch (thrown) {
|
|
183
|
+
return { thrown };
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function encodingApplicationValues(execute, contract, copy) {
|
|
187
|
+
return (request, report, _source, caller) => {
|
|
188
|
+
if ("thrown" in copy) {
|
|
189
|
+
throw copy.thrown;
|
|
190
|
+
}
|
|
191
|
+
if (!copy.ok) {
|
|
192
|
+
return execute(request, report, { refused: copy.error }, caller);
|
|
193
|
+
}
|
|
194
|
+
return execute({
|
|
195
|
+
...request,
|
|
196
|
+
arguments: encodeOperationArgumentsForWire(contract, request, copy.value),
|
|
197
|
+
}, report, "owned", caller);
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
async function executeTotally(execute, request, diagnostics, source, caller, key) {
|
|
201
|
+
const report = createDiagnosticsReporter(diagnostics, request, undefined, key);
|
|
202
|
+
try {
|
|
203
|
+
return await execute(request, report, source, caller);
|
|
101
204
|
}
|
|
102
205
|
catch (error) {
|
|
103
206
|
report(error, "A3000");
|
|
@@ -138,18 +241,18 @@ function executeTransactionRequestTotally(execute, request, diagnostics, misuse)
|
|
|
138
241
|
}
|
|
139
242
|
return executeTransactionTotally(execute, envelope.value, diagnostics, undefined, { source: "caller" });
|
|
140
243
|
}
|
|
141
|
-
async function executeTransactionTotally(execute, request, diagnostics, origins, planArguments) {
|
|
244
|
+
async function executeTransactionTotally(execute, request, diagnostics, origins, planArguments, caller) {
|
|
142
245
|
const channel = createTransactionDiagnosticsChannel(diagnostics, request);
|
|
143
246
|
const report = channel.transaction();
|
|
144
247
|
try {
|
|
145
|
-
return await execute(request, channel, origins, planArguments);
|
|
248
|
+
return await execute(request, channel, origins, planArguments, caller);
|
|
146
249
|
}
|
|
147
250
|
catch (error) {
|
|
148
251
|
report(error, "A3000");
|
|
149
252
|
return internalFailure();
|
|
150
253
|
}
|
|
151
254
|
}
|
|
152
|
-
async function runTransactionTotally(execute, assembler, operations, requestId, state, diagnostics) {
|
|
255
|
+
async function runTransactionTotally(execute, assembler, operations, requestId, state, diagnostics, caller) {
|
|
153
256
|
let assembled;
|
|
154
257
|
try {
|
|
155
258
|
assembled = await assembler.assemble(operations);
|
|
@@ -174,5 +277,23 @@ async function runTransactionTotally(execute, assembler, operations, requestId,
|
|
|
174
277
|
source: "owned",
|
|
175
278
|
refused: assembled.refused,
|
|
176
279
|
statements: assembled.statements,
|
|
280
|
+
}, caller);
|
|
281
|
+
}
|
|
282
|
+
function withServerClientMembers(facade, all, access) {
|
|
283
|
+
return Object.freeze({
|
|
284
|
+
...facade,
|
|
285
|
+
all,
|
|
286
|
+
...(access === undefined ? {} : { $access: access }),
|
|
177
287
|
});
|
|
178
288
|
}
|
|
289
|
+
function serverClientClashes(contracts) {
|
|
290
|
+
return Object.hasOwn(contracts.client.resources, "all")
|
|
291
|
+
? [
|
|
292
|
+
{
|
|
293
|
+
code: "COMPILER_RESERVED_RESOURCE_NAME",
|
|
294
|
+
path: "adapter.model.resources.all",
|
|
295
|
+
message: 'resource "all" clashes with serverClient.all; rename the Resource or expose it under another name',
|
|
296
|
+
},
|
|
297
|
+
]
|
|
298
|
+
: [];
|
|
299
|
+
}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import type { AvAdapterModel } from "../adapters/adapter-model.js";
|
|
2
2
|
import type { AvContract } from "../contracts/contract.js";
|
|
3
3
|
import type { AvApplicationScalarForms, AvWireScalarForms } from "../contracts/scalar-value-type.js";
|
|
4
|
-
import type { AvResourceKey } from "../operations/operation-arguments.js";
|
|
5
|
-
import type {
|
|
4
|
+
import type { AvOperationArgumentsFor, AvResourceKey } from "../operations/operation-arguments.js";
|
|
5
|
+
import type { AvOperationCall, AvOperationGrammar, DeferredArguments, DeferredPlainCall, DeferredProjectingCall, PlainCall, ProjectingCall } from "../operations/operation-call.js";
|
|
6
6
|
import type { AvOperationIdentity } from "../operations/operation-identity.js";
|
|
7
|
+
import { type PolicyCaller } from "../policy/policy-request.js";
|
|
7
8
|
import type { AvExecutionOptions } from "../runtime/execution-options.js";
|
|
8
|
-
import type {
|
|
9
|
+
import type { AvOperationRequest } from "../runtime/operation-request.js";
|
|
9
10
|
import type { AvOperationResponse } from "../runtime/operation-response.js";
|
|
10
11
|
import type { AvState } from "../runtime/request-state.js";
|
|
11
|
-
import type {
|
|
12
|
+
import type { AvSqlStatementBuilder } from "../transactions/sql-statement.js";
|
|
12
13
|
import type { AvTransactionResponse } from "../transactions/transaction-response.js";
|
|
14
|
+
import type { AccessProviderOf, ServerClientAccess } from "./access-facade.js";
|
|
13
15
|
import type { AvContractApplicationView, ClientContractView } from "./contract-view.js";
|
|
14
16
|
/**
|
|
15
17
|
* A model whose Resource names are not literal — the abstract `AvAdapterModel` behind
|
|
@@ -19,13 +21,62 @@ import type { AvContractApplicationView, ClientContractView } from "./contract-v
|
|
|
19
21
|
type OpaqueSurface = {
|
|
20
22
|
readonly [resource: string]: unknown;
|
|
21
23
|
};
|
|
22
|
-
/** The
|
|
23
|
-
type FacadeSurface = "application" | "client" | "appTx" | "clientTx";
|
|
24
|
+
/** The typed surfaces of an `AvFramework`, named by the member that holds each. */
|
|
25
|
+
type FacadeSurface = "application" | "client" | "serverClient" | "appTx" | "clientTx" | "serverClientTx";
|
|
26
|
+
/** `framework.application.<Resource>.<family>.<variant>` when the variant takes a `select` or `include`. */
|
|
27
|
+
export type AvApplicationProjectingCall<in out C extends AvContract, in out R extends AvResourceKey<C>, in out I extends AvOperationIdentity> = ProjectingCall<C, R, I, AvOperationArgumentsFor<C, R, I, AvApplicationScalarForms>, AvApplicationScalarForms, AvExecutionOptions>;
|
|
28
|
+
/** `framework.application.<Resource>.<family>.<variant>` when it does not (the `count` variants). */
|
|
29
|
+
export type AvApplicationPlainCall<in out C extends AvContract, in out R extends AvResourceKey<C>, in out I extends AvOperationIdentity> = PlainCall<C, R, I, AvOperationArgumentsFor<C, R, I, AvApplicationScalarForms>, AvApplicationScalarForms, AvExecutionOptions>;
|
|
30
|
+
/** `framework.client.<Resource>.<family>.<variant>` when the variant takes a `select` or `include`: wire forms in. */
|
|
31
|
+
export type AvClientProjectingCall<in out C extends AvContract, in out R extends AvResourceKey<C>, in out I extends AvOperationIdentity> = ProjectingCall<C, R, I, AvOperationArgumentsFor<C, R, I, AvWireScalarForms>, AvApplicationScalarForms, AvExecutionOptions>;
|
|
32
|
+
/** `framework.client.<Resource>.<family>.<variant>` when it does not. */
|
|
33
|
+
export type AvClientPlainCall<in out C extends AvContract, in out R extends AvResourceKey<C>, in out I extends AvOperationIdentity> = PlainCall<C, R, I, AvOperationArgumentsFor<C, R, I, AvWireScalarForms>, AvApplicationScalarForms, AvExecutionOptions>;
|
|
34
|
+
/** `framework.appTx.<Resource>.<family>.<variant>` when the variant takes a `select` or `include`. */
|
|
35
|
+
export type AvAppTxProjectingCall<in out C extends AvContract, in out R extends AvResourceKey<C>, in out I extends AvOperationIdentity> = DeferredProjectingCall<C, R, I, DeferredArguments<C, R, I, AvApplicationScalarForms, AvApplicationScalarForms>, AvApplicationScalarForms, "application">;
|
|
36
|
+
/** `framework.appTx.<Resource>.<family>.<variant>` when it does not. */
|
|
37
|
+
export type AvAppTxPlainCall<in out C extends AvContract, in out R extends AvResourceKey<C>, in out I extends AvOperationIdentity> = DeferredPlainCall<C, R, I, DeferredArguments<C, R, I, AvApplicationScalarForms, AvApplicationScalarForms>, AvApplicationScalarForms, "application">;
|
|
38
|
+
/** `framework.clientTx.<Resource>.<family>.<variant>` when the variant takes a `select` or `include`: wire forms in. */
|
|
39
|
+
export type AvClientTxProjectingCall<in out C extends AvContract, in out R extends AvResourceKey<C>, in out I extends AvOperationIdentity> = DeferredProjectingCall<C, R, I, DeferredArguments<C, R, I, AvWireScalarForms, AvApplicationScalarForms>, AvApplicationScalarForms, "client">;
|
|
40
|
+
/** `framework.clientTx.<Resource>.<family>.<variant>` when it does not. */
|
|
41
|
+
export type AvClientTxPlainCall<in out C extends AvContract, in out R extends AvResourceKey<C>, in out I extends AvOperationIdentity> = DeferredPlainCall<C, R, I, DeferredArguments<C, R, I, AvWireScalarForms, AvApplicationScalarForms>, AvApplicationScalarForms, "client">;
|
|
42
|
+
/** A `serverClient` call's options: {@link AvExecutionOptions}, and the call's own abort signal. */
|
|
43
|
+
type AvServerClientCallOptions = AvExecutionOptions & {
|
|
44
|
+
/**
|
|
45
|
+
* Aborts this call only. Aborted before the call runs, it never runs;
|
|
46
|
+
* while it runs, it rejects with the signal's reason at once, and the
|
|
47
|
+
* database finishes what it started. Any platform's `AbortSignal` is one.
|
|
48
|
+
*/
|
|
49
|
+
readonly signal?: {
|
|
50
|
+
readonly aborted: boolean;
|
|
51
|
+
readonly reason: unknown;
|
|
52
|
+
addEventListener(type: "abort", listener: () => void, options?: {
|
|
53
|
+
readonly once?: boolean;
|
|
54
|
+
}): void;
|
|
55
|
+
removeEventListener(type: "abort", listener: () => void): void;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* `framework.serverClient.<Resource>.<family>.<variant>` when the variant takes a `select` or `include`:
|
|
60
|
+
* the Client Contract's view, application forms in.
|
|
61
|
+
*/
|
|
62
|
+
export type AvServerClientProjectingCall<in out C extends AvContract, in out R extends AvResourceKey<C>, in out I extends AvOperationIdentity> = ProjectingCall<C, R, I, AvOperationArgumentsFor<C, R, I, AvApplicationScalarForms>, AvApplicationScalarForms, AvServerClientCallOptions>;
|
|
63
|
+
/** `framework.serverClient.<Resource>.<family>.<variant>` when it does not. */
|
|
64
|
+
export type AvServerClientPlainCall<in out C extends AvContract, in out R extends AvResourceKey<C>, in out I extends AvOperationIdentity> = PlainCall<C, R, I, AvOperationArgumentsFor<C, R, I, AvApplicationScalarForms>, AvApplicationScalarForms, AvServerClientCallOptions>;
|
|
65
|
+
/**
|
|
66
|
+
* `framework.serverClientTx.<Resource>.<family>.<variant>` when the variant takes a `select` or `include`:
|
|
67
|
+
* the Client Contract's view, application forms in, a client-origin handle out.
|
|
68
|
+
*/
|
|
69
|
+
export type AvServerClientTxProjectingCall<in out C extends AvContract, in out R extends AvResourceKey<C>, in out I extends AvOperationIdentity> = DeferredProjectingCall<C, R, I, DeferredArguments<C, R, I, AvApplicationScalarForms, AvApplicationScalarForms>, AvApplicationScalarForms, "client">;
|
|
70
|
+
/** `framework.serverClientTx.<Resource>.<family>.<variant>` when it does not. */
|
|
71
|
+
export type AvServerClientTxPlainCall<in out C extends AvContract, in out R extends AvResourceKey<C>, in out I extends AvOperationIdentity> = DeferredPlainCall<C, R, I, DeferredArguments<C, R, I, AvApplicationScalarForms, AvApplicationScalarForms>, AvApplicationScalarForms, "client">;
|
|
24
72
|
/**
|
|
25
73
|
* One variant on a surface: a direct call (application or wire forms), or a
|
|
26
|
-
* deferred one for a transaction (`appTx`, `clientTx`)
|
|
74
|
+
* deferred one for a transaction (`appTx`, `clientTx`, `serverClientTx`),
|
|
75
|
+
* projecting when its arguments carry a `select` (as `AvOperationCall` and
|
|
76
|
+
* `AvDeferredOperationCall` decide it). `serverClient` and `serverClientTx` take
|
|
77
|
+
* the application forms over the Client Contract's view.
|
|
27
78
|
*/
|
|
28
|
-
type SurfaceCall<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, S extends FacadeSurface> = S extends "application" ?
|
|
79
|
+
type SurfaceCall<C extends AvContract, R extends AvResourceKey<C>, I extends AvOperationIdentity, S extends FacadeSurface> = S extends "application" ? "select" extends keyof AvOperationArgumentsFor<C, R, I, AvApplicationScalarForms> ? AvApplicationProjectingCall<C, R, I> : AvApplicationPlainCall<C, R, I> : S extends "client" ? "select" extends keyof AvOperationArgumentsFor<C, R, I, AvWireScalarForms> ? AvClientProjectingCall<C, R, I> : AvClientPlainCall<C, R, I> : S extends "serverClient" ? "select" extends keyof AvOperationArgumentsFor<C, R, I, AvApplicationScalarForms> ? AvServerClientProjectingCall<C, R, I> : AvServerClientPlainCall<C, R, I> : S extends "appTx" ? "select" extends keyof DeferredArguments<C, R, I, AvApplicationScalarForms, AvApplicationScalarForms> ? AvAppTxProjectingCall<C, R, I> : AvAppTxPlainCall<C, R, I> : S extends "clientTx" ? "select" extends keyof DeferredArguments<C, R, I, AvWireScalarForms, AvApplicationScalarForms> ? AvClientTxProjectingCall<C, R, I> : AvClientTxPlainCall<C, R, I> : "select" extends keyof DeferredArguments<C, R, I, AvApplicationScalarForms, AvApplicationScalarForms> ? AvServerClientTxProjectingCall<C, R, I> : AvServerClientTxPlainCall<C, R, I>;
|
|
29
80
|
/** The families view `C` advertises on Resource `R`. */
|
|
30
81
|
type FamilyKey<C extends AvContract, R extends AvResourceKey<C>> = keyof AvOperationGrammar<C>[R];
|
|
31
82
|
/** One family node of surface `S`; the public names below are its four instances. */
|
|
@@ -36,10 +87,14 @@ type FamilyNode<C extends AvContract, S extends FacadeSurface, R extends AvResou
|
|
|
36
87
|
export type AvApplicationFamilyFacade<in out C extends AvContract, in out R extends AvResourceKey<C>, in out F extends FamilyKey<C, R>> = FamilyNode<C, "application", R, F>;
|
|
37
88
|
/** `framework.client.<Resource>.<family>`: one direct call per variant, wire forms. */
|
|
38
89
|
export type AvClientFamilyFacade<in out C extends AvContract, in out R extends AvResourceKey<C>, in out F extends FamilyKey<C, R>> = FamilyNode<C, "client", R, F>;
|
|
90
|
+
/** `framework.serverClient.<Resource>.<family>`: one direct call per variant, application forms. */
|
|
91
|
+
export type AvServerClientFamilyFacade<in out C extends AvContract, in out R extends AvResourceKey<C>, in out F extends FamilyKey<C, R>> = FamilyNode<C, "serverClient", R, F>;
|
|
39
92
|
/** `framework.appTx.<Resource>.<family>`: one deferred operation per variant. */
|
|
40
93
|
export type AvAppTxFamilyFacade<in out C extends AvContract, in out R extends AvResourceKey<C>, in out F extends FamilyKey<C, R>> = FamilyNode<C, "appTx", R, F>;
|
|
41
94
|
/** `framework.clientTx.<Resource>.<family>`: one deferred operation per variant. */
|
|
42
95
|
export type AvClientTxFamilyFacade<in out C extends AvContract, in out R extends AvResourceKey<C>, in out F extends FamilyKey<C, R>> = FamilyNode<C, "clientTx", R, F>;
|
|
96
|
+
/** `framework.serverClientTx.<Resource>.<family>`: one deferred operation per variant, application forms. */
|
|
97
|
+
export type AvServerClientTxFamilyFacade<in out C extends AvContract, in out R extends AvResourceKey<C>, in out F extends FamilyKey<C, R>> = FamilyNode<C, "serverClientTx", R, F>;
|
|
43
98
|
/** `framework.application.<Resource>`: one {@link AvApplicationFamilyFacade} per family. */
|
|
44
99
|
export type AvApplicationResourceFacade<in out C extends AvContract, in out R extends AvResourceKey<C>> = {
|
|
45
100
|
readonly [F in FamilyKey<C, R>]: AvApplicationFamilyFacade<C, R, F>;
|
|
@@ -48,6 +103,10 @@ export type AvApplicationResourceFacade<in out C extends AvContract, in out R ex
|
|
|
48
103
|
export type AvClientResourceFacade<in out C extends AvContract, in out R extends AvResourceKey<C>> = {
|
|
49
104
|
readonly [F in FamilyKey<C, R>]: AvClientFamilyFacade<C, R, F>;
|
|
50
105
|
};
|
|
106
|
+
/** `framework.serverClient.<Resource>`: one {@link AvServerClientFamilyFacade} per family. */
|
|
107
|
+
export type AvServerClientResourceFacade<in out C extends AvContract, in out R extends AvResourceKey<C>> = {
|
|
108
|
+
readonly [F in FamilyKey<C, R>]: AvServerClientFamilyFacade<C, R, F>;
|
|
109
|
+
};
|
|
51
110
|
/** `framework.appTx.<Resource>`: one {@link AvAppTxFamilyFacade} per family. */
|
|
52
111
|
export type AvAppTxResourceFacade<in out C extends AvContract, in out R extends AvResourceKey<C>> = {
|
|
53
112
|
readonly [F in FamilyKey<C, R>]: AvAppTxFamilyFacade<C, R, F>;
|
|
@@ -56,6 +115,10 @@ export type AvAppTxResourceFacade<in out C extends AvContract, in out R extends
|
|
|
56
115
|
export type AvClientTxResourceFacade<in out C extends AvContract, in out R extends AvResourceKey<C>> = {
|
|
57
116
|
readonly [F in FamilyKey<C, R>]: AvClientTxFamilyFacade<C, R, F>;
|
|
58
117
|
};
|
|
118
|
+
/** `framework.serverClientTx.<Resource>`: one {@link AvServerClientTxFamilyFacade} per family. */
|
|
119
|
+
export type AvServerClientTxResourceFacade<in out C extends AvContract, in out R extends AvResourceKey<C>> = {
|
|
120
|
+
readonly [F in FamilyKey<C, R>]: AvServerClientTxFamilyFacade<C, R, F>;
|
|
121
|
+
};
|
|
59
122
|
/**
|
|
60
123
|
* `framework.application`: one {@link AvApplicationResourceFacade} per Resource
|
|
61
124
|
* of `C`, the Application Contract's view.
|
|
@@ -70,14 +133,58 @@ export type AvApplicationFacade<C extends AvContract> = {
|
|
|
70
133
|
export type AvClientFacade<C extends AvContract> = {
|
|
71
134
|
readonly [R in AvResourceKey<C>]: AvClientResourceFacade<C, R>;
|
|
72
135
|
};
|
|
136
|
+
/** `framework.serverClient.all`: its own member beside the Resources. */
|
|
137
|
+
type ServerClientAll = {
|
|
138
|
+
/**
|
|
139
|
+
* Awaits an object of calls together, in process (any number of them:
|
|
140
|
+
* `limits.maxAll` guards the HTTP door only), and resolves one value per key. A call already runs when it is made;
|
|
141
|
+
* an `avLazy(() => call)` entry is started by `all`, at most
|
|
142
|
+
* `limits.maxAllConcurrency` at once. Strict: the first failure rejects it
|
|
143
|
+
* and its `avLazy` entries not yet started never start (fail-fast, not
|
|
144
|
+
* atomic: what already ran stays done). With `settle: true` every key settles as `{ status, value }`
|
|
145
|
+
* or `{ status, reason }`. Its `signal` aborts each of its calls and no other.
|
|
146
|
+
*/
|
|
147
|
+
readonly all: <E extends {
|
|
148
|
+
readonly [key: string]: PromiseLike<unknown>;
|
|
149
|
+
}, S extends boolean = false>(entries: E, options?: {
|
|
150
|
+
/** Aborts every call of this `all`, and no other. Any platform's `AbortSignal` is one. */
|
|
151
|
+
readonly signal?: {
|
|
152
|
+
readonly aborted: boolean;
|
|
153
|
+
readonly reason: unknown;
|
|
154
|
+
addEventListener(type: "abort", listener: () => void, options?: {
|
|
155
|
+
readonly once?: boolean;
|
|
156
|
+
}): void;
|
|
157
|
+
removeEventListener(type: "abort", listener: () => void): void;
|
|
158
|
+
};
|
|
159
|
+
/** true settles every key on its own and never rejects for one; strict otherwise. */
|
|
160
|
+
readonly settle?: S;
|
|
161
|
+
}) => Promise<S extends true ? {
|
|
162
|
+
-readonly [K in keyof E]: {
|
|
163
|
+
readonly status: "fulfilled";
|
|
164
|
+
readonly value: Awaited<E[K]>;
|
|
165
|
+
} | {
|
|
166
|
+
readonly status: "rejected";
|
|
167
|
+
readonly reason: unknown;
|
|
168
|
+
};
|
|
169
|
+
} : {
|
|
170
|
+
-readonly [K in keyof E]: Awaited<E[K]>;
|
|
171
|
+
}>;
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* `framework.serverClient`: one {@link AvServerClientResourceFacade} per Resource
|
|
175
|
+
* of `C`, the Client Contract's view, taking application forms, and `all`.
|
|
176
|
+
*/
|
|
177
|
+
export type AvServerClientFacade<C extends AvContract> = {
|
|
178
|
+
readonly [R in AvResourceKey<C>]: AvServerClientResourceFacade<C, R>;
|
|
179
|
+
} & ServerClientAll;
|
|
73
180
|
/** `framework.appTx.$sql`: the developer SQL step only an application transaction has. */
|
|
74
181
|
type ApplicationSqlStep = {
|
|
75
182
|
/**
|
|
76
183
|
* A developer SQL step, written only as a tagged template:
|
|
77
184
|
* ``framework.appTx.$sql<Row>`select … ${value}` ``. Every interpolated value
|
|
78
|
-
* is bound as a parameter. See {@link
|
|
185
|
+
* is bound as a parameter. See {@link AvSqlStatementBuilder}.
|
|
79
186
|
*/
|
|
80
|
-
readonly $sql:
|
|
187
|
+
readonly $sql: AvSqlStatementBuilder;
|
|
81
188
|
};
|
|
82
189
|
/**
|
|
83
190
|
* `framework.appTx`: one {@link AvAppTxResourceFacade} per Resource of `C`, the
|
|
@@ -93,18 +200,31 @@ export type AvAppTxFacade<C extends AvContract> = {
|
|
|
93
200
|
export type AvClientTxFacade<C extends AvContract> = {
|
|
94
201
|
readonly [R in AvResourceKey<C>]: AvClientTxResourceFacade<C, R>;
|
|
95
202
|
};
|
|
203
|
+
/**
|
|
204
|
+
* `framework.serverClientTx`: one {@link AvServerClientTxResourceFacade} per
|
|
205
|
+
* Resource of `C`, the Client Contract's view, taking application forms.
|
|
206
|
+
*/
|
|
207
|
+
export type AvServerClientTxFacade<C extends AvContract> = {
|
|
208
|
+
readonly [R in AvResourceKey<C>]: AvServerClientTxResourceFacade<C, R>;
|
|
209
|
+
};
|
|
96
210
|
type ApplicationSurface<C> = C extends AvContract ? string extends AvResourceKey<C> ? OpaqueSurface : AvApplicationFacade<C> : never;
|
|
97
211
|
type ClientSurface<C> = C extends AvContract ? string extends AvResourceKey<C> ? OpaqueSurface : AvClientFacade<C> : never;
|
|
212
|
+
type ServerClientSurface<C> = C extends AvContract ? string extends AvResourceKey<C> ? OpaqueSurface & ServerClientAll : AvServerClientFacade<C> : never;
|
|
98
213
|
type ApplicationDeferredSurface<C> = C extends AvContract ? string extends AvResourceKey<C> ? OpaqueSurface & ApplicationSqlStep : AvAppTxFacade<C> : never;
|
|
99
214
|
type ClientDeferredSurface<C> = C extends AvContract ? string extends AvResourceKey<C> ? OpaqueSurface : AvClientTxFacade<C> : never;
|
|
215
|
+
type ServerClientDeferredSurface<C> = C extends AvContract ? string extends AvResourceKey<C> ? OpaqueSurface : AvServerClientTxFacade<C> : never;
|
|
100
216
|
/** `framework.application`'s type: {@link AvApplicationFacade}, or opaque. */
|
|
101
217
|
export type ApplicationOperations<M extends AvAdapterModel, Cfg> = ApplicationSurface<AvContractApplicationView<M, Cfg>>;
|
|
102
218
|
/** `framework.client`'s type: {@link AvClientFacade}, or opaque. */
|
|
103
219
|
export type ClientOperations<M extends AvAdapterModel, Cfg> = ClientSurface<ClientContractView<M, Cfg>>;
|
|
220
|
+
/** `framework.serverClient`'s type: {@link AvServerClientFacade}, or opaque with `all`, and `$access`. */
|
|
221
|
+
export type ServerClientOperations<M extends AvAdapterModel, Cfg> = ServerClientSurface<ClientContractView<M, Cfg>> & ServerClientAccess<ClientContractView<M, Cfg>, AccessProviderOf<Cfg>>;
|
|
104
222
|
/** `framework.appTx`'s type: {@link AvAppTxFacade}, or opaque with `$sql`. */
|
|
105
223
|
export type ApplicationTransactionBuilders<M extends AvAdapterModel, Cfg> = ApplicationDeferredSurface<AvContractApplicationView<M, Cfg>>;
|
|
106
224
|
/** `framework.clientTx`'s type: {@link AvClientTxFacade}, or opaque. */
|
|
107
225
|
export type ClientTransactionBuilders<M extends AvAdapterModel, Cfg> = ClientDeferredSurface<ClientContractView<M, Cfg>>;
|
|
226
|
+
/** `framework.serverClientTx`'s type: {@link AvServerClientTxFacade}, or opaque. */
|
|
227
|
+
export type ServerClientTransactionBuilders<M extends AvAdapterModel, Cfg> = ServerClientDeferredSurface<ClientContractView<M, Cfg>>;
|
|
108
228
|
/**
|
|
109
229
|
* The Resources of a pipeline ctx: `ctx.<Resource>.<family>.<variant>(args)`,
|
|
110
230
|
* application-origin, resolving the operation's data.
|
|
@@ -130,8 +250,8 @@ type ComputeReadFacade<C> = C extends AvContract ? string extends AvResourceKey<
|
|
|
130
250
|
};
|
|
131
251
|
} : never;
|
|
132
252
|
/** Builds the request one façade call hands to `execute`, under its request id and state. */
|
|
133
|
-
export type FacadeRequest = (resource: string, identity: AvOperationIdentity, args: unknown, requestId: string, state: AvState | undefined) =>
|
|
134
|
-
type FacadeExecutor = (request:
|
|
253
|
+
export type FacadeRequest = (resource: string, identity: AvOperationIdentity, args: unknown, requestId: string, state: AvState | undefined) => AvOperationRequest;
|
|
254
|
+
type FacadeExecutor = (request: AvOperationRequest, caller: PolicyCaller | undefined) => Promise<AvOperationResponse>;
|
|
135
255
|
/**
|
|
136
256
|
* Builds a façade over `model`, the same object its types are read from, so a
|
|
137
257
|
* call that type-checks always reaches `execute`: a Resource, variant or field
|
|
@@ -150,11 +270,19 @@ export declare function createOperationFacade<Facade>(model: AvAdapterModel, req
|
|
|
150
270
|
* the response's data, or its failure thrown.
|
|
151
271
|
*/
|
|
152
272
|
export declare function settleOperation(response: AvOperationResponse | AvTransactionResponse): unknown;
|
|
273
|
+
/** Prepares one call's run: its arguments are read when the call is made. */
|
|
274
|
+
type FacadePreparer = (request: AvOperationRequest, caller: PolicyCaller | undefined) => () => Promise<AvOperationResponse>;
|
|
275
|
+
/**
|
|
276
|
+
* {@link createOperationFacade}'s twin for `framework.serverClient`: a call
|
|
277
|
+
* builds its request and runs at once, and the caller's `signal` aborts it
|
|
278
|
+
* (already aborted, it never runs; aborted while it runs, it rejects at once).
|
|
279
|
+
*/
|
|
280
|
+
export declare function createAbortableOperationFacade<Facade>(model: AvAdapterModel, request: FacadeRequest, prepare: FacadePreparer): Facade;
|
|
153
281
|
/**
|
|
154
282
|
* One leaf of an operation tree: the callable for one advertised variant. The
|
|
155
283
|
* second parameter is a façade call's options; a builder leaf ignores it.
|
|
156
284
|
*/
|
|
157
|
-
|
|
285
|
+
type OperationLeaf = (resource: string, identity: AvOperationIdentity) => (args?: unknown, options?: unknown) => unknown;
|
|
158
286
|
/**
|
|
159
287
|
* The runtime shape every façade and builder shares: one frozen property per
|
|
160
288
|
* Resource of `model`, one per family under it, one leaf per variant the model
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { isOperationVariantAvailable } from "../contracts/resource-operations.js";
|
|
2
2
|
import { parseOperationIdentity } from "../operations/operation-identity.js";
|
|
3
|
+
import { callerOf } from "../policy/policy-request.js";
|
|
3
4
|
import { thrownFailure } from "../runtime/framework-error.factory.js";
|
|
4
5
|
import { requestIdOf } from "../runtime/request-id.js";
|
|
5
6
|
import { stateOptionOf } from "../runtime/request-state.resolver.js";
|
|
7
|
+
import { runAbortable, signalOptionOf } from "./operation-set.runner.js";
|
|
6
8
|
export function createOperationFacade(model, request, execute) {
|
|
7
|
-
return createOperationTree(model, (resource, identity) => async (args, options) => settleOperation(await execute(request(resource, identity, args === undefined ? {} : args, requestIdOf(options), stateOptionOf(options)))));
|
|
9
|
+
return createOperationTree(model, (resource, identity) => async (args, options) => settleOperation(await execute(request(resource, identity, args === undefined ? {} : args, requestIdOf(options), stateOptionOf(options)), callerOf(options))));
|
|
8
10
|
}
|
|
9
11
|
export function settleOperation(response) {
|
|
10
12
|
if (response.cause !== null) {
|
|
@@ -12,6 +14,12 @@ export function settleOperation(response) {
|
|
|
12
14
|
}
|
|
13
15
|
return response.data;
|
|
14
16
|
}
|
|
17
|
+
export function createAbortableOperationFacade(model, request, prepare) {
|
|
18
|
+
return createOperationTree(model, (resource, identity) => (args, options) => {
|
|
19
|
+
const run = prepare(request(resource, identity, args === undefined ? {} : args, requestIdOf(options), stateOptionOf(options)), callerOf(options));
|
|
20
|
+
return runAbortable(async () => settleOperation(await run()), signalOptionOf(options));
|
|
21
|
+
});
|
|
22
|
+
}
|
|
15
23
|
export function createOperationTree(model, leaf) {
|
|
16
24
|
const resources = Object.entries(model.resources).map(([resource, { operations }]) => {
|
|
17
25
|
const families = Object.entries(operations).map(([family, variants]) => [family, variantLeaves(leaf, resource, family, variants)]);
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { AvContractLimits } from "../contracts/contract-limits.js";
|
|
2
|
+
/**
|
|
3
|
+
* What core reads of an abort signal: the platform's `AbortSignal` (DOM's,
|
|
4
|
+
* Node's, any runtime's) is one, structurally. Core runs in any JS runtime, so
|
|
5
|
+
* its declarations name no platform global (rc.11): a consumer with neither
|
|
6
|
+
* DOM's lib nor Node's types type-checks them. The public signatures spell this
|
|
7
|
+
* shape inline (`serverClient` calls, `serverClient.all`, the protocol's
|
|
8
|
+
* `handleAll`): no new public name.
|
|
9
|
+
*/
|
|
10
|
+
export type AbortSignalShape = {
|
|
11
|
+
readonly aborted: boolean;
|
|
12
|
+
readonly reason: unknown;
|
|
13
|
+
addEventListener(type: "abort", listener: () => void, options?: {
|
|
14
|
+
readonly once?: boolean;
|
|
15
|
+
}): void;
|
|
16
|
+
removeEventListener(type: "abort", listener: () => void): void;
|
|
17
|
+
};
|
|
18
|
+
/** `options.signal` when it is an abort signal; anything else is ignored. */
|
|
19
|
+
export declare function signalOptionOf(options: unknown): AbortSignalShape | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Runs `run` now under `signal`: an eager call's own abort. Already aborted, it
|
|
22
|
+
* never runs; aborted while it runs, it rejects at once with the signal's reason.
|
|
23
|
+
*/
|
|
24
|
+
export declare function runAbortable(run: () => Promise<unknown>, signal: AbortSignalShape | undefined): Promise<unknown>;
|
|
25
|
+
/**
|
|
26
|
+
* A call made later: `avLazy(() => avClient.Post.find.many(args))` makes the
|
|
27
|
+
* call on each `then`, `catch` or `finally`, never before the first, and
|
|
28
|
+
* answers what that call answers. It keeps no answer: awaited again (by another
|
|
29
|
+
* request, say), it makes the call again, in the context awaiting it. Given to
|
|
30
|
+
* `all`, it is started by `all`, at most `limits.maxAllConcurrency` at once,
|
|
31
|
+
* and never when `all` has already failed (strict) or been aborted.
|
|
32
|
+
*/
|
|
33
|
+
export declare function avLazy<T>(make: () => PromiseLike<T>): Promise<T>;
|
|
34
|
+
/**
|
|
35
|
+
* The Contract's `limits.maxAllConcurrency`, for `all` here and for `POST /_all`
|
|
36
|
+
* (`protocol/operation-set.handler.ts`). A compiled Contract always holds a
|
|
37
|
+
* whole number of at least 1; a hand-built one that does not runs its entries
|
|
38
|
+
* one at a time, never none.
|
|
39
|
+
*/
|
|
40
|
+
export declare function maxAllConcurrencyOf(limits: AvContractLimits): number;
|
|
41
|
+
/**
|
|
42
|
+
* `all(entries, options?)` over `limits` (the Client Contract's): see the module
|
|
43
|
+
* comment. Rejects with a `TypeError`, before anything runs, when `entries` is not
|
|
44
|
+
* an object whose every value is a promise. Any number of entries is accepted:
|
|
45
|
+
* `limits.maxAll` guards the HTTP door only.
|
|
46
|
+
*/
|
|
47
|
+
export declare function runOperationSet(entries: unknown, options: unknown, limits: AvContractLimits): Promise<unknown>;
|