@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
|
@@ -21,6 +21,11 @@ export type PlannedReadOperation = {
|
|
|
21
21
|
readonly projection: ReadProjectionPlan | undefined;
|
|
22
22
|
readonly materialize: boolean;
|
|
23
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* The fields a level returns when it states no projection: every scalar of the
|
|
26
|
+
* active Contract whose `select` is `true` and that is not governed.
|
|
27
|
+
*/
|
|
28
|
+
export declare function defaultProjectionFields(active: AvContract, resourceName: string): readonly string[];
|
|
24
29
|
/**
|
|
25
30
|
* Clone the caller projection into the internal Adapter projection: the read
|
|
26
31
|
* set the Adapter is asked for, always explicit for a projecting variant, plus
|
|
@@ -33,5 +38,5 @@ export declare function planReadOperation(core: AvContractCore, model: AvAdapter
|
|
|
33
38
|
* Materialize computed scalar reads and remove internal dependency fields,
|
|
34
39
|
* against `active` — the Contract `planReadOperation` was given as `active`.
|
|
35
40
|
*/
|
|
36
|
-
export declare function materializeReadOperation(active: AvContract, compute: ResolvedComputeConfig | undefined,
|
|
41
|
+
export declare function materializeReadOperation(active: AvContract, compute: ResolvedComputeConfig | undefined, _request: OperationExecutionRequest, plan: PlannedReadOperation, value: unknown, contextFactory: ContextFactory): Promise<unknown>;
|
|
37
42
|
export {};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { adapterPrimaryIdentifier } from "../adapters/adapter-identifier.js";
|
|
1
2
|
import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
|
|
2
3
|
import { AvComputedValueError } from "./computed-value.error.js";
|
|
4
|
+
import { frozenCopy } from "./readonly-value.js";
|
|
5
|
+
import { isRecord } from "./record.guard.js";
|
|
3
6
|
import { normalizeScalarFieldValue } from "./scalar-runtime.js";
|
|
4
|
-
|
|
5
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
6
|
-
}
|
|
7
|
+
import { isThenable } from "./thenable.guard.js";
|
|
7
8
|
function readCompute(value) {
|
|
8
9
|
if (typeof value === "function") {
|
|
9
10
|
return { compute: value, dependsOn: [] };
|
|
@@ -51,6 +52,11 @@ function addScalarProjection(core, model, active, compute, resourceName, fieldNa
|
|
|
51
52
|
const stage = readCompute(compute?.[resourceName]?.[fieldName]?.read);
|
|
52
53
|
if (stage !== undefined) {
|
|
53
54
|
appendUnique(computed, fieldName);
|
|
55
|
+
if (stage.dependsOn.length === 0) {
|
|
56
|
+
for (const member of adapterPrimaryIdentifier(model, resourceName)) {
|
|
57
|
+
appendUniqueProjection(adapterSelect, member);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
54
60
|
for (const dependency of stage.dependsOn) {
|
|
55
61
|
if (storedScalar(model, resourceName, dependency)) {
|
|
56
62
|
appendUniqueProjection(adapterSelect, dependency);
|
|
@@ -77,18 +83,27 @@ function projectionEntry(entry) {
|
|
|
77
83
|
function withoutProjectionChoice(value) {
|
|
78
84
|
return Object.fromEntries(Object.entries(value).filter(([key]) => key !== "select" && key !== "include"));
|
|
79
85
|
}
|
|
80
|
-
function
|
|
86
|
+
export function defaultProjectionFields(active, resourceName) {
|
|
81
87
|
const activeResource = lookupResource(active, resourceName);
|
|
88
|
+
if (activeResource === undefined) {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
const fields = [];
|
|
92
|
+
for (const [fieldName, field] of Object.entries(activeResource.fields)) {
|
|
93
|
+
if (field.kind === "scalar" &&
|
|
94
|
+
field.capabilities.select === true &&
|
|
95
|
+
field.governed !== true) {
|
|
96
|
+
fields.push(fieldName);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return fields;
|
|
100
|
+
}
|
|
101
|
+
function defaultProjectionLevel(core, model, active, compute, resourceName) {
|
|
82
102
|
const adapterSelect = [];
|
|
83
103
|
const requested = [];
|
|
84
104
|
const computed = [];
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (field.kind !== "scalar" || field.capabilities.select !== true) {
|
|
88
|
-
continue;
|
|
89
|
-
}
|
|
90
|
-
addScalarProjection(core, model, active, compute, resourceName, fieldName, adapterSelect, requested, computed);
|
|
91
|
-
}
|
|
105
|
+
for (const fieldName of defaultProjectionFields(active, resourceName)) {
|
|
106
|
+
addScalarProjection(core, model, active, compute, resourceName, fieldName, adapterSelect, requested, computed);
|
|
92
107
|
}
|
|
93
108
|
return {
|
|
94
109
|
select: adapterSelect,
|
|
@@ -156,6 +171,12 @@ function planSelectLevel(core, model, active, compute, resourceName, select, col
|
|
|
156
171
|
}
|
|
157
172
|
for (const entry of select) {
|
|
158
173
|
if (typeof entry === "string") {
|
|
174
|
+
if (entry === "$defaults") {
|
|
175
|
+
for (const fieldName of defaultProjectionFields(active, resourceName)) {
|
|
176
|
+
addScalarProjection(core, model, active, compute, resourceName, fieldName, adapterSelect, requested, computed);
|
|
177
|
+
}
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
159
180
|
if (entry === "$count") {
|
|
160
181
|
adapterSelect.push(entry);
|
|
161
182
|
if (collectReducers) {
|
|
@@ -280,7 +301,170 @@ export function planReadOperation(core, model, active, compute, request, args) {
|
|
|
280
301
|
materialize: defaults.plan.computed.length > 0,
|
|
281
302
|
};
|
|
282
303
|
}
|
|
283
|
-
|
|
304
|
+
function resolveReadLevel(active, compute, plan, tail) {
|
|
305
|
+
const resource = lookupResource(active, plan.resource);
|
|
306
|
+
if (resource === undefined) {
|
|
307
|
+
return undefined;
|
|
308
|
+
}
|
|
309
|
+
const stages = [];
|
|
310
|
+
for (const fieldName of plan.computed) {
|
|
311
|
+
const field = lookupField(resource, fieldName);
|
|
312
|
+
const stage = readCompute(compute?.[plan.resource]?.[fieldName]?.read);
|
|
313
|
+
if (field?.kind !== "scalar" || stage === undefined) {
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
stages.push({
|
|
317
|
+
field: fieldName,
|
|
318
|
+
definition: field,
|
|
319
|
+
compute: stage.compute,
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
const relations = [];
|
|
323
|
+
let restFree = true;
|
|
324
|
+
for (const relation of [...plan.relations].reverse()) {
|
|
325
|
+
const level = resolveReadLevel(active, compute, relation.projection, tail && restFree);
|
|
326
|
+
relations.unshift({ relation, level });
|
|
327
|
+
restFree &&= level?.computeFree ?? true;
|
|
328
|
+
}
|
|
329
|
+
return {
|
|
330
|
+
plan,
|
|
331
|
+
stages,
|
|
332
|
+
relations,
|
|
333
|
+
computeFree: stages.length === 0 && restFree,
|
|
334
|
+
atOnce: tail && stages.length <= 1 && restFree,
|
|
335
|
+
plainKeys: plan.requested.every((field) => !(field in Object.prototype)),
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
function isNestedContainer(value) {
|
|
339
|
+
return (value !== null &&
|
|
340
|
+
typeof value === "object" &&
|
|
341
|
+
!(value instanceof Date) &&
|
|
342
|
+
!(value instanceof Uint8Array));
|
|
343
|
+
}
|
|
344
|
+
function setOwn(target, key, value) {
|
|
345
|
+
if (key in target) {
|
|
346
|
+
Object.defineProperty(target, key, {
|
|
347
|
+
value,
|
|
348
|
+
writable: true,
|
|
349
|
+
enumerable: true,
|
|
350
|
+
configurable: true,
|
|
351
|
+
});
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
target[key] = value;
|
|
355
|
+
}
|
|
356
|
+
function answerOf(level, record) {
|
|
357
|
+
const answer = {};
|
|
358
|
+
for (const fieldName of level.plan.requested) {
|
|
359
|
+
if (!Object.hasOwn(record, fieldName)) {
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
if (level.plainKeys) {
|
|
363
|
+
answer[fieldName] = record[fieldName];
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
setOwn(answer, fieldName, record[fieldName]);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return answer;
|
|
370
|
+
}
|
|
371
|
+
function heldReadValue(active, level, stage, value) {
|
|
372
|
+
const validation = normalizeScalarFieldValue(active, stage.definition, value, "runtime", [
|
|
373
|
+
"resources",
|
|
374
|
+
level.plan.resource,
|
|
375
|
+
"fields",
|
|
376
|
+
stage.field,
|
|
377
|
+
"pipelines",
|
|
378
|
+
"compute",
|
|
379
|
+
"read",
|
|
380
|
+
]);
|
|
381
|
+
if (!validation.ok) {
|
|
382
|
+
throw new AvComputedValueError(level.plan.resource, stage.field, "read", validation.issues);
|
|
383
|
+
}
|
|
384
|
+
return validation.value;
|
|
385
|
+
}
|
|
386
|
+
function projectedAtOnce(level, value) {
|
|
387
|
+
if (!isRecord(value) || level === undefined) {
|
|
388
|
+
return value;
|
|
389
|
+
}
|
|
390
|
+
const record = { ...value };
|
|
391
|
+
relationsAtOnce(level, record);
|
|
392
|
+
return answerOf(level, record);
|
|
393
|
+
}
|
|
394
|
+
function relationsAtOnce(level, record) {
|
|
395
|
+
for (const { relation, level: nested } of level.relations) {
|
|
396
|
+
if (!Object.hasOwn(record, relation.field)) {
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
const value = record[relation.field];
|
|
400
|
+
if (value === null || value === undefined) {
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
if (relation.cardinality === "many") {
|
|
404
|
+
if (Array.isArray(value)) {
|
|
405
|
+
record[relation.field] = Array.from(value, (entry) => projectedAtOnce(nested, entry));
|
|
406
|
+
}
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
record[relation.field] = projectedAtOnce(nested, value);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
function computedAtOnce(active, level, stage, value, contextFactory) {
|
|
413
|
+
const record = { ...value };
|
|
414
|
+
const view = frozenCopy(record);
|
|
415
|
+
let computedValue;
|
|
416
|
+
try {
|
|
417
|
+
computedValue = stage.compute({
|
|
418
|
+
field: stage.field,
|
|
419
|
+
value: view[stage.field],
|
|
420
|
+
record: view,
|
|
421
|
+
ctx: contextFactory(),
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
catch (error) {
|
|
425
|
+
return Promise.reject(error);
|
|
426
|
+
}
|
|
427
|
+
const finish = (returned) => {
|
|
428
|
+
if (returned !== undefined) {
|
|
429
|
+
record[stage.field] = heldReadValue(active, level, stage, returned);
|
|
430
|
+
}
|
|
431
|
+
relationsAtOnce(level, record);
|
|
432
|
+
return answerOf(level, record);
|
|
433
|
+
};
|
|
434
|
+
const later = (error) => Promise.resolve().then(() => {
|
|
435
|
+
throw error;
|
|
436
|
+
});
|
|
437
|
+
let waits;
|
|
438
|
+
try {
|
|
439
|
+
waits = isThenable(computedValue);
|
|
440
|
+
}
|
|
441
|
+
catch (error) {
|
|
442
|
+
return later(error);
|
|
443
|
+
}
|
|
444
|
+
if (waits) {
|
|
445
|
+
const pending = computedValue;
|
|
446
|
+
return (async () => finish(await pending))();
|
|
447
|
+
}
|
|
448
|
+
try {
|
|
449
|
+
return finish(computedValue);
|
|
450
|
+
}
|
|
451
|
+
catch (error) {
|
|
452
|
+
return later(error);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
function materializeRecord(active, level, value, contextFactory) {
|
|
456
|
+
if (level?.atOnce !== true) {
|
|
457
|
+
return materializeInTurn(active, level, value, contextFactory);
|
|
458
|
+
}
|
|
459
|
+
if (!isRecord(value)) {
|
|
460
|
+
return value;
|
|
461
|
+
}
|
|
462
|
+
const [stage] = level.stages;
|
|
463
|
+
return stage === undefined
|
|
464
|
+
? projectedAtOnce(level, value)
|
|
465
|
+
: computedAtOnce(active, level, stage, value, contextFactory);
|
|
466
|
+
}
|
|
467
|
+
async function materializeRelation(active, level, relation, value, contextFactory) {
|
|
284
468
|
if (value === null || value === undefined) {
|
|
285
469
|
return value;
|
|
286
470
|
}
|
|
@@ -288,65 +472,62 @@ async function materializeRelation(active, compute, request, relation, value, co
|
|
|
288
472
|
if (!Array.isArray(value)) {
|
|
289
473
|
return value;
|
|
290
474
|
}
|
|
291
|
-
return Promise.all(value.map((entry) => materializeRecord(active,
|
|
475
|
+
return Promise.all(value.map((entry) => materializeRecord(active, level, entry, contextFactory)));
|
|
292
476
|
}
|
|
293
|
-
return materializeRecord(active,
|
|
477
|
+
return materializeRecord(active, level, value, contextFactory);
|
|
294
478
|
}
|
|
295
|
-
async function
|
|
296
|
-
if (!isRecord(value)) {
|
|
297
|
-
return value;
|
|
298
|
-
}
|
|
299
|
-
const resource = lookupResource(active, plan.resource);
|
|
300
|
-
if (resource === undefined) {
|
|
479
|
+
async function materializeInTurn(active, level, value, contextFactory) {
|
|
480
|
+
if (!isRecord(value) || level === undefined) {
|
|
301
481
|
return value;
|
|
302
482
|
}
|
|
483
|
+
const { stages } = level;
|
|
303
484
|
const record = { ...value };
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
485
|
+
let told;
|
|
486
|
+
if (stages.length > 1) {
|
|
487
|
+
told = { ...record };
|
|
488
|
+
for (const key of Object.keys(told)) {
|
|
489
|
+
const nested = told[key];
|
|
490
|
+
if (isNestedContainer(nested)) {
|
|
491
|
+
told[key] = frozenCopy(nested, true);
|
|
492
|
+
}
|
|
309
493
|
}
|
|
494
|
+
}
|
|
495
|
+
for (const stage of stages) {
|
|
496
|
+
const view = frozenCopy(told ?? record);
|
|
310
497
|
const computedValue = await stage.compute({
|
|
311
|
-
field:
|
|
312
|
-
value:
|
|
313
|
-
record,
|
|
498
|
+
field: stage.field,
|
|
499
|
+
value: view[stage.field],
|
|
500
|
+
record: view,
|
|
314
501
|
ctx: contextFactory(),
|
|
315
502
|
});
|
|
316
503
|
if (computedValue === undefined) {
|
|
317
504
|
continue;
|
|
318
505
|
}
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
fieldName,
|
|
324
|
-
"pipelines",
|
|
325
|
-
"compute",
|
|
326
|
-
"read",
|
|
327
|
-
]);
|
|
328
|
-
if (!validation.ok) {
|
|
329
|
-
throw new AvComputedValueError(plan.resource, fieldName, "read", validation.issues);
|
|
506
|
+
const held = heldReadValue(active, level, stage, computedValue);
|
|
507
|
+
record[stage.field] = held;
|
|
508
|
+
if (told !== undefined) {
|
|
509
|
+
told[stage.field] = held;
|
|
330
510
|
}
|
|
331
|
-
record[fieldName] = validation.value;
|
|
332
511
|
}
|
|
333
|
-
for (const relation of
|
|
512
|
+
for (const { relation, level: nested } of level.relations) {
|
|
334
513
|
if (!Object.hasOwn(record, relation.field)) {
|
|
335
514
|
continue;
|
|
336
515
|
}
|
|
337
|
-
record[relation.field] = await materializeRelation(active,
|
|
516
|
+
record[relation.field] = await materializeRelation(active, nested, relation, record[relation.field], contextFactory);
|
|
338
517
|
}
|
|
339
|
-
return
|
|
340
|
-
.filter((fieldName) => Object.hasOwn(record, fieldName))
|
|
341
|
-
.map((fieldName) => [fieldName, record[fieldName]]));
|
|
518
|
+
return answerOf(level, record);
|
|
342
519
|
}
|
|
343
|
-
export async function materializeReadOperation(active, compute,
|
|
520
|
+
export async function materializeReadOperation(active, compute, _request, plan, value, contextFactory) {
|
|
344
521
|
const projection = plan.projection;
|
|
345
522
|
if (!plan.materialize || projection === undefined) {
|
|
346
523
|
return value;
|
|
347
524
|
}
|
|
525
|
+
const level = resolveReadLevel(active, compute, projection, true);
|
|
348
526
|
if (Array.isArray(value)) {
|
|
349
|
-
|
|
527
|
+
const rows = value.map((entry) => materializeRecord(active, level, entry, contextFactory));
|
|
528
|
+
return rows.some((row) => row instanceof Promise)
|
|
529
|
+
? Promise.all(rows)
|
|
530
|
+
: Array.from(rows);
|
|
350
531
|
}
|
|
351
|
-
return materializeRecord(active,
|
|
532
|
+
return materializeRecord(active, level, value, contextFactory);
|
|
352
533
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { AvValidationIssue } from "../operations/validation-code.js";
|
|
2
2
|
/**
|
|
3
3
|
* What the diagnostics channel receives when a computed value — a read or write
|
|
4
|
-
* compute stage's return — is one its Contract refuses
|
|
4
|
+
* compute stage's return — is one its Contract refuses, or a `compute.create`
|
|
5
|
+
* stage returned `undefined` for a field a create cannot do without (rc.2): the developer's broken code,
|
|
5
6
|
* never the caller's. It is thrown, not a deliberate outcome, so the framework's
|
|
6
7
|
* boundary answers the caller the generic `A3000` and reports this error, with the
|
|
7
8
|
* issues, exactly once.
|
|
@@ -9,5 +10,5 @@ import type { AvValidationIssue } from "../operations/validation-code.js";
|
|
|
9
10
|
export declare class AvComputedValueError extends Error {
|
|
10
11
|
readonly issues: readonly AvValidationIssue[];
|
|
11
12
|
readonly name = "AvComputedValueError";
|
|
12
|
-
constructor(resource: string, field: string, stage: "read" | "create" | "update", issues: readonly AvValidationIssue[]);
|
|
13
|
+
constructor(resource: string, field: string, stage: "read" | "create" | "update", issues: readonly AvValidationIssue[], message?: string);
|
|
13
14
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
export class AvComputedValueError extends Error {
|
|
2
2
|
issues;
|
|
3
3
|
name = "AvComputedValueError";
|
|
4
|
-
constructor(resource, field, stage, issues) {
|
|
4
|
+
constructor(resource, field, stage, issues, message) {
|
|
5
5
|
const [first] = issues;
|
|
6
|
-
super(
|
|
6
|
+
super(message ??
|
|
7
|
+
`The compute.${stage} stage of ${resource}.${field} returned a value its Contract refuses${first === undefined ? "." : ` (${first.code}: ${first.message})`}`);
|
|
7
8
|
this.issues = issues;
|
|
8
9
|
}
|
|
9
10
|
}
|
|
@@ -7,7 +7,7 @@ import type { AvOperationFamily } from "../operations/operation-identity.js";
|
|
|
7
7
|
import { type AvDiagnosticsSink } from "./diagnostics-reporter.js";
|
|
8
8
|
import type { AvComputeContext } from "./field-compute.js";
|
|
9
9
|
import type { MisuseReporter } from "./misuse-reporter.js";
|
|
10
|
-
import type {
|
|
10
|
+
import type { AvApplicationOperationRequest } from "./operation-request.js";
|
|
11
11
|
import type { AvOperationResponse } from "./operation-response.js";
|
|
12
12
|
import type { AvContext, AvTransactionContext, AvTransportContext } from "./pipeline.js";
|
|
13
13
|
import type { AvState } from "./request-state.js";
|
|
@@ -35,8 +35,8 @@ export type ContextFacts = {
|
|
|
35
35
|
readonly $args: unknown;
|
|
36
36
|
};
|
|
37
37
|
/** Runs one raw application-origin call in `transaction`, or standalone. Total. */
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
type RawOperationRunner<M extends AvAdapterModel> = (request: AvApplicationOperationRequest, transaction: AvAdapterTransactionExecutor<M> | undefined) => Promise<AvOperationResponse>;
|
|
39
|
+
type ContextExecutorDependencies<M extends AvAdapterModel> = {
|
|
40
40
|
/** The model, as construction read it once: the ctx's Resources. */
|
|
41
41
|
readonly model: M;
|
|
42
42
|
readonly adapter: AvAdapter<M>;
|
|
@@ -57,3 +57,4 @@ export type ContextExecutor<M extends AvAdapterModel = AvAdapterModel> = {
|
|
|
57
57
|
};
|
|
58
58
|
/** Builds the ctx factory of one Framework over its model. */
|
|
59
59
|
export declare function createContextExecutor<M extends AvAdapterModel>(dependencies: ContextExecutorDependencies<M>): ContextExecutor<M>;
|
|
60
|
+
export {};
|
|
@@ -195,9 +195,10 @@ export function createContextExecutor(dependencies) {
|
|
|
195
195
|
const contextOf = (prototype, scope, facts, readOnly = false) => {
|
|
196
196
|
const context = Object.create(prototype);
|
|
197
197
|
Object.defineProperty(context, STATE, {
|
|
198
|
-
value: { scope, facts, resources:
|
|
198
|
+
value: { scope, facts, resources: undefined },
|
|
199
199
|
});
|
|
200
|
-
for (const
|
|
200
|
+
for (const key of Object.keys(facts)) {
|
|
201
|
+
const value = facts[key];
|
|
201
202
|
if (value !== undefined) {
|
|
202
203
|
Object.defineProperty(context, key, { value, enumerable: true });
|
|
203
204
|
}
|
|
@@ -232,6 +233,7 @@ export function createContextExecutor(dependencies) {
|
|
|
232
233
|
Object.defineProperty(prototype, resource, {
|
|
233
234
|
get() {
|
|
234
235
|
const state = stateOf(this);
|
|
236
|
+
state.resources ??= new Map();
|
|
235
237
|
let tree = state.resources.get(resource);
|
|
236
238
|
if (tree === undefined) {
|
|
237
239
|
tree = resourceTree(state.scope, resource, readOnly);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** The registered symbol every copy of this major brands class `name` with. */
|
|
2
|
+
export declare function coreBrandOf(name: string): symbol;
|
|
3
|
+
/** Whether `value` carries `brand`, wherever it was made: one `in`. */
|
|
4
|
+
export declare function hasCoreBrand(value: unknown, brand: symbol): boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Brands `type`'s prototype as `name` and makes `instanceof type` read the brand.
|
|
7
|
+
* A developer's own subclass of `type` inherits the static `Symbol.hasInstance`, so
|
|
8
|
+
* on any constructor but `type` itself it answers as `instanceof` always does.
|
|
9
|
+
*/
|
|
10
|
+
export declare function brandCoreClass(type: abstract new (...args: never[]) => object, name: string): symbol;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { CORE_VERSION } from "../prebuilt/core-version.generated.js";
|
|
2
|
+
const CORE_MAJOR = CORE_VERSION.slice(0, CORE_VERSION.indexOf("."));
|
|
3
|
+
export function coreBrandOf(name) {
|
|
4
|
+
return Symbol.for(`aventara.core.${name}@${CORE_MAJOR}`);
|
|
5
|
+
}
|
|
6
|
+
export function hasCoreBrand(value, brand) {
|
|
7
|
+
return typeof value === "object" && value !== null && brand in value;
|
|
8
|
+
}
|
|
9
|
+
const ordinaryHasInstance = Function.prototype[Symbol.hasInstance];
|
|
10
|
+
export function brandCoreClass(type, name) {
|
|
11
|
+
const brand = coreBrandOf(name);
|
|
12
|
+
Object.defineProperty(type.prototype, brand, { value: true });
|
|
13
|
+
Object.defineProperty(type, Symbol.hasInstance, {
|
|
14
|
+
value: function hasInstance(value) {
|
|
15
|
+
return this === type
|
|
16
|
+
? hasCoreBrand(value, brand)
|
|
17
|
+
: ordinaryHasInstance.call(this, value);
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
return brand;
|
|
21
|
+
}
|
|
@@ -1,20 +1,32 @@
|
|
|
1
1
|
import type { AvContract } from "../contracts/contract.js";
|
|
2
|
+
import type { AvCreateRequirements } from "../contracts/create-requirements.js";
|
|
2
3
|
import type { AvOperationIdentity } from "../operations/operation-identity.js";
|
|
3
4
|
import type { AvValidationIssue } from "../operations/validation-code.js";
|
|
4
5
|
import type { ReferentialActionTable } from "./referential-action.js";
|
|
5
6
|
type Path = readonly (string | number)[];
|
|
7
|
+
/** One required field a `compute.create` stage was to fill and left missing. */
|
|
8
|
+
type ComputedRequirementGap = {
|
|
9
|
+
readonly resource: string;
|
|
10
|
+
readonly field: string;
|
|
11
|
+
readonly issue: AvValidationIssue;
|
|
12
|
+
};
|
|
6
13
|
/**
|
|
7
|
-
* What the Adapter stated
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
14
|
+
* What the Adapter stated that the checks read: its referential edges, for the
|
|
15
|
+
* fields that hold each reference, and its own create requirements per
|
|
16
|
+
* Resource, before any layer projected them (what write compute must not leave
|
|
17
|
+
* missing). Read once when the Framework is constructed. The requirements the
|
|
18
|
+
* caller is held to are the active Contract's.
|
|
11
19
|
*/
|
|
12
20
|
export type RecordWriteFacts = {
|
|
13
21
|
readonly references: ReferentialActionTable;
|
|
22
|
+
readonly stated: (resource: string) => AvCreateRequirements | undefined;
|
|
14
23
|
};
|
|
15
24
|
/** The facts an Adapter stated, read off it once; an absent table states nothing. */
|
|
16
25
|
export declare function recordWriteFactsOf(adapter: {
|
|
17
26
|
readonly referentialActions?: ReferentialActionTable;
|
|
27
|
+
readonly model?: {
|
|
28
|
+
readonly resources: Readonly<Record<string, unknown>>;
|
|
29
|
+
};
|
|
18
30
|
}): RecordWriteFacts;
|
|
19
31
|
/**
|
|
20
32
|
* The `V1000` issues for every create position in one operation's arguments
|
|
@@ -24,7 +36,21 @@ export declare function recordWriteFactsOf(adapter: {
|
|
|
24
36
|
* reference both, in argument order. Empty when there are none. Total over
|
|
25
37
|
* malformed input.
|
|
26
38
|
*/
|
|
27
|
-
export declare function createRequirementIssues(contract: AvContract, facts: RecordWriteFacts, request: AvOperationIdentity & {
|
|
39
|
+
export declare function createRequirementIssues(contract: AvContract, facts: Pick<RecordWriteFacts, "references">, request: AvOperationIdentity & {
|
|
28
40
|
readonly resource: string;
|
|
29
41
|
}, args: unknown, argumentsPath: Path): readonly AvValidationIssue[];
|
|
42
|
+
/**
|
|
43
|
+
* Every required field a `compute.create` stage was to fill and that is still
|
|
44
|
+
* missing after write compute, at every create position of one operation's
|
|
45
|
+
* arguments (`create.*`'s `data`, `upsert`'s `create`, every nested create),
|
|
46
|
+
* in argument order, read against the Adapter's own statement of each
|
|
47
|
+
* Resource's create requirements; `computed` names the fields a Resource's
|
|
48
|
+
* `compute.create` stages fill.
|
|
49
|
+
* A field the parent supplies to a nested create, a group whose relation the
|
|
50
|
+
* record writes, and a value the caller sent are not missing. Empty when
|
|
51
|
+
* nothing is.
|
|
52
|
+
*/
|
|
53
|
+
export declare function computedRequirementGapsOf(contract: AvContract, facts: RecordWriteFacts, request: AvOperationIdentity & {
|
|
54
|
+
readonly resource: string;
|
|
55
|
+
}, args: unknown, argumentsPath: Path, computed: (resource: string) => ReadonlySet<string>): readonly ComputedRequirementGap[];
|
|
30
56
|
export {};
|