@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,10 +1,8 @@
|
|
|
1
1
|
import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
|
|
2
2
|
import { advertisedDirectivesAt } from "../contracts/field.js";
|
|
3
|
-
import { NESTED_WRITE_SCOPE, resolveWriteScope, } from "../operations/write-scope.resolver.js";
|
|
3
|
+
import { LOOPBACK_WRITE_SCOPE, NESTED_WRITE_SCOPE, resolveWriteScope, } from "../operations/write-scope.resolver.js";
|
|
4
4
|
import { isRelationMutationDirective, RELATION_MUTATION_RECORD_SITES, } from "./mutation-planner.js";
|
|
5
|
-
|
|
6
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
7
|
-
}
|
|
5
|
+
import { isRecord } from "./record.guard.js";
|
|
8
6
|
function written(record, key) {
|
|
9
7
|
return Object.hasOwn(record, key) && record[key] !== undefined;
|
|
10
8
|
}
|
|
@@ -13,7 +11,7 @@ function edgesOf(table, resource) {
|
|
|
13
11
|
return Array.isArray(listed) ? listed : [];
|
|
14
12
|
}
|
|
15
13
|
function referencesOf(edge) {
|
|
16
|
-
return Array.isArray(edge.
|
|
14
|
+
return Array.isArray(edge.referenceFields) ? edge.referenceFields : [];
|
|
17
15
|
}
|
|
18
16
|
function creatableScalar(contract, resource, field) {
|
|
19
17
|
const found = lookupField(lookupResource(contract, resource), field);
|
|
@@ -63,9 +61,19 @@ function checkCreateRecord(context, resource, record, path, scope, via) {
|
|
|
63
61
|
if (!isRecord(record)) {
|
|
64
62
|
return;
|
|
65
63
|
}
|
|
64
|
+
if (context.computed !== undefined) {
|
|
65
|
+
computedRequirementGaps(context, resource, record, path, via);
|
|
66
|
+
walkNestedCreates(context, resource, record, path);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
66
69
|
const { contract, issues } = context;
|
|
67
|
-
const
|
|
68
|
-
|
|
70
|
+
const looped = loopbackWrites(context, resource, record, path, via, "create");
|
|
71
|
+
const conflicted = looped.size > 0
|
|
72
|
+
? looped
|
|
73
|
+
: referenceConflicts(context, resource, record, path);
|
|
74
|
+
if (looped.size === 0) {
|
|
75
|
+
mixedReferenceWrites(context, resource, record, path, conflicted);
|
|
76
|
+
}
|
|
69
77
|
const requirements = requirementsOf(contract, resource);
|
|
70
78
|
if (requirements !== undefined) {
|
|
71
79
|
const supplied = suppliedThrough(requirements, via);
|
|
@@ -157,14 +165,93 @@ function mixedReferenceWrites(context, resource, record, path, conflicted) {
|
|
|
157
165
|
});
|
|
158
166
|
}
|
|
159
167
|
}
|
|
160
|
-
function checkUpdateRecord(context, resource, record, path) {
|
|
168
|
+
function checkUpdateRecord(context, resource, record, path, via) {
|
|
161
169
|
if (!isRecord(record)) {
|
|
162
170
|
return;
|
|
163
171
|
}
|
|
164
|
-
|
|
165
|
-
|
|
172
|
+
if (context.computed === undefined &&
|
|
173
|
+
loopbackWrites(context, resource, record, path, via, "update").size === 0) {
|
|
174
|
+
const conflicted = referenceConflicts(context, resource, record, path);
|
|
175
|
+
mixedReferenceWrites(context, resource, record, path, conflicted);
|
|
176
|
+
}
|
|
166
177
|
walkNestedCreates(context, resource, record, path);
|
|
167
178
|
}
|
|
179
|
+
function loopbackWrites(context, resource, record, path, via, stage) {
|
|
180
|
+
const refused = new Set();
|
|
181
|
+
if (via === undefined) {
|
|
182
|
+
return refused;
|
|
183
|
+
}
|
|
184
|
+
const { contract } = context;
|
|
185
|
+
const edge = lookupField(lookupResource(contract, via.resource), via.relation);
|
|
186
|
+
if (edge?.kind !== "relation" || typeof edge.inverse !== "string") {
|
|
187
|
+
return refused;
|
|
188
|
+
}
|
|
189
|
+
const inverse = edge.inverse;
|
|
190
|
+
const other = lookupField(lookupResource(contract, resource), inverse);
|
|
191
|
+
if (other?.kind === "relation" &&
|
|
192
|
+
advertisedDirectivesAt(other.capabilities[stage], LOOPBACK_WRITE_SCOPE) !==
|
|
193
|
+
undefined) {
|
|
194
|
+
return refused;
|
|
195
|
+
}
|
|
196
|
+
const references = edgesOf(context.references, resource).find((candidate) => candidate.field === inverse) ?? undefined;
|
|
197
|
+
for (const field of [
|
|
198
|
+
inverse,
|
|
199
|
+
...(references === undefined ? [] : referencesOf(references)),
|
|
200
|
+
]) {
|
|
201
|
+
if (!written(record, field)) {
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
refused.add(field);
|
|
205
|
+
context.issues.push({
|
|
206
|
+
code: "V1012",
|
|
207
|
+
path: [...path, field],
|
|
208
|
+
message: field === inverse
|
|
209
|
+
? `Relation "${field}" is the relation this ${resource} is written through, from its other end ("${via.resource}.${via.relation}"): the write it sits in supplies it.`
|
|
210
|
+
: `Field "${field}" holds the reference of "${inverse}", the relation this ${resource} is written through ("${via.resource}.${via.relation}"): the write it sits in supplies it.`,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
return refused;
|
|
214
|
+
}
|
|
215
|
+
function computedRequirementGaps(context, resource, record, path, via) {
|
|
216
|
+
const reader = context.computed;
|
|
217
|
+
const computed = reader?.computed(resource);
|
|
218
|
+
const stated = reader?.stated(resource);
|
|
219
|
+
if (computed === undefined || computed.size === 0 || stated === undefined) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
const supplied = suppliedThrough(stated, via);
|
|
223
|
+
const gap = (field) => {
|
|
224
|
+
context.gaps?.push({
|
|
225
|
+
resource,
|
|
226
|
+
field,
|
|
227
|
+
issue: {
|
|
228
|
+
code: "V1000",
|
|
229
|
+
path: [...path, field],
|
|
230
|
+
message: `compute.create on ${resource}.${field} returned undefined for a required field.`,
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
};
|
|
234
|
+
for (const field of namesOf(stated.required)) {
|
|
235
|
+
if (computed.has(field) &&
|
|
236
|
+
!supplied.has(field) &&
|
|
237
|
+
!written(record, field)) {
|
|
238
|
+
gap(field);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const groups = Array.isArray(stated.oneOf) ? stated.oneOf : [];
|
|
242
|
+
for (const group of groups) {
|
|
243
|
+
const [relation, ...references] = namesOf(group);
|
|
244
|
+
const left = references.find((field) => computed.has(field) && !written(record, field));
|
|
245
|
+
if (relation === undefined ||
|
|
246
|
+
left === undefined ||
|
|
247
|
+
supplied.has(relation) ||
|
|
248
|
+
references.some((field) => supplied.has(field)) ||
|
|
249
|
+
written(record, relation)) {
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
gap(left);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
168
255
|
function walkNestedCreates(context, resource, record, path) {
|
|
169
256
|
if (!isRecord(record)) {
|
|
170
257
|
return;
|
|
@@ -196,7 +283,7 @@ function walkNestedCreates(context, resource, record, path) {
|
|
|
196
283
|
checkCreateRecord(context, field.target, siteRecord, sitePath, NESTED_WRITE_SCOPE, via);
|
|
197
284
|
}
|
|
198
285
|
else {
|
|
199
|
-
checkUpdateRecord(context, field.target, siteRecord, sitePath);
|
|
286
|
+
checkUpdateRecord(context, field.target, siteRecord, sitePath, via);
|
|
200
287
|
}
|
|
201
288
|
}
|
|
202
289
|
}
|
|
@@ -204,17 +291,43 @@ function walkNestedCreates(context, resource, record, path) {
|
|
|
204
291
|
}
|
|
205
292
|
}
|
|
206
293
|
export function recordWriteFactsOf(adapter) {
|
|
207
|
-
|
|
294
|
+
const resources = adapter.model?.resources ?? {};
|
|
295
|
+
return {
|
|
296
|
+
references: adapter.referentialActions ?? {},
|
|
297
|
+
stated: (resource) => {
|
|
298
|
+
const found = Object.hasOwn(resources, resource)
|
|
299
|
+
? resources[resource]
|
|
300
|
+
: undefined;
|
|
301
|
+
const stated = isRecord(found) ? found.createRequirements : undefined;
|
|
302
|
+
return isRecord(stated) ? stated : undefined;
|
|
303
|
+
},
|
|
304
|
+
};
|
|
208
305
|
}
|
|
209
306
|
export function createRequirementIssues(contract, facts, request, args, argumentsPath) {
|
|
210
|
-
if (!isRecord(args)) {
|
|
211
|
-
return [];
|
|
212
|
-
}
|
|
213
307
|
const context = {
|
|
214
308
|
contract,
|
|
215
309
|
references: facts.references,
|
|
216
310
|
issues: [],
|
|
217
311
|
};
|
|
312
|
+
walkOperation(context, request, args, argumentsPath);
|
|
313
|
+
return context.issues;
|
|
314
|
+
}
|
|
315
|
+
export function computedRequirementGapsOf(contract, facts, request, args, argumentsPath, computed) {
|
|
316
|
+
const gaps = [];
|
|
317
|
+
walkOperation({
|
|
318
|
+
contract,
|
|
319
|
+
references: facts.references,
|
|
320
|
+
issues: [],
|
|
321
|
+
computed: { stated: facts.stated, computed },
|
|
322
|
+
gaps,
|
|
323
|
+
}, request, args, argumentsPath);
|
|
324
|
+
return gaps;
|
|
325
|
+
}
|
|
326
|
+
function walkOperation(context, request, args, argumentsPath) {
|
|
327
|
+
if (!isRecord(args)) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const contract = context.contract;
|
|
218
331
|
const scope = resolveWriteScope(lookupResource(contract, request.resource), request);
|
|
219
332
|
if (request.family === "create" && written(args, "data")) {
|
|
220
333
|
const data = args.data;
|
|
@@ -229,16 +342,9 @@ export function createRequirementIssues(contract, facts, request, args, argument
|
|
|
229
342
|
}
|
|
230
343
|
if (request.family === "upsert") {
|
|
231
344
|
checkCreateRecord(context, request.resource, args.create, [...argumentsPath, "create"], scope, undefined);
|
|
232
|
-
checkUpdateRecord(context, request.resource, args.update, [
|
|
233
|
-
...argumentsPath,
|
|
234
|
-
"update",
|
|
235
|
-
]);
|
|
345
|
+
checkUpdateRecord(context, request.resource, args.update, [...argumentsPath, "update"], undefined);
|
|
236
346
|
}
|
|
237
347
|
if (request.family === "update") {
|
|
238
|
-
checkUpdateRecord(context, request.resource, args.data, [
|
|
239
|
-
...argumentsPath,
|
|
240
|
-
"data",
|
|
241
|
-
]);
|
|
348
|
+
checkUpdateRecord(context, request.resource, args.data, [...argumentsPath, "data"], undefined);
|
|
242
349
|
}
|
|
243
|
-
return context.issues;
|
|
244
350
|
}
|
|
@@ -12,3 +12,17 @@ export declare class AvDecimal {
|
|
|
12
12
|
*/
|
|
13
13
|
toJSON(): string;
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Whether `value` is an `AvDecimal`, made by this copy of core or by another of
|
|
17
|
+
* its major: one `in`, for the hot paths that ask about every value.
|
|
18
|
+
*/
|
|
19
|
+
export declare function isAvDecimal(value: unknown): value is AvDecimal;
|
|
20
|
+
/**
|
|
21
|
+
* The digits of `value`, read without running anything the caller could have put
|
|
22
|
+
* on it when this copy made it. Another copy's decimal is read through its own
|
|
23
|
+
* `toString`, which only that copy can answer; what it returns is checked as a
|
|
24
|
+
* decimal string, so the caller's copy keeps the grammar.
|
|
25
|
+
*
|
|
26
|
+
* @throws TypeError when another copy's decimal does not answer a decimal string.
|
|
27
|
+
*/
|
|
28
|
+
export declare function decimalDigitsOf(value: AvDecimal): string;
|
package/dist/runtime/decimal.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { WIRE_SCALAR_PATTERNS } from "../contracts/wire-scalar-format.js";
|
|
2
|
+
import { brandCoreClass, hasCoreBrand } from "./core-class.brand.js";
|
|
3
|
+
let ownDigitsOf;
|
|
2
4
|
export class AvDecimal {
|
|
3
5
|
#value;
|
|
6
|
+
static {
|
|
7
|
+
ownDigitsOf = (value) => (#value in value ? value.#value : undefined);
|
|
8
|
+
}
|
|
4
9
|
constructor(value) {
|
|
5
10
|
if (typeof value !== "string") {
|
|
6
11
|
throw new TypeError("Decimal value must be a string.");
|
|
@@ -17,3 +22,19 @@ export class AvDecimal {
|
|
|
17
22
|
return this.#value;
|
|
18
23
|
}
|
|
19
24
|
}
|
|
25
|
+
const DECIMAL_BRAND = brandCoreClass(AvDecimal, "AvDecimal");
|
|
26
|
+
export function isAvDecimal(value) {
|
|
27
|
+
return hasCoreBrand(value, DECIMAL_BRAND);
|
|
28
|
+
}
|
|
29
|
+
export function decimalDigitsOf(value) {
|
|
30
|
+
const own = ownDigitsOf(value);
|
|
31
|
+
if (own !== undefined) {
|
|
32
|
+
return own;
|
|
33
|
+
}
|
|
34
|
+
const digits = value.toString();
|
|
35
|
+
if (typeof digits !== "string" ||
|
|
36
|
+
!WIRE_SCALAR_PATTERNS.decimal.test(digits)) {
|
|
37
|
+
throw new TypeError("Decimal value must be a valid decimal string.");
|
|
38
|
+
}
|
|
39
|
+
return digits;
|
|
40
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AvRequestOrigin } from "../config/config-layer.js";
|
|
2
2
|
import type { AvOperationFamily } from "../operations/operation-identity.js";
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
3
|
+
import type { AvTransactionRequest } from "../transactions/transaction-request.js";
|
|
4
|
+
import type { AvOperationRequest } from "./operation-request.js";
|
|
5
5
|
import { type AvOperationErrorCode, type AvOperationFailureResponse } from "./operation-response.js";
|
|
6
6
|
/**
|
|
7
7
|
* One unplanned failure of an operation: the raw error, the code the caller
|
|
@@ -19,6 +19,11 @@ export type AvOperationDiagnostic = {
|
|
|
19
19
|
readonly variant: string;
|
|
20
20
|
readonly requestId: string;
|
|
21
21
|
readonly operation?: number;
|
|
22
|
+
/**
|
|
23
|
+
* The key of the Operation Set entry (`POST /_all`) the failure met; absent
|
|
24
|
+
* for an operation that ran alone or as a transaction step.
|
|
25
|
+
*/
|
|
26
|
+
readonly key?: string;
|
|
22
27
|
/**
|
|
23
28
|
* `true` when `error` is an `AvError` its thrower (a pipeline
|
|
24
29
|
* callback, a compute stage, a filter or an Adapter) raised deliberately with an
|
|
@@ -47,7 +52,8 @@ export type AvTransactionDiagnostic = {
|
|
|
47
52
|
};
|
|
48
53
|
/**
|
|
49
54
|
* One unplanned failure of the MCP endpoint itself, outside any tool call's
|
|
50
|
-
* operation: the raw error, answered `500` with no detail
|
|
55
|
+
* operation: the raw error, answered `500` with no detail, or `401` when it is
|
|
56
|
+
* the throw of `mcp.authorization.verify`.
|
|
51
57
|
*/
|
|
52
58
|
export type AvMcpDiagnostic = {
|
|
53
59
|
readonly kind: "mcp";
|
|
@@ -62,8 +68,40 @@ export type AvMcpDiagnostic = {
|
|
|
62
68
|
/** Never present: only an operation diagnostic is marked `deliberate`. */
|
|
63
69
|
readonly deliberate?: never;
|
|
64
70
|
};
|
|
65
|
-
/**
|
|
66
|
-
|
|
71
|
+
/**
|
|
72
|
+
* One unplanned failure of a `POST /_access/can` request: the raw error, the
|
|
73
|
+
* code the caller received, and, when one question met it, that question's
|
|
74
|
+
* index (`question`), Resource and action; none of the three when the batch
|
|
75
|
+
* as a whole failed.
|
|
76
|
+
*/
|
|
77
|
+
export type AvCanDiagnostic = {
|
|
78
|
+
readonly kind: "can";
|
|
79
|
+
readonly error: unknown;
|
|
80
|
+
readonly code: AvOperationErrorCode;
|
|
81
|
+
/** The route is the clients': an agent has no `can` route. */
|
|
82
|
+
readonly origin: "client";
|
|
83
|
+
readonly requestId: string;
|
|
84
|
+
/** Never present: no operation of a plan is involved (see `question`). */
|
|
85
|
+
readonly operation?: never;
|
|
86
|
+
/** Never present: only an operation diagnostic is marked `deliberate`. */
|
|
87
|
+
readonly deliberate?: never;
|
|
88
|
+
} & ({
|
|
89
|
+
/** The index of the question in `questions` the failure is blamed on. */
|
|
90
|
+
readonly question: number;
|
|
91
|
+
/** That question's Resource. */
|
|
92
|
+
readonly resource: string;
|
|
93
|
+
/** That question's action. */
|
|
94
|
+
readonly action: "read" | "create" | "update" | "delete";
|
|
95
|
+
} | {
|
|
96
|
+
readonly question?: never;
|
|
97
|
+
readonly resource?: never;
|
|
98
|
+
readonly action?: never;
|
|
99
|
+
});
|
|
100
|
+
/**
|
|
101
|
+
* One diagnostic: of an operation, of a transaction as a whole, of a `can`
|
|
102
|
+
* request, or of the MCP endpoint.
|
|
103
|
+
*/
|
|
104
|
+
export type AvDiagnostic = AvOperationDiagnostic | AvTransactionDiagnostic | AvCanDiagnostic | AvMcpDiagnostic;
|
|
67
105
|
/**
|
|
68
106
|
* Receives a diagnostic for every unplanned failure. Set once, as the root
|
|
69
107
|
* configuration's `diagnostics`.
|
|
@@ -80,8 +118,10 @@ export type DiagnosticMarks = Pick<AvOperationDiagnostic, "deliberate">;
|
|
|
80
118
|
/** The identifying half of a diagnostic, captured once per request. */
|
|
81
119
|
type OperationDiagnosticIdentity = Omit<AvOperationDiagnostic, "error" | "code">;
|
|
82
120
|
type TransactionDiagnosticIdentity = Omit<AvTransactionDiagnostic, "error" | "code">;
|
|
121
|
+
/** A `can` request's identity: its batch's, or one question's. */
|
|
122
|
+
type CanDiagnosticIdentity = AvCanDiagnostic extends infer Diagnostic ? Diagnostic extends unknown ? Omit<Diagnostic, "error" | "code"> : never : never;
|
|
83
123
|
/** The diagnostics channel bound to one diagnostic identity. */
|
|
84
|
-
export declare function createReporter(sink: AvDiagnosticsSink | undefined, identity: OperationDiagnosticIdentity | TransactionDiagnosticIdentity): DiagnosticsReporter;
|
|
124
|
+
export declare function createReporter(sink: AvDiagnosticsSink | undefined, identity: OperationDiagnosticIdentity | TransactionDiagnosticIdentity | CanDiagnosticIdentity): DiagnosticsReporter;
|
|
85
125
|
/**
|
|
86
126
|
* The MCP endpoint's failure channel for `framework`: each call reports one
|
|
87
127
|
* {@link AvMcpDiagnostic} to its configured sink, under a minted request id, and
|
|
@@ -99,14 +139,14 @@ export declare function diagnosticsSinkOf(framework: object): AvDiagnosticsSink
|
|
|
99
139
|
* Binds the configured sink to one operation request. The sink is not awaited,
|
|
100
140
|
* and nothing it throws or rejects with reaches the response.
|
|
101
141
|
*/
|
|
102
|
-
export declare function createDiagnosticsReporter(sink: AvDiagnosticsSink | undefined, request:
|
|
142
|
+
export declare function createDiagnosticsReporter(sink: AvDiagnosticsSink | undefined, request: AvOperationRequest, operation?: number, key?: string): DiagnosticsReporter;
|
|
103
143
|
/** The diagnostics channel of one transaction request. */
|
|
104
144
|
export type TransactionDiagnosticsChannel = {
|
|
105
145
|
/** A plan-level report; `operation` attributes it to a recorded failing index. */
|
|
106
146
|
readonly transaction: (operation?: number) => DiagnosticsReporter;
|
|
107
147
|
/** A report carrying one plan operation's own identity and index. */
|
|
108
|
-
readonly operation: (request:
|
|
148
|
+
readonly operation: (request: AvOperationRequest, operation: number) => DiagnosticsReporter;
|
|
109
149
|
};
|
|
110
150
|
/** Binds the configured sink to one transaction request and its plan operations. */
|
|
111
|
-
export declare function createTransactionDiagnosticsChannel(sink: AvDiagnosticsSink | undefined, request:
|
|
151
|
+
export declare function createTransactionDiagnosticsChannel(sink: AvDiagnosticsSink | undefined, request: AvTransactionRequest): TransactionDiagnosticsChannel;
|
|
112
152
|
export {};
|
|
@@ -1,13 +1,8 @@
|
|
|
1
|
+
import { coreBrandOf } from "./core-class.brand.js";
|
|
1
2
|
import { internalFailure, } from "./operation-response.js";
|
|
2
3
|
import { requestIdOf } from "./request-id.js";
|
|
4
|
+
import { isThenable } from "./thenable.guard.js";
|
|
3
5
|
const IGNORE_DIAGNOSTIC = () => undefined;
|
|
4
|
-
function isThenable(value) {
|
|
5
|
-
if ((typeof value !== "object" || value === null) &&
|
|
6
|
-
typeof value !== "function") {
|
|
7
|
-
return false;
|
|
8
|
-
}
|
|
9
|
-
return typeof value.then === "function";
|
|
10
|
-
}
|
|
11
6
|
export function createReporter(sink, identity) {
|
|
12
7
|
if (sink === undefined) {
|
|
13
8
|
return IGNORE_DIAGNOSTIC;
|
|
@@ -31,7 +26,18 @@ export function createReporter(sink, identity) {
|
|
|
31
26
|
}
|
|
32
27
|
};
|
|
33
28
|
}
|
|
34
|
-
const CONFIGURED_SINKS =
|
|
29
|
+
const CONFIGURED_SINKS = sharedSinkRegistry();
|
|
30
|
+
function sharedSinkRegistry() {
|
|
31
|
+
const key = coreBrandOf("diagnostics");
|
|
32
|
+
const holder = globalThis;
|
|
33
|
+
const existing = holder[key];
|
|
34
|
+
if (existing instanceof WeakMap) {
|
|
35
|
+
return existing;
|
|
36
|
+
}
|
|
37
|
+
const registry = new WeakMap();
|
|
38
|
+
Object.defineProperty(holder, key, { value: registry });
|
|
39
|
+
return registry;
|
|
40
|
+
}
|
|
35
41
|
export function mcpFailureReporterOf(framework) {
|
|
36
42
|
const sink = CONFIGURED_SINKS.get(framework);
|
|
37
43
|
return (error) => {
|
|
@@ -62,7 +68,7 @@ export function recordDiagnosticsSink(framework, sink) {
|
|
|
62
68
|
export function diagnosticsSinkOf(framework) {
|
|
63
69
|
return CONFIGURED_SINKS.get(framework);
|
|
64
70
|
}
|
|
65
|
-
export function createDiagnosticsReporter(sink, request, operation) {
|
|
71
|
+
export function createDiagnosticsReporter(sink, request, operation, key) {
|
|
66
72
|
let identity;
|
|
67
73
|
try {
|
|
68
74
|
identity = {
|
|
@@ -73,6 +79,7 @@ export function createDiagnosticsReporter(sink, request, operation) {
|
|
|
73
79
|
variant: request.variant,
|
|
74
80
|
requestId: request.requestId,
|
|
75
81
|
...(operation === undefined ? {} : { operation }),
|
|
82
|
+
...(key === undefined ? {} : { key }),
|
|
76
83
|
};
|
|
77
84
|
}
|
|
78
85
|
catch {
|
|
@@ -3,7 +3,7 @@ import { AvError } from "./framework-error.js";
|
|
|
3
3
|
import type { AvCause, AvOperationErrorCode, AvOperationFailureResponse } from "./operation-response.js";
|
|
4
4
|
import type { AvContext } from "./pipeline.js";
|
|
5
5
|
/** Where an unexpected post-validation exception originated. */
|
|
6
|
-
|
|
6
|
+
type FailureOrigin = "adapter" | "runtime";
|
|
7
7
|
/** The one generic Adapter-failure text; every unexpected A3001 carries it. */
|
|
8
8
|
export declare const ADAPTER_FAILURE_MESSAGE = "Adapter execution failed.";
|
|
9
9
|
/** One boundary instance belongs to one operation execution. */
|
|
@@ -50,6 +50,13 @@ type DeliberateOutcome = {
|
|
|
50
50
|
*/
|
|
51
51
|
readonly unvouched: readonly unknown[];
|
|
52
52
|
};
|
|
53
|
+
/**
|
|
54
|
+
* The refusal code `error` deliberately carries, vetted as every boundary vets
|
|
55
|
+
* it ({@link vetDeliberateOutcome}): a recognised error code that is no
|
|
56
|
+
* internal (`A3xxx`) one, with a well-formed cause. `undefined` for anything
|
|
57
|
+
* else, which the caller answers as the defect it is.
|
|
58
|
+
*/
|
|
59
|
+
export declare function deliberateRefusalCode(error: unknown): AvOperationErrorCode | undefined;
|
|
53
60
|
/**
|
|
54
61
|
* Final framework sanitization, shared by every boundary. A deliberate
|
|
55
62
|
* {@link AvError} carries its own stable outcome; anything else is
|
|
@@ -100,7 +107,7 @@ export declare function resolveUnhandledFailure(failure: UnhandledFailure, chain
|
|
|
100
107
|
* A chain of filters and the context they are told, tried in reverse: the first
|
|
101
108
|
* that returns an {@link AvError} handles the error.
|
|
102
109
|
*/
|
|
103
|
-
|
|
110
|
+
type FilterChain = {
|
|
104
111
|
readonly attempt: (error: unknown, view: CallerArgumentsView, boundary: AdapterBoundary) => Promise<FilteredOutcome | undefined>;
|
|
105
112
|
};
|
|
106
113
|
/** The chain of `filters` (stored outer to inner, tried in reverse), told `context`. */
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isDatabaseRefusalMessage } from "../operations/database-refusal.js";
|
|
1
2
|
import { VALIDATION_CODE_MESSAGES, VALIDATION_CODES, } from "../operations/validation-code.js";
|
|
2
3
|
import { AvError } from "./framework-error.js";
|
|
3
4
|
import { INTERNAL_FAILURE_MESSAGE, internalFailure, OPERATION_CODES, operationFailure, } from "./operation-response.js";
|
|
@@ -164,6 +165,9 @@ function projectIssue(value, unvouched, view, author) {
|
|
|
164
165
|
unvouched.push(supplied);
|
|
165
166
|
}
|
|
166
167
|
}
|
|
168
|
+
else if (isDatabaseRefusalMessage(code, supplied)) {
|
|
169
|
+
message = supplied;
|
|
170
|
+
}
|
|
167
171
|
if (rawPath === undefined) {
|
|
168
172
|
return { code, message };
|
|
169
173
|
}
|
|
@@ -238,6 +242,14 @@ function vetDeliberateOutcome(error, view, author) {
|
|
|
238
242
|
const cause = projectCause(rawCause, unvouched, view, author);
|
|
239
243
|
return cause === undefined ? MALFORMED_OUTCOME : { code, cause, unvouched };
|
|
240
244
|
}
|
|
245
|
+
export function deliberateRefusalCode(error) {
|
|
246
|
+
const outcome = vetDeliberateOutcome(error, { path: [], arguments: undefined }, "developer");
|
|
247
|
+
return outcome === undefined ||
|
|
248
|
+
outcome === MALFORMED_OUTCOME ||
|
|
249
|
+
isInternalCode(outcome.code)
|
|
250
|
+
? undefined
|
|
251
|
+
: outcome.code;
|
|
252
|
+
}
|
|
241
253
|
function reportUnvouched(outcome, report) {
|
|
242
254
|
for (const value of outcome.unvouched) {
|
|
243
255
|
report(value, outcome.code);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Why a code is answered, and what the one who meets it should do. */
|
|
2
|
+
export type ErrorCodeGuidance = {
|
|
3
|
+
/** What typically produced the code, in a sentence or two. */
|
|
4
|
+
readonly cause: string;
|
|
5
|
+
/** What to change so it does not happen again. */
|
|
6
|
+
readonly fix: string;
|
|
7
|
+
};
|
|
8
|
+
/** Guidance for a code whose table holds no message of its own. */
|
|
9
|
+
export type ErrorCodeDescription = ErrorCodeGuidance & {
|
|
10
|
+
/** The code's meaning, in one short sentence. */
|
|
11
|
+
readonly message: string;
|
|
12
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { AvAdapterDiscoveryDiagnosticCode } from "../adapters/adapter-discovery-diagnostic.js";
|
|
2
|
+
import type { AvContractCompilerDiagnosticCode } from "../compiler/contract-compiler-diagnostic.js";
|
|
3
|
+
import type { AvConfigDiagnosticCode } from "../config/config-diagnostic.js";
|
|
4
|
+
import type { AvConstructionStage } from "../framework/framework-construction.error.js";
|
|
5
|
+
import { type AvValidationCode } from "../operations/validation-code.js";
|
|
6
|
+
import { type AvOperationCode } from "./operation-response.js";
|
|
7
|
+
/**
|
|
8
|
+
* The documentation page every catalog entry links into. Each code has its own
|
|
9
|
+
* anchor there: the code in lower case (`#a2004`, `#config_required`).
|
|
10
|
+
*/
|
|
11
|
+
export declare const ERROR_CODES_DOCS_URL = "https://aventara.razor34.dev/framework/docs/error-codes";
|
|
12
|
+
/**
|
|
13
|
+
* What kind of code an entry is: an outcome code's family (`success` `A1xxx`,
|
|
14
|
+
* `request` `A2xxx`, `internal` `A3xxx`, `auth` `A4xxx`), a `validation` issue
|
|
15
|
+
* code (`V1xxx`), or a startup code, by the construction stage that reports it.
|
|
16
|
+
*/
|
|
17
|
+
export type AvErrorKind = "success" | "request" | "internal" | "auth" | "validation" | AvConstructionStage;
|
|
18
|
+
/** Every code the catalog describes: outcome, validation and startup codes. */
|
|
19
|
+
export type AvErrorCatalogCode = AvOperationCode | AvValidationCode | AvConfigDiagnosticCode | AvAdapterDiscoveryDiagnosticCode | AvContractCompilerDiagnosticCode;
|
|
20
|
+
/** One code: what it means, why it happens, what to do, and where it is documented. */
|
|
21
|
+
export type AvErrorCatalogEntry<C extends AvErrorCatalogCode = AvErrorCatalogCode> = {
|
|
22
|
+
readonly code: C;
|
|
23
|
+
readonly kind: AvErrorKind;
|
|
24
|
+
/** Its meaning in one sentence; for a V-code, the framework's message for it. */
|
|
25
|
+
readonly message: string;
|
|
26
|
+
/** What typically produces it. */
|
|
27
|
+
readonly cause: string;
|
|
28
|
+
/** What to change. */
|
|
29
|
+
readonly fix: string;
|
|
30
|
+
/** Its entry on the error-codes page. */
|
|
31
|
+
readonly docs: string;
|
|
32
|
+
};
|
|
33
|
+
/** The error catalog's type: one entry per code. */
|
|
34
|
+
export type AvErrorCatalog = {
|
|
35
|
+
readonly [C in AvErrorCatalogCode]: AvErrorCatalogEntry<C>;
|
|
36
|
+
};
|
|
37
|
+
/** The documentation URL of one code: the error-codes page at its anchor. */
|
|
38
|
+
export declare function errorDocsUrl(code: AvErrorCatalogCode): string;
|
|
39
|
+
/**
|
|
40
|
+
* Every code Aventara answers or refuses with, by code: its `kind`, `message`,
|
|
41
|
+
* `cause`, `fix` and `docs` URL. An operation's `code`, a validation issue's
|
|
42
|
+
* `code` and a startup diagnostic's `code` are all keys of it:
|
|
43
|
+
*
|
|
44
|
+
* ```ts
|
|
45
|
+
* AvErrorCatalog[error.code].fix;
|
|
46
|
+
* AvErrorCatalog.V1000.docs; // https://aventara.razor34.dev/framework/docs/error-codes#v1000
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare const AvErrorCatalog: AvErrorCatalog;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ADAPTER_DISCOVERY_DIAGNOSTIC_GUIDANCE } from "../adapters/adapter-discovery-diagnostic.guidance.js";
|
|
2
|
+
import { CONTRACT_COMPILER_DIAGNOSTIC_GUIDANCE } from "../compiler/contract-compiler-diagnostic.guidance.js";
|
|
3
|
+
import { CONFIG_DIAGNOSTIC_GUIDANCE } from "../config/config-diagnostic.guidance.js";
|
|
4
|
+
import { VALIDATION_CODE_GUIDANCE } from "../operations/validation-code.guidance.js";
|
|
5
|
+
import { VALIDATION_CODE_MESSAGES, VALIDATION_CODES, } from "../operations/validation-code.js";
|
|
6
|
+
import { OPERATION_CODE_GUIDANCE } from "./operation-code.guidance.js";
|
|
7
|
+
import { OPERATION_CODES } from "./operation-response.js";
|
|
8
|
+
export const ERROR_CODES_DOCS_URL = "https://aventara.razor34.dev/framework/docs/error-codes";
|
|
9
|
+
export function errorDocsUrl(code) {
|
|
10
|
+
return `${ERROR_CODES_DOCS_URL}#${code.toLowerCase()}`;
|
|
11
|
+
}
|
|
12
|
+
const OUTCOME_KIND = {
|
|
13
|
+
"1": "success",
|
|
14
|
+
"2": "request",
|
|
15
|
+
"3": "internal",
|
|
16
|
+
"4": "auth",
|
|
17
|
+
};
|
|
18
|
+
function entry(code, kind, description) {
|
|
19
|
+
return Object.freeze({
|
|
20
|
+
code,
|
|
21
|
+
kind,
|
|
22
|
+
message: description.message,
|
|
23
|
+
cause: description.cause,
|
|
24
|
+
fix: description.fix,
|
|
25
|
+
docs: errorDocsUrl(code),
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function entriesOf(table, kind) {
|
|
29
|
+
return Object.keys(table).map((code) => [
|
|
30
|
+
code,
|
|
31
|
+
entry(code, kind, table[code]),
|
|
32
|
+
]);
|
|
33
|
+
}
|
|
34
|
+
export const AvErrorCatalog = Object.freeze(Object.fromEntries([
|
|
35
|
+
...OPERATION_CODES.map((code) => [
|
|
36
|
+
code,
|
|
37
|
+
entry(code, OUTCOME_KIND[code[1]], OPERATION_CODE_GUIDANCE[code]),
|
|
38
|
+
]),
|
|
39
|
+
...VALIDATION_CODES.map((code) => [
|
|
40
|
+
code,
|
|
41
|
+
entry(code, "validation", {
|
|
42
|
+
message: VALIDATION_CODE_MESSAGES[code],
|
|
43
|
+
...VALIDATION_CODE_GUIDANCE[code],
|
|
44
|
+
}),
|
|
45
|
+
]),
|
|
46
|
+
...entriesOf(CONFIG_DIAGNOSTIC_GUIDANCE, "configuration"),
|
|
47
|
+
...entriesOf(ADAPTER_DISCOVERY_DIAGNOSTIC_GUIDANCE, "discovery"),
|
|
48
|
+
...entriesOf(CONTRACT_COMPILER_DIAGNOSTIC_GUIDANCE, "contract-compilation"),
|
|
49
|
+
]));
|
|
@@ -18,4 +18,12 @@ export type AvExecutionOptions = {
|
|
|
18
18
|
* object), the Framework starts the request with `{}`.
|
|
19
19
|
*/
|
|
20
20
|
readonly state?: AvState & object;
|
|
21
|
+
/**
|
|
22
|
+
* The principal the call or run is checked as by the configuration's
|
|
23
|
+
* `policy`. An application call names one to opt in: left out, it is server
|
|
24
|
+
* code and the policy does not check it. A `framework.client.*` call is
|
|
25
|
+
* checked either way, and `as` replaces the principal `policy.principal`
|
|
26
|
+
* would derive from its state. `null` is the anonymous principal.
|
|
27
|
+
*/
|
|
28
|
+
readonly as?: unknown;
|
|
21
29
|
};
|
|
@@ -24,6 +24,4 @@ export declare function fieldCheckIssue(check: AvFieldCheck, subject: FieldCheck
|
|
|
24
24
|
export declare function fieldCheckIssues(checks: readonly AvFieldCheck[], value: unknown, subject: FieldCheckSubject, path: Path, list: boolean): readonly AvValidationIssue[];
|
|
25
25
|
/** The issues of the checks one value — a whole value, or a list's entry — breaks. */
|
|
26
26
|
export declare function entryCheckIssues(checks: readonly AvFieldCheck[], value: unknown, subject: FieldCheckSubject, path: Path): readonly AvValidationIssue[];
|
|
27
|
-
/** Whether a check judges a list's own length (`AvZ.minItems`/`AvZ.maxItems`). */
|
|
28
|
-
export declare function isListCheck(check: AvFieldCheck): boolean;
|
|
29
27
|
export {};
|
|
@@ -515,7 +515,7 @@ export function entryCheckIssues(checks, value, subject, path) {
|
|
|
515
515
|
}
|
|
516
516
|
return issues;
|
|
517
517
|
}
|
|
518
|
-
|
|
518
|
+
function isListCheck(check) {
|
|
519
519
|
return ((check.check === "max_length" || check.check === "min_length") &&
|
|
520
520
|
check.list === true);
|
|
521
521
|
}
|