@astrale-os/kernel-dsl 1.0.0-beta.2 → 1.0.0-beta.20
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/dist/v1/addressing/class-key.js +3 -3
- package/dist/v1/addressing/definition-ref.js +21 -37
- package/dist/v1/addressing/domain-dependency.d.ts +0 -6
- package/dist/v1/addressing/domain-dependency.js +1 -6
- package/dist/v1/addressing/key.d.ts +4 -1
- package/dist/v1/addressing/key.js +23 -3
- package/dist/v1/addressing/ordering.d.ts +2 -0
- package/dist/v1/addressing/ordering.js +4 -0
- package/dist/v1/addressing/patterns.d.ts +1 -1
- package/dist/v1/addressing/patterns.js +2 -6
- package/dist/v1/builder/callable/authoring.d.ts +11 -5
- package/dist/v1/builder/callable/authoring.js +2 -0
- package/dist/v1/builder/class/authoring.d.ts +94 -224
- package/dist/v1/builder/class/authoring.js +31 -33
- package/dist/v1/builder/class/handle.d.ts +27 -0
- package/dist/v1/builder/class/handle.js +1 -0
- package/dist/v1/builder/class/input.d.ts +159 -0
- package/dist/v1/builder/class/projection.d.ts +129 -0
- package/dist/v1/builder/class/projection.js +1 -0
- package/dist/v1/builder/class/property.d.ts +3 -9
- package/dist/v1/builder/class/property.js +1 -0
- package/dist/v1/builder/core/authoring.d.ts +1 -1
- package/dist/v1/builder/index.d.ts +5 -2
- package/dist/v1/builder/lowering/callable.js +1 -0
- package/dist/v1/builder/lowering/class.d.ts +9 -1
- package/dist/v1/builder/lowering/class.js +62 -17
- package/dist/v1/builder/lowering/policy.js +2 -0
- package/dist/v1/builder/lowering/property-keys.d.ts +27 -0
- package/dist/v1/builder/lowering/property-keys.js +108 -0
- package/dist/v1/builder/lowering/schema/compile.js +11 -6
- package/dist/v1/builder/lowering/schema/context.d.ts +9 -1
- package/dist/v1/builder/lowering/schema/context.js +36 -4
- package/dist/v1/builder/lowering/schema/lifetime.d.ts +11 -0
- package/dist/v1/builder/lowering/schema/lifetime.js +55 -0
- package/dist/v1/builder/lowering/value/path.d.ts +1 -1
- package/dist/v1/builder/lowering/value/path.js +2 -4
- package/dist/v1/builder/lowering/value/zod.js +1 -3
- package/dist/v1/builder/policy/authoring.d.ts +85 -5
- package/dist/v1/builder/policy/authoring.js +107 -68
- package/dist/v1/builder/schema/define.d.ts +0 -1
- package/dist/v1/builder/schema/diagnostic.d.ts +3 -2
- package/dist/v1/builder/schema/diagnostic.js +5 -10
- package/dist/v1/builder/schema/input.d.ts +1 -1
- package/dist/v1/builder/schema/projection/callable.d.ts +7 -5
- package/dist/v1/builder/schema/projection/class.d.ts +118 -15
- package/dist/v1/builder/schema/projection/core-input.d.ts +2 -1
- package/dist/v1/builder/schema/projection/identity.d.ts +2 -1
- package/dist/v1/builder/schema/projection/model.d.ts +4 -2
- package/dist/v1/builder/schema/projection/property.d.ts +1 -1
- package/dist/v1/builder/schema/projection/resolved-class.d.ts +2 -1
- package/dist/v1/builder/schema/projection.d.ts +1 -1
- package/dist/v1/builder/value/full-match.d.ts +0 -1
- package/dist/v1/builder/value/full-match.js +0 -1
- package/dist/v1/builder/value/path-metadata.d.ts +1 -1
- package/dist/v1/builder/value/path.d.ts +1 -1
- package/dist/v1/bundle/codec.js +11 -13
- package/dist/v1/bundle/diagnostic.d.ts +2 -0
- package/dist/v1/bundle/diagnostic.js +9 -7
- package/dist/v1/bundle/model.js +1 -1
- package/dist/v1/bundle/structure.js +4 -6
- package/dist/v1/compiled/admission/accept.js +4 -10
- package/dist/v1/compiled/admission/closure.js +2 -2
- package/dist/v1/compiled/admission/diagnostic.d.ts +1 -1
- package/dist/v1/compiled/admission/diagnostic.js +1 -3
- package/dist/v1/compiled/admission/revision.d.ts +9 -1
- package/dist/v1/compiled/admission/revision.js +6 -3
- package/dist/v1/compiled/admission/semantics/class.d.ts +4 -1
- package/dist/v1/compiled/admission/semantics/class.js +37 -12
- package/dist/v1/compiled/admission/semantics/core.d.ts +1 -24
- package/dist/v1/compiled/admission/semantics/core.js +56 -24
- package/dist/v1/compiled/admission/semantics/edge.d.ts +2 -4
- package/dist/v1/compiled/admission/semantics/edge.js +6 -65
- package/dist/v1/compiled/admission/semantics/policy/callable.js +0 -2
- package/dist/v1/compiled/admission/semantics/policy/contracts.d.ts +5 -20
- package/dist/v1/compiled/admission/semantics/policy/contracts.js +8 -21
- package/dist/v1/compiled/admission/semantics/policy/parity.js +40 -43
- package/dist/v1/compiled/admission/semantics/policy/pattern.d.ts +4 -1
- package/dist/v1/compiled/admission/semantics/policy/pattern.js +4 -16
- package/dist/v1/compiled/admission/semantics/policy/typing.d.ts +2 -24
- package/dist/v1/compiled/admission/semantics/policy/typing.js +19 -201
- package/dist/v1/compiled/admission/wire/callable.js +11 -1
- package/dist/v1/compiled/admission/wire/class.js +73 -21
- package/dist/v1/compiled/admission/wire/policy.d.ts +4 -3
- package/dist/v1/compiled/admission/wire/policy.js +8 -7
- package/dist/v1/compiled/compiler/compile.js +8 -8
- package/dist/v1/compiled/diagnostic.js +2 -3
- package/dist/v1/compiled/loader/load.d.ts +3 -2
- package/dist/v1/compiled/loader/load.js +11 -45
- package/dist/v1/domain/create.js +5 -6
- package/dist/v1/domain/model/domain.d.ts +2 -7
- package/dist/v1/domain/model/input.d.ts +2 -1
- package/dist/v1/domain/namespace/member-collection.js +4 -6
- package/dist/v1/domain/projection/classes.js +4 -1
- package/dist/v1/domain/validation/create.d.ts +6 -3
- package/dist/v1/domain/validation/create.js +21 -69
- package/dist/v1/index.d.ts +2 -1
- package/dist/v1/language/.spec/schemas/draft-2020-12.schema.json +462 -0
- package/dist/v1/language/.spec/schemas/value-schema.schema.json +22 -0
- package/dist/v1/language/callable/admission.d.ts +15 -0
- package/dist/v1/language/callable/admission.js +43 -0
- package/dist/v1/language/callable/model/callable.d.ts +10 -0
- package/dist/v1/language/callable/resolved.d.ts +16 -3
- package/dist/v1/language/class/inheritance.d.ts +36 -5
- package/dist/v1/language/class/inheritance.js +87 -1
- package/dist/v1/language/class/lifetime.d.ts +50 -11
- package/dist/v1/language/class/lifetime.js +89 -20
- package/dist/v1/language/class/model/class.d.ts +45 -9
- package/dist/v1/language/class/model/edge.d.ts +31 -2
- package/dist/v1/language/class/model/property.d.ts +16 -7
- package/dist/v1/language/class/property-values.js +2 -4
- package/dist/v1/language/class/unique.d.ts +143 -0
- package/dist/v1/language/class/unique.js +264 -0
- package/dist/v1/language/core/facts.d.ts +85 -0
- package/dist/v1/language/core/facts.js +116 -0
- package/dist/v1/language/definition/metadata.d.ts +5 -0
- package/dist/v1/language/definition/metadata.js +7 -0
- package/dist/v1/language/freeze.d.ts +5 -0
- package/dist/v1/{schema/canonical → language}/freeze.js +4 -0
- package/dist/v1/language/index.d.ts +7 -2
- package/dist/v1/language/index.js +5 -1
- package/dist/v1/language/limits.d.ts +64 -0
- package/dist/v1/language/limits.js +60 -0
- package/dist/v1/language/policy/analysis/branches.d.ts +8 -0
- package/dist/v1/language/policy/analysis/branches.js +2 -1
- package/dist/v1/language/policy/analysis/budgets.d.ts +45 -12
- package/dist/v1/language/policy/analysis/budgets.js +133 -19
- package/dist/v1/language/policy/analysis/checks.js +3 -2
- package/dist/v1/language/policy/analysis/typing.d.ts +51 -0
- package/dist/v1/language/policy/analysis/typing.js +455 -0
- package/dist/v1/language/policy/model/policy.d.ts +49 -9
- package/dist/v1/language/policy/model/policy.js +14 -0
- package/dist/v1/language/policy/normalization/normalize.d.ts +6 -6
- package/dist/v1/language/policy/normalization/normalize.js +22 -21
- package/dist/v1/language/validation/diagnostic.d.ts +15 -1
- package/dist/v1/language/validation/diagnostic.js +21 -0
- package/dist/v1/language/validation/rule.d.ts +45 -0
- package/dist/v1/language/validation/rule.js +109 -0
- package/dist/v1/language/value/compile/fields.js +4 -8
- package/dist/v1/language/value/evaluate/program.d.ts +2 -1
- package/dist/v1/language/value/evaluate/program.js +2 -2
- package/dist/v1/language/value/evaluate/validate.d.ts +2 -2
- package/dist/v1/language/value/evaluate/validate.js +6 -2
- package/dist/v1/language/value/evaluate/validity.optimization.d.ts +14 -0
- package/dist/v1/language/value/evaluate/validity.optimization.js +342 -0
- package/dist/v1/language/value/inclusion/arrays.d.ts +3 -0
- package/dist/v1/language/value/inclusion/arrays.js +85 -0
- package/dist/v1/language/value/inclusion/assertions.d.ts +18 -0
- package/dist/v1/language/value/inclusion/assertions.js +29 -0
- package/dist/v1/language/value/inclusion/combinators.d.ts +3 -0
- package/dist/v1/language/value/inclusion/combinators.js +67 -0
- package/dist/v1/language/value/inclusion/equivalence.d.ts +4 -0
- package/dist/v1/language/value/inclusion/equivalence.js +74 -0
- package/dist/v1/language/value/inclusion/evidence.d.ts +34 -0
- package/dist/v1/language/value/inclusion/evidence.js +138 -0
- package/dist/v1/language/value/inclusion/includes.d.ts +17 -0
- package/dist/v1/language/value/inclusion/includes.js +25 -719
- package/dist/v1/language/value/inclusion/keywords.d.ts +5 -0
- package/dist/v1/language/value/inclusion/keywords.js +31 -0
- package/dist/v1/language/value/inclusion/kinds.d.ts +17 -0
- package/dist/v1/language/value/inclusion/kinds.js +57 -0
- package/dist/v1/language/value/inclusion/location.d.ts +24 -0
- package/dist/v1/language/value/inclusion/location.js +63 -0
- package/dist/v1/language/value/inclusion/numbers.d.ts +3 -0
- package/dist/v1/language/value/inclusion/numbers.js +41 -0
- package/dist/v1/language/value/inclusion/objects.d.ts +3 -0
- package/dist/v1/language/value/inclusion/objects.js +190 -0
- package/dist/v1/language/value/inclusion/strings.d.ts +3 -0
- package/dist/v1/language/value/inclusion/strings.js +29 -0
- package/dist/v1/language/value/inclusion/types.d.ts +3 -0
- package/dist/v1/language/value/inclusion/types.js +11 -0
- package/dist/v1/language/value/ordering.d.ts +14 -0
- package/dist/v1/language/value/ordering.js +86 -9
- package/dist/v1/language/value/profile/canonicalize.js +6 -5
- package/dist/v1/language/value/profile/json.validate.d.ts +3 -1
- package/dist/v1/language/value/profile/json.validate.js +3 -2
- package/dist/v1/language/value/profile/meta-schema.compiled.js +4 -1
- package/dist/v1/language/value/profile/rules.js +17 -43
- package/dist/v1/language/value/profile/validate.js +1 -10
- package/dist/v1/language/value/profile/vocabulary.d.ts +35 -2
- package/dist/v1/language/value/profile/vocabulary.js +52 -5
- package/dist/v1/language/value/reference/closure.js +3 -4
- package/dist/v1/language/value/reference/recursion.js +2 -22
- package/dist/v1/language/value/reference/registry.index.d.ts +2 -0
- package/dist/v1/language/value/reference/registry.index.js +33 -16
- package/dist/v1/language/value/regexp/ast.js +6 -7
- package/dist/v1/language/value/regexp/compile.d.ts +5 -11
- package/dist/v1/language/value/regexp/compile.js +14 -12
- package/dist/v1/language/value/regexp/syntax.js +3 -2
- package/dist/v1/language/value/syntax/keywords.d.ts +3 -3
- package/dist/v1/language/value/syntax/keywords.js +4 -20
- package/dist/v1/language/value/syntax/node-path/validate.js +2 -3
- package/dist/v1/language/value/syntax/pointer.d.ts +2 -0
- package/dist/v1/language/value/syntax/pointer.js +5 -2
- package/dist/v1/language/value/syntax/walk.d.ts +2 -0
- package/dist/v1/language/value/syntax/walk.js +19 -20
- package/dist/v1/schema/.spec/schemas/domain-schema.schema.json +2519 -0
- package/dist/v1/schema/admission/accept.js +3 -14
- package/dist/v1/schema/admission/callable.d.ts +21 -0
- package/dist/v1/schema/admission/callable.js +96 -0
- package/dist/v1/schema/analysis/class.js +33 -15
- package/dist/v1/schema/canonical/revision.js +4 -4
- package/dist/v1/schema/compatibility/api.d.ts +2 -1
- package/dist/v1/schema/compatibility/api.js +1 -0
- package/dist/v1/schema/compatibility/comparators/callables.js +1 -1
- package/dist/v1/schema/compatibility/comparators/classes.d.ts +9 -4
- package/dist/v1/schema/compatibility/comparators/classes.js +29 -8
- package/dist/v1/schema/compatibility/comparators/index.d.ts +1 -1
- package/dist/v1/schema/compatibility/comparators/members.js +1 -1
- package/dist/v1/schema/compatibility/comparators/values.js +2 -2
- package/dist/v1/schema/compatibility/coordinate.js +3 -3
- package/dist/v1/schema/compatibility/diff.js +2 -4
- package/dist/v1/schema/compatibility/extension.d.ts +11 -0
- package/dist/v1/schema/compatibility/extension.js +22 -0
- package/dist/v1/schema/compatibility/fields.d.ts +20 -4
- package/dist/v1/schema/compatibility/fields.js +13 -3
- package/dist/v1/schema/compatibility/meaning/footprint.js +16 -50
- package/dist/v1/schema/compatibility/model.d.ts +17 -5
- package/dist/v1/schema/compatibility/report.js +1 -1
- package/dist/v1/schema/compatibility/scope.d.ts +2 -0
- package/dist/v1/schema/compatibility/scope.js +4 -1
- package/dist/v1/schema/compatibility/structure/index.js +6 -4
- package/dist/v1/schema/compatibility/structure/requirements.js +57 -58
- package/dist/v1/schema/compatibility/versioning/index.js +1 -1
- package/dist/v1/schema/compatibility/versioning/surface.d.ts +1 -1
- package/dist/v1/schema/compatibility/versioning/surface.js +30 -2
- package/dist/v1/schema/compatibility/walk.d.ts +17 -0
- package/dist/v1/schema/compatibility/walk.js +41 -0
- package/dist/v1/schema/diagnostic.d.ts +17 -3
- package/dist/v1/schema/diagnostic.js +14 -11
- package/dist/v1/schema/index.d.ts +10 -1
- package/dist/v1/schema/index.js +4 -0
- package/dist/v1/schema/model/schema.d.ts +20 -1
- package/dist/v1/schema/model/schema.js +1 -1
- package/dist/v1/schema/normalization/domain.d.ts +2 -0
- package/dist/v1/schema/normalization/domain.js +29 -9
- package/dist/v1/schema/resolution/closure.js +2 -1
- package/dist/v1/schema/resolution/context.js +13 -13
- package/dist/v1/schema/resolution/domain.d.ts +5 -0
- package/dist/v1/schema/resolution/domain.js +2 -2
- package/dist/v1/schema/resolution/origins.js +3 -2
- package/dist/v1/schema/rule.d.ts +26 -0
- package/dist/v1/schema/rule.js +440 -0
- package/dist/v1/schema/validation/callable.d.ts +35 -2
- package/dist/v1/schema/validation/callable.js +65 -9
- package/dist/v1/schema/validation/class.d.ts +6 -2
- package/dist/v1/schema/validation/class.js +127 -104
- package/dist/v1/schema/validation/core.js +90 -168
- package/dist/v1/schema/validation/domain.js +4 -13
- package/dist/v1/schema/validation/domain.json-schema.d.ts +15 -0
- package/dist/v1/schema/validation/domain.json-schema.js +197 -0
- package/dist/v1/schema/validation/domain.route.d.ts +6 -1
- package/dist/v1/schema/validation/domain.route.js +18 -0
- package/dist/v1/schema/validation/domain.structure.d.ts +7780 -0
- package/dist/v1/schema/validation/domain.structure.js +398 -147
- package/dist/v1/schema/validation/json.json-schema.d.ts +40 -0
- package/dist/v1/schema/validation/json.json-schema.js +46 -0
- package/dist/v1/schema/validation/policy/budgets.d.ts +33 -2
- package/dist/v1/schema/validation/policy/budgets.js +87 -121
- package/dist/v1/schema/validation/policy/context.d.ts +6 -5
- package/dist/v1/schema/validation/policy/context.js +7 -10
- package/dist/v1/schema/validation/policy/objects.d.ts +1 -1
- package/dist/v1/schema/validation/policy/objects.js +6 -14
- package/dist/v1/schema/validation/policy/references.js +11 -27
- package/dist/v1/schema/validation/policy/typing.d.ts +3 -18
- package/dist/v1/schema/validation/policy/typing.js +22 -356
- package/dist/v1/schema/validation/policy/uses.d.ts +40 -3
- package/dist/v1/schema/validation/policy/uses.js +66 -89
- package/dist/v1/schema/validation/policy/validate.js +5 -5
- package/dist/v1/schema/validation/value-api.d.ts +22 -0
- package/dist/v1/schema/validation/value-api.js +34 -1
- package/dist/v1/schema/validation/value.d.ts +3 -0
- package/dist/v1/schema/validation/value.js +9 -17
- package/dist/v1/schema/validation/value.json-schema.d.ts +49 -0
- package/dist/v1/schema/validation/value.json-schema.js +137 -0
- package/dist/v1/schema/validation/view.js +4 -8
- package/dist/value/canonical.d.ts +6 -0
- package/dist/value/canonical.js +36 -0
- package/dist/value/decode.d.ts +7 -0
- package/dist/value/decode.js +159 -9
- package/dist/value/index.d.ts +1 -1
- package/dist/value/json.d.ts +2 -2
- package/dist/value/json.js +2 -2
- package/dist/value/types.d.ts +6 -0
- package/dist/value/unicode.d.ts +2 -1
- package/dist/value/unicode.js +2 -0
- package/package.json +8 -1
- package/dist/v1/builder/lowering/core-properties.d.ts +0 -10
- package/dist/v1/builder/lowering/core-properties.js +0 -76
- package/dist/v1/compiled/admission/semantics/cardinality.d.ts +0 -5
- package/dist/v1/compiled/admission/semantics/cardinality.js +0 -113
- package/dist/v1/compiled/admission/semantics/policy/equality.d.ts +0 -8
- package/dist/v1/compiled/admission/semantics/policy/equality.js +0 -27
- package/dist/v1/compiled/admission/semantics/policy/measure.d.ts +0 -9
- package/dist/v1/compiled/admission/semantics/policy/measure.js +0 -81
- package/dist/v1/compiled/admission/semantics/policy/variants.d.ts +0 -10
- package/dist/v1/compiled/admission/semantics/policy/variants.js +0 -65
- package/dist/v1/language/class/index.d.ts +0 -8
- package/dist/v1/language/class/index.js +0 -1
- package/dist/v1/language/core/index.d.ts +0 -2
- package/dist/v1/language/value/index.d.ts +0 -11
- package/dist/v1/language/value/index.js +0 -8
- package/dist/v1/schema/canonical/domain.d.ts +0 -3
- package/dist/v1/schema/canonical/domain.digest.d.ts +0 -3
- package/dist/v1/schema/canonical/domain.digest.js +0 -5
- package/dist/v1/schema/canonical/domain.js +0 -5
- package/dist/v1/schema/canonical/freeze.d.ts +0 -1
- /package/dist/v1/{language/core/index.js → builder/class/input.js} +0 -0
package/dist/v1/bundle/codec.js
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import { accept as acceptJsonValue, BoundaryError as JsonBoundaryError, json, } from '@astrale-os/kernel-dsl/value';
|
|
2
|
-
import { dependencyLimits } from '../addressing/domain-dependency.js';
|
|
3
2
|
import { compareUnicode } from '../addressing/ordering.js';
|
|
3
|
+
import { limits } from '../language/limits.js';
|
|
4
|
+
import { escapePointerToken } from '../language/value/syntax/pointer.js';
|
|
4
5
|
import { acceptDomainSchema } from '../schema/admission/accept.js';
|
|
5
6
|
import { canonicalDomainSchemaAfterValidation } from '../schema/canonical/revision.js';
|
|
6
7
|
import { revisionOfDomainSchema } from '../schema/canonical/revision.js';
|
|
7
8
|
import { MemoryDomainSchemaLookup } from '../schema/dependency/lookup.js';
|
|
8
9
|
import { SchemaError } from '../schema/diagnostic.js';
|
|
9
|
-
import { BundleError, diagnostic } from './diagnostic.js';
|
|
10
|
+
import { BundleError, diagnostic, schemaDiagnosticAt } from './diagnostic.js';
|
|
10
11
|
import { asDomainSchemaBundle, } from './model.js';
|
|
11
12
|
import { parseDomainSchemaBundleStructure } from './structure.js';
|
|
12
|
-
function escapeToken(value) {
|
|
13
|
-
return value.replaceAll('~', '~0').replaceAll('/', '~1');
|
|
14
|
-
}
|
|
15
13
|
export function acceptDomainSchemaBundle(input) {
|
|
16
14
|
let admitted;
|
|
17
15
|
try {
|
|
@@ -48,12 +46,12 @@ function acceptBundleValue(input) {
|
|
|
48
46
|
const closure = structure.closure.map((schema, index) => candidate(schema, `/closure/${index}`));
|
|
49
47
|
const diagnostics = [];
|
|
50
48
|
const candidates = new Map();
|
|
51
|
-
if (closure.length + 1 >
|
|
52
|
-
diagnostics.push(diagnostic('DV_DEPENDENCY_LIMITS', '/closure', `A dependency closure may contain at most ${
|
|
49
|
+
if (closure.length + 1 > limits.dependency.closure) {
|
|
50
|
+
diagnostics.push(diagnostic('DV_DEPENDENCY_LIMITS', '/closure', `A dependency closure may contain at most ${limits.dependency.closure} Domains.`));
|
|
53
51
|
}
|
|
54
52
|
for (const entry of [root, ...closure]) {
|
|
55
|
-
if (Object.keys(entry.schema.dependencies).length >
|
|
56
|
-
diagnostics.push(diagnostic('DV_DEPENDENCY_LIMITS', `${entry.pointer}/dependencies`, `A Domain may declare at most ${
|
|
53
|
+
if (Object.keys(entry.schema.dependencies).length > limits.dependency.direct) {
|
|
54
|
+
diagnostics.push(diagnostic('DV_DEPENDENCY_LIMITS', `${entry.pointer}/dependencies`, `A Domain may declare at most ${limits.dependency.direct} direct dependency aliases.`));
|
|
57
55
|
}
|
|
58
56
|
}
|
|
59
57
|
for (const entry of closure) {
|
|
@@ -101,7 +99,7 @@ function acceptBundleValue(input) {
|
|
|
101
99
|
catch (error) {
|
|
102
100
|
if (!(error instanceof SchemaError))
|
|
103
101
|
throw error;
|
|
104
|
-
throw new BundleError(error.diagnostics.map((item) =>
|
|
102
|
+
throw new BundleError(error.diagnostics.map((item) => schemaDiagnosticAt(entry.pointer, item)));
|
|
105
103
|
}
|
|
106
104
|
};
|
|
107
105
|
for (const entry of candidates.values()) {
|
|
@@ -130,13 +128,13 @@ function collectReachable(current, root, candidates, reachable, active, revision
|
|
|
130
128
|
return;
|
|
131
129
|
}
|
|
132
130
|
active.add(current.key);
|
|
133
|
-
if (depth >
|
|
134
|
-
diagnostics.push(diagnostic('DV_DEPENDENCY_LIMITS', current.pointer, `Dependency depth ${depth} exceeds the maximum ${
|
|
131
|
+
if (depth > limits.dependency.depth) {
|
|
132
|
+
diagnostics.push(diagnostic('DV_DEPENDENCY_LIMITS', current.pointer, `Dependency depth ${depth} exceeds the maximum ${limits.dependency.depth}.`));
|
|
135
133
|
active.delete(current.key);
|
|
136
134
|
return;
|
|
137
135
|
}
|
|
138
136
|
for (const [alias, dependency] of Object.entries(current.schema.dependencies)) {
|
|
139
|
-
const pointer = `${current.pointer}/dependencies/${
|
|
137
|
+
const pointer = `${current.pointer}/dependencies/${escapePointerToken(alias)}`;
|
|
140
138
|
const dependencyKey = keyOf(dependency.origin, dependency.revision);
|
|
141
139
|
if (dependencyKey === root.key) {
|
|
142
140
|
diagnostics.push(diagnostic('BUNDLE_CLOSURE_CYCLE', pointer, 'Bundle dependency closure returns to its root.'));
|
|
@@ -4,6 +4,8 @@ export type BundleDiagnostic<Code extends BundleDiagnosticCode = BundleDiagnosti
|
|
|
4
4
|
readonly code: Code;
|
|
5
5
|
};
|
|
6
6
|
export declare function diagnostic<const Code extends BundleDiagnosticCode>(code: Code, pointer: string, message: string, ref?: string): BundleDiagnostic<Code>;
|
|
7
|
+
/** A refusal of one bundled schema, its pointer rebased under the schema's place in the bundle. */
|
|
8
|
+
export declare function schemaDiagnosticAt(pointer: string, refusal: SchemaDiagnostic): BundleDiagnostic;
|
|
7
9
|
export declare class BundleError extends Error {
|
|
8
10
|
readonly diagnostics: readonly BundleDiagnostic[];
|
|
9
11
|
constructor(diagnostics: readonly BundleDiagnostic[]);
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { formatDiagnostics, orderDiagnostics } from '../language/validation/diagnostic.js';
|
|
2
2
|
export function diagnostic(code, pointer, message, ref) {
|
|
3
3
|
return Object.freeze({ code, pointer, message, ...(ref === undefined ? {} : { ref }) });
|
|
4
4
|
}
|
|
5
|
+
/** A refusal of one bundled schema, its pointer rebased under the schema's place in the bundle. */
|
|
6
|
+
export function schemaDiagnosticAt(pointer, refusal) {
|
|
7
|
+
// Acceptance refuses a document with Schema codes only, never with comparison request codes.
|
|
8
|
+
const code = refusal.code;
|
|
9
|
+
return Object.freeze({ ...refusal, code, pointer: `${pointer}${refusal.pointer}` });
|
|
10
|
+
}
|
|
5
11
|
export class BundleError extends Error {
|
|
6
12
|
diagnostics;
|
|
7
13
|
constructor(diagnostics) {
|
|
8
|
-
const ordered =
|
|
9
|
-
|
|
10
|
-
compareUnicode(left.message, right.message));
|
|
11
|
-
super(ordered
|
|
12
|
-
.map(({ code, pointer, message }) => `${pointer || '/'} [${code}] ${message}`)
|
|
13
|
-
.join('\n'));
|
|
14
|
+
const ordered = orderDiagnostics(diagnostics);
|
|
15
|
+
super(formatDiagnostics(ordered));
|
|
14
16
|
this.name = 'BundleError';
|
|
15
17
|
this.diagnostics = Object.freeze(ordered);
|
|
16
18
|
}
|
package/dist/v1/bundle/model.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { deepFreeze } from '../
|
|
1
|
+
import { deepFreeze } from '../language/freeze.js';
|
|
2
2
|
export const DOMAIN_BUNDLE_FORMAT = 'astrale.dsl.bundle';
|
|
3
3
|
export const DOMAIN_BUNDLE_VERSION = 'v1';
|
|
4
4
|
export function asDomainSchemaBundle(root, closure) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { escapePointerToken } from '../language/value/syntax/pointer.js';
|
|
1
2
|
import { SchemaError } from '../schema/diagnostic.js';
|
|
2
3
|
import { routeDomainSchema } from '../schema/validation/domain.route.js';
|
|
3
|
-
import { BundleError, diagnostic } from './diagnostic.js';
|
|
4
|
+
import { BundleError, diagnostic, schemaDiagnosticAt } from './diagnostic.js';
|
|
4
5
|
import { DOMAIN_BUNDLE_FORMAT, DOMAIN_BUNDLE_VERSION } from './model.js';
|
|
5
6
|
export function parseDomainSchemaBundleStructure(input) {
|
|
6
7
|
if (!isObject(input)) {
|
|
@@ -12,7 +13,7 @@ export function parseDomainSchemaBundleStructure(input) {
|
|
|
12
13
|
const expected = new Set(['format', 'version', 'root', 'closure']);
|
|
13
14
|
for (const key of Object.keys(input)) {
|
|
14
15
|
if (!expected.has(key)) {
|
|
15
|
-
diagnostics.push(diagnostic('BUNDLE_STRUCTURE', `/${
|
|
16
|
+
diagnostics.push(diagnostic('BUNDLE_STRUCTURE', `/${escapePointerToken(key)}`, `Unknown bundle field ${key}.`));
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
19
|
for (const key of expected) {
|
|
@@ -56,7 +57,7 @@ function routeAt(value, pointer, diagnostics) {
|
|
|
56
57
|
catch (error) {
|
|
57
58
|
if (!(error instanceof SchemaError))
|
|
58
59
|
throw error;
|
|
59
|
-
diagnostics.push(...error.diagnostics.map((entry) =>
|
|
60
|
+
diagnostics.push(...error.diagnostics.map((entry) => schemaDiagnosticAt(pointer, entry)));
|
|
60
61
|
return undefined;
|
|
61
62
|
}
|
|
62
63
|
}
|
|
@@ -66,6 +67,3 @@ function isObject(value) {
|
|
|
66
67
|
function describe(value) {
|
|
67
68
|
return value === undefined ? '(missing)' : JSON.stringify(value);
|
|
68
69
|
}
|
|
69
|
-
function escapeToken(value) {
|
|
70
|
-
return value.replaceAll('~', '~0').replaceAll('/', '~1');
|
|
71
|
-
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { accept as acceptPortable } from '@astrale-os/kernel-dsl/value';
|
|
2
|
-
import {
|
|
2
|
+
import { deepFreeze } from '../../language/freeze.js';
|
|
3
|
+
import { limits } from '../../language/limits.js';
|
|
3
4
|
import {} from '../model/schema.js';
|
|
4
5
|
import { validateClosure } from './closure.js';
|
|
5
6
|
import { invalid, pointer } from './diagnostic.js';
|
|
@@ -20,7 +21,7 @@ export function acceptCompiledSchema(input) {
|
|
|
20
21
|
const rootPin = dependency(root.root, 'root', '/root');
|
|
21
22
|
const machines = new Map();
|
|
22
23
|
const closure = array(root.closure, 'closure', '/closure').map((value, index) => entry(value, index, `/closure/${index}`, machines));
|
|
23
|
-
if (closure.length >
|
|
24
|
+
if (closure.length > limits.dependency.closure) {
|
|
24
25
|
invalid('dependency closure limit', 'COMPILED_DEPENDENCY_LIMITS', '/closure');
|
|
25
26
|
}
|
|
26
27
|
const closureOrigins = new Set();
|
|
@@ -34,7 +35,7 @@ export function acceptCompiledSchema(input) {
|
|
|
34
35
|
if (rootEntry?.revision !== rootPin.revision)
|
|
35
36
|
invalid('root pin', undefined, '/root');
|
|
36
37
|
for (const [entryIndex, owner] of closure.entries()) {
|
|
37
|
-
if (Object.keys(owner.dependencies).length >
|
|
38
|
+
if (Object.keys(owner.dependencies).length > limits.dependency.direct) {
|
|
38
39
|
invalid('direct dependency limit', 'COMPILED_DEPENDENCY_LIMITS', `/closure/${entryIndex}/dependencies`);
|
|
39
40
|
}
|
|
40
41
|
for (const [alias, pin] of Object.entries(owner.dependencies)) {
|
|
@@ -69,10 +70,3 @@ export function acceptCompiledSchema(input) {
|
|
|
69
70
|
validateCompiledSemantics(candidate);
|
|
70
71
|
return deepFreeze(candidate);
|
|
71
72
|
}
|
|
72
|
-
function deepFreeze(input) {
|
|
73
|
-
if (input === null || typeof input !== 'object' || Object.isFrozen(input))
|
|
74
|
-
return input;
|
|
75
|
-
for (const value of Object.values(input))
|
|
76
|
-
deepFreeze(value);
|
|
77
|
-
return Object.freeze(input);
|
|
78
|
-
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {} from '@astrale-os/kernel-dsl/value';
|
|
2
|
-
import { dependencyLimits } from '../../addressing/domain-dependency.js';
|
|
3
2
|
import { Key, isDefinitionRef } from '../../addressing/index.js';
|
|
4
3
|
import {} from '../../language/class/model/edge.js';
|
|
4
|
+
import { limits } from '../../language/limits.js';
|
|
5
5
|
import {} from '../model/schema.js';
|
|
6
6
|
import { invalid, pointer } from './diagnostic.js';
|
|
7
7
|
/** Require closed direct references, acyclic inheritance and concrete Core Classes. */
|
|
@@ -128,7 +128,7 @@ function validateDependencyCycles(candidate) {
|
|
|
128
128
|
const visited = new Set();
|
|
129
129
|
const frames = [];
|
|
130
130
|
const push = (origin, depth) => {
|
|
131
|
-
if (depth >
|
|
131
|
+
if (depth > limits.dependency.depth) {
|
|
132
132
|
invalid('dependency depth limit', 'COMPILED_DEPENDENCY_LIMITS', `/closure/${byOrigin.get(origin)?.index ?? 0}/dependencies`);
|
|
133
133
|
}
|
|
134
134
|
active.add(origin);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type CompiledDiagnosticCode } from '../diagnostic.js';
|
|
2
2
|
/** Append one escaped JSON Pointer segment. */
|
|
3
|
-
export
|
|
3
|
+
export { appendPointer as pointer } from '../../language/value/syntax/pointer.js';
|
|
4
4
|
/** Report a structural compiled-input violation with its stable diagnostic code. */
|
|
5
5
|
export declare function invalid(label: string, code?: CompiledDiagnosticCode, path?: string): never;
|
|
6
6
|
/** Report a contextual compiled-language violation at its original source pointer. */
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { invalidCompiled } from '../diagnostic.js';
|
|
2
2
|
/** Append one escaped JSON Pointer segment. */
|
|
3
|
-
export
|
|
4
|
-
return `${parent}/${String(member).replaceAll('~', '~0').replaceAll('/', '~1')}`;
|
|
5
|
-
}
|
|
3
|
+
export { appendPointer as pointer } from '../../language/value/syntax/pointer.js';
|
|
6
4
|
/** Report a structural compiled-input violation with its stable diagnostic code. */
|
|
7
5
|
export function invalid(label, code = 'COMPILED_STRUCTURE_INVALID', path = '') {
|
|
8
6
|
return invalidCompiled(code, `Invalid compiled Schema ${label}.`, path);
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import type { Revision } from '../../addressing/index.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { FunctionDefinition, MethodDefinition } from '../../language/callable/model/callable.js';
|
|
3
|
+
import type { JsonSchema } from '../../language/value/model/schema.js';
|
|
4
|
+
import type { CompiledFunction, CompiledMethod, CompiledSchemaEntry } from '../model/schema.js';
|
|
3
5
|
/** Derive the exact canonical source-revision preimage without constructing an authored Schema. */
|
|
4
6
|
export declare function revisionOfCompiledEntry(entry: CompiledSchemaEntry): Revision;
|
|
7
|
+
/** The source definition of a compiled Method: its value programs back to their schemas. */
|
|
8
|
+
export declare function sourceMethod(entry: CompiledSchemaEntry, method: CompiledMethod): MethodDefinition;
|
|
9
|
+
/** The source definition of a compiled Function: its value programs back to their schemas. */
|
|
10
|
+
export declare function sourceFunction(entry: CompiledSchemaEntry, definition: CompiledFunction): FunctionDefinition;
|
|
11
|
+
/** The schema of the root node of the entry's value program `index`. */
|
|
12
|
+
export declare function schemaOf(entry: CompiledSchemaEntry, index: number): JsonSchema;
|
|
@@ -44,7 +44,8 @@ function sourceClass(entry, definition) {
|
|
|
44
44
|
methods: Object.fromEntries(methods.map((method) => [method.name, sourceMethod(entry, method)])),
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
|
-
|
|
47
|
+
/** The source definition of a compiled Method: its value programs back to their schemas. */
|
|
48
|
+
export function sourceMethod(entry, method) {
|
|
48
49
|
const { name: _, input, fields: __, output, ...rest } = method;
|
|
49
50
|
return {
|
|
50
51
|
...rest,
|
|
@@ -52,7 +53,8 @@ function sourceMethod(entry, method) {
|
|
|
52
53
|
output: sourceOutput(entry, output),
|
|
53
54
|
};
|
|
54
55
|
}
|
|
55
|
-
|
|
56
|
+
/** The source definition of a compiled Function: its value programs back to their schemas. */
|
|
57
|
+
export function sourceFunction(entry, definition) {
|
|
56
58
|
const { input, fields: _, output, ...rest } = definition;
|
|
57
59
|
return {
|
|
58
60
|
...rest,
|
|
@@ -72,7 +74,8 @@ function sourceOutput(entry, output) {
|
|
|
72
74
|
const schema = schemaOf(entry, output.value);
|
|
73
75
|
return output.mode === 'value' ? { mode: 'value', schema } : { mode: 'stream', item: schema };
|
|
74
76
|
}
|
|
75
|
-
|
|
77
|
+
/** The schema of the root node of the entry's value program `index`. */
|
|
78
|
+
export function schemaOf(entry, index) {
|
|
76
79
|
const program = entry.values[index];
|
|
77
80
|
const root = program?.nodes[program.root];
|
|
78
81
|
if (root === undefined)
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { type Located, type CompiledClass, type ClassAnalysis, type SemanticIndex } from './context.js';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Compose inherited Properties, Methods and Data ownership once per Class. The closure check has
|
|
4
|
+
* already proved every parent present and the inheritance graph acyclic.
|
|
5
|
+
*/
|
|
3
6
|
export declare function analyzeClasses(classes: ReadonlyMap<string, Located<CompiledClass>>): ReadonlyMap<string, ClassAnalysis>;
|
|
4
7
|
/** Check automatic Properties, immutability and abstract Class obligations. */
|
|
5
8
|
export declare function validateClassFacets(context: SemanticIndex): void;
|
|
@@ -2,26 +2,26 @@ import { json } from '@astrale-os/kernel-dsl/value';
|
|
|
2
2
|
import { Key, PropertyKey as PropertyKeyValue, } from '../../../addressing/index.js';
|
|
3
3
|
import { composeMethods } from '../../../language/callable/composition.js';
|
|
4
4
|
import { isMethodExecutable } from '../../../language/callable/executable.js';
|
|
5
|
+
import { keyableProperty } from '../../../language/class/unique.js';
|
|
5
6
|
import { bindValueProgram } from '../../../language/value/compile/load.js';
|
|
6
7
|
import {} from '../../model/schema.js';
|
|
7
8
|
import { fail } from '../diagnostic.js';
|
|
8
9
|
import {} from './context.js';
|
|
9
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Compose inherited Properties, Methods and Data ownership once per Class. The closure check has
|
|
12
|
+
* already proved every parent present and the inheritance graph acyclic.
|
|
13
|
+
*/
|
|
10
14
|
export function analyzeClasses(classes) {
|
|
11
15
|
const analyses = new Map();
|
|
12
|
-
const visiting = new Set();
|
|
13
16
|
const analyze = (located) => {
|
|
14
17
|
const classKey = Key.of(located.value.ref);
|
|
15
18
|
const cached = analyses.get(classKey);
|
|
16
19
|
if (cached !== undefined)
|
|
17
20
|
return cached;
|
|
18
|
-
if (visiting.has(classKey))
|
|
19
|
-
fail(`${located.pointer}/extends`, 'Class inheritance is cyclic.');
|
|
20
|
-
visiting.add(classKey);
|
|
21
21
|
const parents = located.value.extends.map((ref, index) => {
|
|
22
22
|
const parent = classes.get(Key.of(ref));
|
|
23
|
-
if (parent ===
|
|
24
|
-
fail(`${located.pointer}/extends/${index}`, '
|
|
23
|
+
if (parent.value.inheritance === 'final')
|
|
24
|
+
fail(`${located.pointer}/extends/${index}`, 'A final Class has no subclass.');
|
|
25
25
|
return analyze(parent);
|
|
26
26
|
});
|
|
27
27
|
const properties = new Map();
|
|
@@ -68,7 +68,6 @@ export function analyzeClasses(classes) {
|
|
|
68
68
|
...(dataOwner === undefined ? {} : { dataOwner }),
|
|
69
69
|
};
|
|
70
70
|
analyses.set(classKey, analysis);
|
|
71
|
-
visiting.delete(classKey);
|
|
72
71
|
return analysis;
|
|
73
72
|
};
|
|
74
73
|
for (const value of classes.values())
|
|
@@ -91,9 +90,8 @@ function programKey(entry, value) {
|
|
|
91
90
|
/** Check automatic Properties, immutability and abstract Class obligations. */
|
|
92
91
|
export function validateClassFacets(context) {
|
|
93
92
|
for (const located of context.classes.values()) {
|
|
94
|
-
if (located.value.abstract &&
|
|
95
|
-
(located.
|
|
96
|
-
fail(`${located.pointer}/policies`, 'Abstract Classes cannot declare observation Policies.');
|
|
93
|
+
if (located.value.abstract && Object.keys(located.value.policies).length > 0) {
|
|
94
|
+
fail(`${located.pointer}/policies`, 'Abstract Classes cannot declare Class Policies.');
|
|
97
95
|
}
|
|
98
96
|
for (const [index, property] of located.value.properties.entries()) {
|
|
99
97
|
const path = `${located.pointer}/properties/${index}`;
|
|
@@ -114,11 +112,38 @@ export function validateClassFacets(context) {
|
|
|
114
112
|
}
|
|
115
113
|
}
|
|
116
114
|
}
|
|
115
|
+
if (located.value.unique !== undefined) {
|
|
116
|
+
const properties = context.analyses.get(Key.of(located.value.ref))?.properties;
|
|
117
|
+
const keyable = (key, at) => {
|
|
118
|
+
const property = properties?.get(key)?.declaration;
|
|
119
|
+
if (property === undefined || !keyableProperty(property.ordering, property.auto)) {
|
|
120
|
+
fail(at, 'A key Property is a keyable Property of the Class.');
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
// A Node tuple names Properties only; an Edge tuple names them as `{ property }`.
|
|
124
|
+
const value = located.value;
|
|
125
|
+
if (value.kind === 'node') {
|
|
126
|
+
for (const [t, tuple] of (value.unique ?? []).entries())
|
|
127
|
+
for (const [f, key] of tuple.entries())
|
|
128
|
+
keyable(key, `${located.pointer}/unique/${t}/${f}`);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
for (const [t, tuple] of (value.unique ?? []).entries())
|
|
132
|
+
for (const [f, field] of tuple.entries())
|
|
133
|
+
if (typeof field !== 'string')
|
|
134
|
+
keyable(field.property, `${located.pointer}/unique/${t}/${f}/property`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
117
137
|
if (located.value.kind === 'node') {
|
|
118
138
|
for (const [index, method] of located.value.methods.entries()) {
|
|
119
|
-
if (
|
|
139
|
+
if (isMethodExecutable(located.value, method))
|
|
140
|
+
continue;
|
|
141
|
+
if (method.policy !== undefined) {
|
|
120
142
|
fail(`${located.pointer}/methods/${index}/policy`, 'An abstract Method cannot have a Policy.');
|
|
121
143
|
}
|
|
144
|
+
if (method.admission !== undefined) {
|
|
145
|
+
fail(`${located.pointer}/methods/${index}/admission`, 'An abstract Method cannot have an admission age.');
|
|
146
|
+
}
|
|
122
147
|
}
|
|
123
148
|
}
|
|
124
149
|
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { type ClassRef } from '../../../addressing/index.js';
|
|
2
|
-
import { type CoreEdge } from '../../../language/core/model/core.js';
|
|
3
1
|
import { type CompiledSchemaEntry, type CompiledSchema } from '../../model/schema.js';
|
|
4
|
-
import { type Located, type CompiledClass, type ClassAnalysis, type
|
|
2
|
+
import { type Located, type CompiledClass, type ClassAnalysis, type SemanticIndex } from './context.js';
|
|
5
3
|
/** A local Core Node paired with its admitted Class analysis. */
|
|
6
4
|
export interface CoreNode {
|
|
7
5
|
readonly key: string;
|
|
@@ -10,26 +8,5 @@ export interface CoreNode {
|
|
|
10
8
|
readonly analysis: ClassAnalysis;
|
|
11
9
|
readonly pointer: string;
|
|
12
10
|
}
|
|
13
|
-
/**
|
|
14
|
-
* A local Definition other than a Core Node, or a Class-owned Method. The Domain projects it as a
|
|
15
|
-
* Kernel declaration Node, so `class` names that Kernel Class rather than an authored one.
|
|
16
|
-
*/
|
|
17
|
-
interface CoreMemberEndpoint {
|
|
18
|
-
readonly key: string;
|
|
19
|
-
readonly class: ClassRef;
|
|
20
|
-
readonly pointer: string;
|
|
21
|
-
}
|
|
22
|
-
type CoreEndpoint = CoreNode | CoreMemberEndpoint | {
|
|
23
|
-
readonly key: 'domain';
|
|
24
|
-
};
|
|
25
|
-
/** A Core Edge paired with resolved endpoints and its exact Class. */
|
|
26
|
-
export interface CoreEdgeValue {
|
|
27
|
-
readonly source: CoreEndpoint;
|
|
28
|
-
readonly target: CoreEndpoint;
|
|
29
|
-
readonly value: CoreEdge;
|
|
30
|
-
readonly class: Located<CompiledEdge>;
|
|
31
|
-
readonly pointer: string;
|
|
32
|
-
}
|
|
33
11
|
/** Admit local Core Nodes, Properties and Edge endpoint contracts. */
|
|
34
12
|
export declare function validateCore(candidate: CompiledSchema, context: SemanticIndex): void;
|
|
35
|
-
export {};
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import { Key } from '../../../addressing/index.js';
|
|
2
2
|
import { isMethodExecutable } from '../../../language/callable/executable.js';
|
|
3
|
+
import { coveringEdgeUniqueTuples, coveringNodeUniqueTuples, edgeUniqueKeys, nodeUniqueKeys, } from '../../../language/class/unique.js';
|
|
4
|
+
import { checkCoreEdgeSet, checkHeldKeys, coreEndpointsSatisfy, DOMAIN_ENDPOINT_CLASS, } from '../../../language/core/facts.js';
|
|
3
5
|
import {} from '../../../language/core/model/core.js';
|
|
4
6
|
import { policyObjectOrigin, policyObjectKey, projectedMemberClass, } from '../../../language/index.js';
|
|
5
7
|
import { bindValueProgram } from '../../../language/value/compile/load.js';
|
|
6
8
|
import { validateValueProgram } from '../../../language/value/evaluate/program.js';
|
|
9
|
+
import { escapePointerToken } from '../../../language/value/syntax/pointer.js';
|
|
7
10
|
import {} from '../../model/schema.js';
|
|
8
11
|
import { fail } from '../diagnostic.js';
|
|
9
|
-
import { validateCoreEdgeSet } from './cardinality.js';
|
|
10
12
|
import { isCompiledEdge, classSatisfiesAny, } from './context.js';
|
|
13
|
+
import { sameIncidentEndpoint } from './edge.js';
|
|
11
14
|
/** Admit local Core Nodes, Properties and Edge endpoint contracts. */
|
|
12
15
|
export function validateCore(candidate, context) {
|
|
16
|
+
const resolve = (ref) => context.classes.get(Key.of(ref))?.value;
|
|
13
17
|
for (const [entryIndex, entry] of candidate.closure.entries()) {
|
|
14
18
|
const nodes = new Map();
|
|
15
19
|
for (const [index, value] of entry.definitions.core.entries()) {
|
|
@@ -31,6 +35,9 @@ export function validateCore(candidate, context) {
|
|
|
31
35
|
pointer: path,
|
|
32
36
|
});
|
|
33
37
|
}
|
|
38
|
+
checkHeldKeys(nodes.values(), (node) => nodeUniqueKeys(coveringNodeUniqueTuples(node.class.value, resolve), {
|
|
39
|
+
props: node.value.properties,
|
|
40
|
+
}), (node) => fail(node.pointer, 'Core Node holds a key another Core Node holds.'));
|
|
34
41
|
const edges = [];
|
|
35
42
|
for (const [index, value] of entry.facts.core.entries()) {
|
|
36
43
|
const path = `/closure/${entryIndex}/facts/core/${index}`;
|
|
@@ -46,14 +53,7 @@ export function validateCore(candidate, context) {
|
|
|
46
53
|
validateCoreProperties(value.properties, analysis, `${path}/properties`);
|
|
47
54
|
const source = resolveCoreEndpoint(context, entry, value.source, nodes, `${path}/source`);
|
|
48
55
|
const target = resolveCoreEndpoint(context, entry, value.target, nodes, `${path}/target`);
|
|
49
|
-
const
|
|
50
|
-
const satisfies = declaration.orientation === 'directed'
|
|
51
|
-
? endpointSatisfies(context, source, declaration.endpoints.source.accepts) &&
|
|
52
|
-
endpointSatisfies(context, target, declaration.endpoints.target.accepts)
|
|
53
|
-
: (endpointSatisfies(context, source, declaration.endpoints[0].accepts) &&
|
|
54
|
-
endpointSatisfies(context, target, declaration.endpoints[1].accepts)) ||
|
|
55
|
-
(endpointSatisfies(context, source, declaration.endpoints[1].accepts) &&
|
|
56
|
-
endpointSatisfies(context, target, declaration.endpoints[0].accepts));
|
|
56
|
+
const satisfies = coreEndpointsSatisfy(classValue.value, source, target, (endpoint, accepts) => endpointSatisfies(context, endpoint, accepts));
|
|
57
57
|
if (!satisfies)
|
|
58
58
|
fail(path, 'Core Edge endpoints do not satisfy its exact Class.');
|
|
59
59
|
edges.push({
|
|
@@ -64,28 +64,66 @@ export function validateCore(candidate, context) {
|
|
|
64
64
|
pointer: path,
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
|
-
|
|
67
|
+
checkCoreEdgeSet({
|
|
68
|
+
edges: edges.map((edge) => ({
|
|
69
|
+
edge,
|
|
70
|
+
class: Key.of(edge.value.class),
|
|
71
|
+
contract: edge.class.value,
|
|
72
|
+
source: edge.source,
|
|
73
|
+
target: edge.target,
|
|
74
|
+
})),
|
|
75
|
+
classes: entry.definitions.classes
|
|
76
|
+
.filter(isCompiledEdge)
|
|
77
|
+
.map((value) => ({ key: Key.of(value.ref), contract: value })),
|
|
78
|
+
nodes: [...nodes.values()].map(({ key, value, pointer }) => ({
|
|
79
|
+
key,
|
|
80
|
+
class: value.class,
|
|
81
|
+
pointer,
|
|
82
|
+
})),
|
|
83
|
+
satisfies: (ref, accepts) => classSatisfiesAny(context, ref, accepts),
|
|
84
|
+
keys: ({ edge }) => edgeUniqueKeys(coveringEdgeUniqueTuples(edge.class.value, resolve), {
|
|
85
|
+
source: edge.source.key,
|
|
86
|
+
target: edge.target.key,
|
|
87
|
+
props: edge.value.properties,
|
|
88
|
+
}),
|
|
89
|
+
sameIncident: sameIncidentEndpoint,
|
|
90
|
+
report: (issue) => coreEdgeFailure(issue, entryIndex),
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function coreEdgeFailure(issue, entryIndex) {
|
|
95
|
+
switch (issue.kind) {
|
|
96
|
+
case 'identity':
|
|
97
|
+
return fail(issue.edge.pointer, 'Core Edge duplicates an exact normalized Edge identity.');
|
|
98
|
+
case 'no-self':
|
|
99
|
+
return fail(issue.edge.pointer, 'Core Edge violates noSelf.');
|
|
100
|
+
case 'key':
|
|
101
|
+
return fail(issue.edge.pointer, 'Core Edge holds a key another Core Edge holds.');
|
|
102
|
+
case 'acyclic':
|
|
103
|
+
return fail(`/closure/${entryIndex}/facts/core`, 'Core Edge set violates exact-Class acyclicity.');
|
|
104
|
+
case 'degree':
|
|
105
|
+
return fail(issue.pointer, `Core degree ${issue.degree} violates Edge count ${issue.count}.`);
|
|
68
106
|
}
|
|
69
107
|
}
|
|
70
108
|
function validateCoreProperties(values, analysis, path) {
|
|
71
109
|
for (const key of Object.keys(values))
|
|
72
110
|
if (!analysis.properties.has(key))
|
|
73
|
-
fail(`${path}/${
|
|
111
|
+
fail(`${path}/${escapePointerToken(key)}`, 'Core properties contain an unknown Property key.');
|
|
74
112
|
for (const property of analysis.properties.values()) {
|
|
75
113
|
if (!Object.hasOwn(values, property.key)) {
|
|
76
114
|
if (property.declaration.required && property.declaration.auto === undefined)
|
|
77
|
-
fail(`${path}/${
|
|
115
|
+
fail(`${path}/${escapePointerToken(property.key)}`, 'Core properties omit a required Property.');
|
|
78
116
|
continue;
|
|
79
117
|
}
|
|
80
118
|
if (property.declaration.auto !== undefined)
|
|
81
|
-
fail(`${path}/${
|
|
119
|
+
fail(`${path}/${escapePointerToken(property.key)}`, 'Core properties cannot author an automatic Property.');
|
|
82
120
|
if (validateValueProgram(bindValueProgram(property.entry.values[property.declaration.value], property.entry.patterns), values[property.key]).length > 0)
|
|
83
|
-
fail(`${path}/${
|
|
121
|
+
fail(`${path}/${escapePointerToken(property.key)}`, 'Core Property value does not satisfy its exact contract.');
|
|
84
122
|
}
|
|
85
123
|
}
|
|
86
124
|
function resolveCoreEndpoint(context, entry, ref, nodes, path) {
|
|
87
125
|
if (ref.kind === 'domain')
|
|
88
|
-
return { key: 'domain' };
|
|
126
|
+
return { key: 'domain', member: { class: DOMAIN_ENDPOINT_CLASS, pointer: path } };
|
|
89
127
|
const undeclared = () => fail(path, 'Core endpoint does not name a declared local Definition.');
|
|
90
128
|
if (policyObjectOrigin(ref) !== entry.origin)
|
|
91
129
|
return undeclared();
|
|
@@ -93,7 +131,8 @@ function resolveCoreEndpoint(context, entry, ref, nodes, path) {
|
|
|
93
131
|
return nodes.get(Key.of(ref)) ?? undeclared();
|
|
94
132
|
if (!declaresProjectedMember(context, entry, ref))
|
|
95
133
|
return undeclared();
|
|
96
|
-
|
|
134
|
+
// A projected member's degree is reported at the endpoint that names it.
|
|
135
|
+
return { key: policyObjectKey(ref), member: { class: projectedMemberClass(ref), pointer: path } };
|
|
97
136
|
}
|
|
98
137
|
/** Only a projected declaration can carry a Core fact; an abstract Method is never projected. */
|
|
99
138
|
function declaresProjectedMember(context, entry, ref) {
|
|
@@ -112,12 +151,5 @@ function declaresProjectedMember(context, entry, ref) {
|
|
|
112
151
|
return declarations.some((declaration) => declaration.ref.name === ref.name);
|
|
113
152
|
}
|
|
114
153
|
function endpointSatisfies(context, endpoint, accepts) {
|
|
115
|
-
|
|
116
|
-
return classSatisfiesAny(context, endpoint.value.class, accepts);
|
|
117
|
-
if ('class' in endpoint)
|
|
118
|
-
return classSatisfiesAny(context, endpoint.class, accepts);
|
|
119
|
-
return true;
|
|
120
|
-
}
|
|
121
|
-
function escapePointer(value) {
|
|
122
|
-
return value.replaceAll('~', '~0').replaceAll('/', '~1');
|
|
154
|
+
return classSatisfiesAny(context, 'value' in endpoint ? endpoint.value.class : endpoint.member.class, accepts);
|
|
123
155
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type IncidentEndpoint } from '../../../language/class/model/edge.js';
|
|
2
2
|
import { type SemanticIndex } from './context.js';
|
|
3
|
-
/** Check Edge
|
|
3
|
+
/** Check safe Edge inheritance refinement; the wire and closure checks own the endpoints. */
|
|
4
4
|
export declare function validateEdges(context: SemanticIndex): void;
|
|
5
5
|
/** Compare undirected endpoint acceptance and cardinality contracts. */
|
|
6
6
|
export declare function sameIncidentEndpoint(left: IncidentEndpoint, right: IncidentEndpoint): boolean;
|
|
7
|
-
/** Interpret an Edge count as inclusive degree bounds. */
|
|
8
|
-
export declare function countBounds(value: EdgeCount): readonly [number, number];
|