@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
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { json } from '@astrale-os/kernel-dsl/value';
|
|
2
|
+
import { ClassKey } from '../../addressing/class-key.js';
|
|
3
|
+
import { compareUnicode } from '../../addressing/ordering.js';
|
|
4
|
+
import { PropertyKey } from '../../addressing/property-key.js';
|
|
5
|
+
/** The kinds of key fields, in canonical order: the endpoints, the slug, then the Properties. */
|
|
6
|
+
const KINDS = Object.freeze([
|
|
7
|
+
'source',
|
|
8
|
+
'target',
|
|
9
|
+
'slug',
|
|
10
|
+
'property',
|
|
11
|
+
]);
|
|
12
|
+
/** The canonical order of forms: kind by kind, a form before every form it prefixes. */
|
|
13
|
+
const compareForms = compareSequences(compareKinds);
|
|
14
|
+
/**
|
|
15
|
+
* Every form a key tuple may take, in canonical order: each nonempty set of field kinds. A Property
|
|
16
|
+
* kind stands for one Property or more, whatever their keys.
|
|
17
|
+
*/
|
|
18
|
+
export const EDGE_UNIQUE_FORMS = Object.freeze(Array.from({ length: (1 << KINDS.length) - 1 }, (_, index) => Object.freeze(KINDS.filter((_, kind) => ((index + 1) & (1 << kind)) !== 0))).sort(compareForms));
|
|
19
|
+
/** The one form a Node key tuple takes: its fields are Properties, whatever their keys. */
|
|
20
|
+
export const NODE_UNIQUE_FORMS = Object.freeze([
|
|
21
|
+
Object.freeze(['property']),
|
|
22
|
+
]);
|
|
23
|
+
/** Every form of every kind, which a backend enforcing any key tuple announces. */
|
|
24
|
+
export const UNIQUE_FORMS = Object.freeze({
|
|
25
|
+
edge: EDGE_UNIQUE_FORMS,
|
|
26
|
+
node: NODE_UNIQUE_FORMS,
|
|
27
|
+
});
|
|
28
|
+
/** No form of either kind: a backend that announces none enforces no key tuple. */
|
|
29
|
+
export const NO_UNIQUE_FORMS = Object.freeze({
|
|
30
|
+
edge: Object.freeze([]),
|
|
31
|
+
node: Object.freeze([]),
|
|
32
|
+
});
|
|
33
|
+
/** The kind of `field`. */
|
|
34
|
+
function kindOf(field) {
|
|
35
|
+
return typeof field === 'string' ? field : 'property';
|
|
36
|
+
}
|
|
37
|
+
function compareKinds(left, right) {
|
|
38
|
+
return KINDS.indexOf(left) - KINDS.indexOf(right);
|
|
39
|
+
}
|
|
40
|
+
/** The canonical order of fields: source, target, slug, then Properties by key. */
|
|
41
|
+
export function compareEdgeUniqueFields(left, right) {
|
|
42
|
+
return (compareKinds(kindOf(left), kindOf(right)) ||
|
|
43
|
+
(typeof left === 'string' || typeof right === 'string'
|
|
44
|
+
? 0
|
|
45
|
+
: compareUnicode(left.property, right.property)));
|
|
46
|
+
}
|
|
47
|
+
/** The canonical order of tuples: field by field, a tuple before every tuple it prefixes. */
|
|
48
|
+
export const compareEdgeUniqueTuples = compareSequences(compareEdgeUniqueFields);
|
|
49
|
+
/** The field `value` spells, detached, or undefined when it spells none. */
|
|
50
|
+
function edgeUniqueField(value) {
|
|
51
|
+
if (value === 'source' || value === 'target' || value === 'slug')
|
|
52
|
+
return value;
|
|
53
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
54
|
+
return undefined;
|
|
55
|
+
const keys = Object.keys(value);
|
|
56
|
+
const property = value.property;
|
|
57
|
+
return keys.length === 1 && keys[0] === 'property' && PropertyKey.is(property)
|
|
58
|
+
? Object.freeze({ property })
|
|
59
|
+
: undefined;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The tuple `value` spells, detached, or undefined when it spells none: a nonempty list of fields,
|
|
63
|
+
* distinct and in canonical order, so one set of fields has one spelling.
|
|
64
|
+
*/
|
|
65
|
+
export function edgeUniqueTuple(value) {
|
|
66
|
+
if (!Array.isArray(value) || value.length === 0)
|
|
67
|
+
return undefined;
|
|
68
|
+
const fields = [];
|
|
69
|
+
for (const item of value) {
|
|
70
|
+
const field = edgeUniqueField(item);
|
|
71
|
+
if (field === undefined)
|
|
72
|
+
return undefined;
|
|
73
|
+
if (fields.length > 0 && compareEdgeUniqueFields(fields.at(-1), field) >= 0)
|
|
74
|
+
return undefined;
|
|
75
|
+
fields.push(field);
|
|
76
|
+
}
|
|
77
|
+
return Object.freeze(fields);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The tuple the endpoints and slug `named` holds spell, in canonical order, or undefined when it
|
|
81
|
+
* holds none: the key a selector names an Edge by. A selector names no Property.
|
|
82
|
+
*/
|
|
83
|
+
export function namedEdgeUniqueTuple(named) {
|
|
84
|
+
return edgeUniqueTuple(['source', 'target', 'slug'].filter((field) => named[field] !== undefined));
|
|
85
|
+
}
|
|
86
|
+
/** The canonical order of Node tuples: Property by Property, a tuple before every one it prefixes. */
|
|
87
|
+
export const compareNodeUniqueTuples = compareSequences(compareUnicode);
|
|
88
|
+
/**
|
|
89
|
+
* The Node tuple `value` spells, detached, or undefined when it spells none: a nonempty list of
|
|
90
|
+
* Property keys, distinct and in code-point order, so one set of Properties has one spelling.
|
|
91
|
+
*/
|
|
92
|
+
export function nodeUniqueTuple(value) {
|
|
93
|
+
if (!Array.isArray(value) || value.length === 0)
|
|
94
|
+
return undefined;
|
|
95
|
+
const keys = [];
|
|
96
|
+
for (const key of value) {
|
|
97
|
+
if (!PropertyKey.is(key))
|
|
98
|
+
return undefined;
|
|
99
|
+
if (keys.length > 0 && compareUnicode(keys.at(-1), key) >= 0)
|
|
100
|
+
return undefined;
|
|
101
|
+
keys.push(key);
|
|
102
|
+
}
|
|
103
|
+
return Object.freeze(keys);
|
|
104
|
+
}
|
|
105
|
+
/** The form of `NODE_UNIQUE_FORMS` that `value` spells, or undefined when it spells none. */
|
|
106
|
+
export function nodeUniqueForm(value) {
|
|
107
|
+
return Array.isArray(value) && value.length === 1 && value[0] === 'property'
|
|
108
|
+
? NODE_UNIQUE_FORMS[0]
|
|
109
|
+
: undefined;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Whether a backend announcing `forms` for Nodes enforces the Node tuple `value` spells: every
|
|
113
|
+
* Node tuple has the one Node form. False when `value` spells no tuple.
|
|
114
|
+
*/
|
|
115
|
+
export function enforcesNodeUniqueTuple(forms, value) {
|
|
116
|
+
return forms.length > 0 && nodeUniqueTuple(value) !== undefined;
|
|
117
|
+
}
|
|
118
|
+
/** The form of `tuple`: the kinds of its fields, each once. */
|
|
119
|
+
export function edgeUniqueFormOf(tuple) {
|
|
120
|
+
const kinds = new Set(tuple.map(kindOf));
|
|
121
|
+
return EDGE_UNIQUE_FORMS.find((form) => form.length === kinds.size && form.every((kind) => kinds.has(kind)));
|
|
122
|
+
}
|
|
123
|
+
/** The form of `EDGE_UNIQUE_FORMS` that `value` spells, or undefined when it spells none. */
|
|
124
|
+
export function edgeUniqueForm(value) {
|
|
125
|
+
if (!Array.isArray(value))
|
|
126
|
+
return undefined;
|
|
127
|
+
return EDGE_UNIQUE_FORMS.find((form) => form.length === value.length && form.every((kind, index) => kind === value[index]));
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Whether a backend announcing `forms` enforces the tuple `value` spells: its form is one of them.
|
|
131
|
+
* False when `value` spells no tuple, so a tuple is never taken as enforced by mistake.
|
|
132
|
+
*/
|
|
133
|
+
export function enforcesEdgeUniqueTuple(forms, value) {
|
|
134
|
+
const tuple = edgeUniqueTuple(value);
|
|
135
|
+
if (tuple === undefined)
|
|
136
|
+
return false;
|
|
137
|
+
const form = edgeUniqueFormOf(tuple);
|
|
138
|
+
return forms.some((candidate) => compareForms(candidate, form) === 0);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Whether a Property may be a key field (D-S1): a single-kind scalar by its ordering facet, a
|
|
142
|
+
* string, number, boolean or instant, that no automatic program writes.
|
|
143
|
+
*/
|
|
144
|
+
export function keyableProperty(ordering, auto) {
|
|
145
|
+
return ordering !== undefined && auto === undefined;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* The values of the fields of `tuple` on `edge`, in order, or undefined when one of them is absent,
|
|
149
|
+
* so that an Edge without a slug or without a Property never collides.
|
|
150
|
+
*/
|
|
151
|
+
export function edgeUniqueValues(tuple, edge) {
|
|
152
|
+
return keyValues(tuple, (field) => typeof field === 'string' ? edge[field] : propertyOf(edge.props, field.property));
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* The value `edge` takes under `tuple`, the canonical JSON of the values of its fields, or
|
|
156
|
+
* undefined when one of them is absent: two distinct Edges of the Classes a tuple covers collide
|
|
157
|
+
* exactly when they take one value. Endpoints compare by NodeId, slugs by exact text and
|
|
158
|
+
* Properties by canonical Value.
|
|
159
|
+
*/
|
|
160
|
+
export function edgeUniqueValue(tuple, edge) {
|
|
161
|
+
return serialized(edgeUniqueValues(tuple, edge));
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* The values of the Properties of `tuple` on `node`, in order, or undefined when one of them is
|
|
165
|
+
* absent, so that a Node without one of them never collides, like NULL in an SQL UNIQUE.
|
|
166
|
+
*/
|
|
167
|
+
export function nodeUniqueValues(tuple, node) {
|
|
168
|
+
return keyValues(tuple, (key) => propertyOf(node.props, key));
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* The value `node` takes under `tuple`, the canonical JSON of the values of its Properties, or
|
|
172
|
+
* undefined when one of them is absent: two distinct Nodes of the Classes a tuple covers collide
|
|
173
|
+
* exactly when they take one value. Properties compare by canonical Value, nothing normalized.
|
|
174
|
+
*/
|
|
175
|
+
export function nodeUniqueValue(tuple, node) {
|
|
176
|
+
return serialized(nodeUniqueValues(tuple, node));
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* The tuples covering `candidate`: those it and each of its ancestors declare, each with the Class
|
|
180
|
+
* declaring it, ancestors found by `resolve`. A descendant never restates them.
|
|
181
|
+
*/
|
|
182
|
+
export function coveringEdgeUniqueTuples(candidate, resolve) {
|
|
183
|
+
return coveringTuples(candidate, resolve);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* The Node tuples covering `candidate`: those it and each of its ancestors declare, each with the
|
|
187
|
+
* Class declaring it, ancestors found by `resolve`. A descendant never restates them.
|
|
188
|
+
*/
|
|
189
|
+
export function coveringNodeUniqueTuples(candidate, resolve) {
|
|
190
|
+
return coveringTuples(candidate, resolve);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* The keys `edge` holds: its value under each tuple of `tuples`, tagged by the Class declaring the
|
|
194
|
+
* tuple, so two Edges collide exactly when they hold one key.
|
|
195
|
+
*/
|
|
196
|
+
export function edgeUniqueKeys(tuples, edge) {
|
|
197
|
+
return heldKeys(tuples, (fields) => edgeUniqueValue(fields, edge));
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* The keys `node` holds: its value under each tuple of `tuples`, tagged by the Class declaring the
|
|
201
|
+
* tuple, so two Nodes collide exactly when they hold one key.
|
|
202
|
+
*/
|
|
203
|
+
export function nodeUniqueKeys(tuples, node) {
|
|
204
|
+
return heldKeys(tuples, (fields) => nodeUniqueValue(fields, node));
|
|
205
|
+
}
|
|
206
|
+
/** The values `read` gives the fields of `tuple`, in order, or undefined when one is absent. */
|
|
207
|
+
function keyValues(tuple, read) {
|
|
208
|
+
const values = [];
|
|
209
|
+
for (const field of tuple) {
|
|
210
|
+
const value = read(field);
|
|
211
|
+
if (value === undefined)
|
|
212
|
+
return undefined;
|
|
213
|
+
values.push(value);
|
|
214
|
+
}
|
|
215
|
+
return Object.freeze(values);
|
|
216
|
+
}
|
|
217
|
+
/** The value of the Property `key` in `props`, or undefined when it is absent. */
|
|
218
|
+
function propertyOf(props, key) {
|
|
219
|
+
return Object.hasOwn(props, key) ? props[key] : undefined;
|
|
220
|
+
}
|
|
221
|
+
/** The canonical JSON of a key's values, or undefined when it has none. */
|
|
222
|
+
function serialized(values) {
|
|
223
|
+
return values === undefined ? undefined : json.serializeAdmitted(values);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* The tuples `candidate` and its ancestors declare, each with its declarer. Only ancestors of the
|
|
227
|
+
* candidate's kind are visited, so every tuple is of that kind.
|
|
228
|
+
*/
|
|
229
|
+
function coveringTuples(candidate, resolve) {
|
|
230
|
+
const tuples = [];
|
|
231
|
+
const seen = new Set();
|
|
232
|
+
const visit = (value) => {
|
|
233
|
+
if (seen.has(value) || value.kind !== candidate.kind)
|
|
234
|
+
return;
|
|
235
|
+
seen.add(value);
|
|
236
|
+
for (const fields of value.unique ?? [])
|
|
237
|
+
tuples.push(Object.freeze({ class: ClassKey.of(value.ref), fields }));
|
|
238
|
+
for (const ref of value.extends) {
|
|
239
|
+
const parent = resolve(ref);
|
|
240
|
+
if (parent !== undefined)
|
|
241
|
+
visit(parent);
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
visit(candidate);
|
|
245
|
+
return Object.freeze(tuples);
|
|
246
|
+
}
|
|
247
|
+
/** The keys a fact holds under `tuples`, its value under each tagged by the declaring Class. */
|
|
248
|
+
function heldKeys(tuples, valueOf) {
|
|
249
|
+
return tuples.flatMap(({ class: declaring, fields }) => {
|
|
250
|
+
const value = valueOf(fields);
|
|
251
|
+
return value === undefined ? [] : [JSON.stringify([declaring, fields, value])];
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
/** The lexicographic order of sequences by `compare`, a sequence before every one it prefixes. */
|
|
255
|
+
function compareSequences(compare) {
|
|
256
|
+
return (left, right) => {
|
|
257
|
+
for (let index = 0; index < Math.min(left.length, right.length); index += 1) {
|
|
258
|
+
const order = compare(left[index], right[index]);
|
|
259
|
+
if (order !== 0)
|
|
260
|
+
return order;
|
|
261
|
+
}
|
|
262
|
+
return left.length - right.length;
|
|
263
|
+
};
|
|
264
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { ClassRef } from '../../addressing/index.js';
|
|
2
|
+
import type { EdgeContract, EdgeCount, EdgeEndpointBase, IncidentEndpoint } from '../class/model/edge.js';
|
|
3
|
+
/**
|
|
4
|
+
* The Class of the owning Domain's Node: every Domain principal is a Node of the final Kernel
|
|
5
|
+
* `Domain` Class, so a Core Edge that names the Domain must accept that Class at that endpoint.
|
|
6
|
+
*/
|
|
7
|
+
export declare const DOMAIN_ENDPOINT_CLASS: ClassRef;
|
|
8
|
+
/** One endpoint of a Core Edge: a Core Node, a projected member or the owning Domain. */
|
|
9
|
+
export interface CoreFactEndpoint {
|
|
10
|
+
readonly key: string;
|
|
11
|
+
/**
|
|
12
|
+
* Set on a projected member and on the owning Domain: the Kernel Class it is a Node of, and where
|
|
13
|
+
* a breach of its degree is reported.
|
|
14
|
+
*/
|
|
15
|
+
readonly member?: {
|
|
16
|
+
readonly class: ClassRef;
|
|
17
|
+
readonly pointer: string;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/** One Core Edge whose endpoints satisfy its exact Class. */
|
|
21
|
+
export interface CoreFactEdge<Edge> {
|
|
22
|
+
readonly edge: Edge;
|
|
23
|
+
/** The exact Class's key, as `CoreEdgeSet.classes` names it. */
|
|
24
|
+
readonly class: string;
|
|
25
|
+
readonly contract: EdgeContract;
|
|
26
|
+
readonly source: CoreFactEndpoint;
|
|
27
|
+
readonly target: CoreFactEndpoint;
|
|
28
|
+
}
|
|
29
|
+
/** One declared Core Node. It proves its own complete degree, so both bounds hold. */
|
|
30
|
+
export interface CoreDegreeSubject {
|
|
31
|
+
readonly key: string;
|
|
32
|
+
readonly class: ClassRef;
|
|
33
|
+
readonly pointer: string;
|
|
34
|
+
}
|
|
35
|
+
export interface CoreEdgeSet<Edge> {
|
|
36
|
+
readonly edges: readonly CoreFactEdge<Edge>[];
|
|
37
|
+
/** The local Edge Classes, in the order their slices are checked. */
|
|
38
|
+
readonly classes: readonly {
|
|
39
|
+
readonly key: string;
|
|
40
|
+
readonly contract: EdgeContract & {
|
|
41
|
+
readonly abstract: boolean;
|
|
42
|
+
};
|
|
43
|
+
}[];
|
|
44
|
+
readonly nodes: readonly CoreDegreeSubject[];
|
|
45
|
+
readonly satisfies: (ref: ClassRef, accepts: readonly ClassRef[]) => boolean;
|
|
46
|
+
/** The keys an Edge holds under the tuples covering its Class. */
|
|
47
|
+
readonly keys: (edge: CoreFactEdge<Edge>) => readonly string[];
|
|
48
|
+
/** Whether an undirected Edge's two endpoints state one contract, counted once. */
|
|
49
|
+
readonly sameIncident: (left: IncidentEndpoint, right: IncidentEndpoint) => boolean;
|
|
50
|
+
readonly report: (issue: CoreEdgeIssue<Edge>) => void;
|
|
51
|
+
}
|
|
52
|
+
export type CoreEdgeIssue<Edge> = {
|
|
53
|
+
readonly kind: 'identity';
|
|
54
|
+
readonly edge: Edge;
|
|
55
|
+
readonly previous: Edge;
|
|
56
|
+
} | {
|
|
57
|
+
readonly kind: 'no-self';
|
|
58
|
+
readonly edge: Edge;
|
|
59
|
+
} | {
|
|
60
|
+
readonly kind: 'key';
|
|
61
|
+
readonly edge: Edge;
|
|
62
|
+
readonly previous: Edge;
|
|
63
|
+
} | {
|
|
64
|
+
readonly kind: 'acyclic';
|
|
65
|
+
readonly class: string;
|
|
66
|
+
} | {
|
|
67
|
+
readonly kind: 'degree';
|
|
68
|
+
readonly pointer: string;
|
|
69
|
+
readonly endpoint: EdgeEndpointBase;
|
|
70
|
+
readonly count: EdgeCount;
|
|
71
|
+
readonly degree: number;
|
|
72
|
+
};
|
|
73
|
+
/** Whether the endpoints satisfy the contract: in order when directed, in either order when not. */
|
|
74
|
+
export declare function coreEndpointsSatisfy<Endpoint>(contract: EdgeContract, source: Endpoint, target: Endpoint, satisfies: (endpoint: Endpoint, accepts: readonly ClassRef[]) => boolean): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Report each fact that holds a key an earlier fact holds, with the first holder of that key. Core
|
|
77
|
+
* facts have no slug, so only tuples of endpoints and Properties bind them (DV-NODE-UNIQUE,
|
|
78
|
+
* DV-EDGE-UNIQUE); Activation checks them against stored data.
|
|
79
|
+
*/
|
|
80
|
+
export declare function checkHeldKeys<Fact>(facts: Iterable<Fact>, keys: (fact: Fact) => readonly string[], report: (fact: Fact, previous: Fact) => void): void;
|
|
81
|
+
/**
|
|
82
|
+
* Check normalized Edge identity, noSelf, keys, and the acyclicity and Core degrees of each exact
|
|
83
|
+
* concrete Edge Class over its own Edges.
|
|
84
|
+
*/
|
|
85
|
+
export declare function checkCoreEdgeSet<Edge>(set: CoreEdgeSet<Edge>): void;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { compareUnicode } from '../../addressing/ordering.js';
|
|
2
|
+
import { countBounds, hasDirectedCycle, KERNEL_ORIGIN } from '../class/inheritance.js';
|
|
3
|
+
/*
|
|
4
|
+
* The Core fact rules that authored and compiled admission share. Each admission resolves its own
|
|
5
|
+
* Core Nodes and Edges, then reports every issue under its own codes, messages and pointers.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* The Class of the owning Domain's Node: every Domain principal is a Node of the final Kernel
|
|
9
|
+
* `Domain` Class, so a Core Edge that names the Domain must accept that Class at that endpoint.
|
|
10
|
+
*/
|
|
11
|
+
export const DOMAIN_ENDPOINT_CLASS = Object.freeze({
|
|
12
|
+
origin: KERNEL_ORIGIN,
|
|
13
|
+
kind: 'class',
|
|
14
|
+
name: 'Domain',
|
|
15
|
+
});
|
|
16
|
+
/** Whether the endpoints satisfy the contract: in order when directed, in either order when not. */
|
|
17
|
+
export function coreEndpointsSatisfy(contract, source, target, satisfies) {
|
|
18
|
+
if (contract.orientation === 'directed') {
|
|
19
|
+
const { endpoints } = contract;
|
|
20
|
+
return (satisfies(source, endpoints.source.accepts) && satisfies(target, endpoints.target.accepts));
|
|
21
|
+
}
|
|
22
|
+
const [first, second] = contract.endpoints;
|
|
23
|
+
return ((satisfies(source, first.accepts) && satisfies(target, second.accepts)) ||
|
|
24
|
+
(satisfies(source, second.accepts) && satisfies(target, first.accepts)));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Report each fact that holds a key an earlier fact holds, with the first holder of that key. Core
|
|
28
|
+
* facts have no slug, so only tuples of endpoints and Properties bind them (DV-NODE-UNIQUE,
|
|
29
|
+
* DV-EDGE-UNIQUE); Activation checks them against stored data.
|
|
30
|
+
*/
|
|
31
|
+
export function checkHeldKeys(facts, keys, report) {
|
|
32
|
+
const holders = new Map();
|
|
33
|
+
for (const fact of facts) {
|
|
34
|
+
const held = keys(fact);
|
|
35
|
+
const holder = held.find((key) => holders.has(key));
|
|
36
|
+
if (holder !== undefined)
|
|
37
|
+
report(fact, holders.get(holder));
|
|
38
|
+
for (const key of held)
|
|
39
|
+
if (!holders.has(key))
|
|
40
|
+
holders.set(key, fact);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Check normalized Edge identity, noSelf, keys, and the acyclicity and Core degrees of each exact
|
|
45
|
+
* concrete Edge Class over its own Edges.
|
|
46
|
+
*/
|
|
47
|
+
export function checkCoreEdgeSet(set) {
|
|
48
|
+
const identities = new Map();
|
|
49
|
+
const slices = new Map(set.classes.map(({ key }) => [key, []]));
|
|
50
|
+
for (const fact of set.edges) {
|
|
51
|
+
const [source, target] = fact.contract.orientation === 'undirected' &&
|
|
52
|
+
compareUnicode(fact.source.key, fact.target.key) > 0
|
|
53
|
+
? [fact.target.key, fact.source.key]
|
|
54
|
+
: [fact.source.key, fact.target.key];
|
|
55
|
+
const identity = `${fact.class}\u0000${source}\u0000${target}`;
|
|
56
|
+
const previous = identities.get(identity);
|
|
57
|
+
if (previous !== undefined)
|
|
58
|
+
set.report({ kind: 'identity', edge: fact.edge, previous });
|
|
59
|
+
else
|
|
60
|
+
identities.set(identity, fact.edge);
|
|
61
|
+
slices.get(fact.class)?.push(fact);
|
|
62
|
+
if (fact.contract.constraints.noSelf === true && fact.source.key === fact.target.key)
|
|
63
|
+
set.report({ kind: 'no-self', edge: fact.edge });
|
|
64
|
+
}
|
|
65
|
+
checkHeldKeys(set.edges, set.keys, (fact, previous) => set.report({ kind: 'key', edge: fact.edge, previous: previous.edge }));
|
|
66
|
+
for (const { key, contract } of set.classes) {
|
|
67
|
+
// No Edge is of an abstract Class exactly, so it bounds no degree and closes no cycle of its
|
|
68
|
+
// own: each concrete descendant carries the counts it refines, over its own Edges.
|
|
69
|
+
if (contract.abstract)
|
|
70
|
+
continue;
|
|
71
|
+
const slice = slices.get(key);
|
|
72
|
+
if (contract.constraints.acyclic === true && hasDirectedCycle(slice))
|
|
73
|
+
set.report({ kind: 'acyclic', class: key });
|
|
74
|
+
checkDegrees(set, contract, slice);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function checkDegrees(set, contract, slice) {
|
|
78
|
+
for (const subject of degreeSubjects(set.nodes, slice)) {
|
|
79
|
+
const check = (endpoint, count, degree) => {
|
|
80
|
+
const [minimum, maximum] = countBounds(count);
|
|
81
|
+
if (degree > maximum || (degree < minimum && subject.minimum))
|
|
82
|
+
set.report({ kind: 'degree', pointer: subject.pointer, endpoint, count, degree });
|
|
83
|
+
};
|
|
84
|
+
if (contract.orientation === 'directed') {
|
|
85
|
+
const { source, target } = contract.endpoints;
|
|
86
|
+
if (set.satisfies(subject.class, source.accepts))
|
|
87
|
+
check(source, source.outgoing, slice.filter((edge) => edge.source.key === subject.key).length);
|
|
88
|
+
if (set.satisfies(subject.class, target.accepts))
|
|
89
|
+
check(target, target.incoming, slice.filter((edge) => edge.target.key === subject.key).length);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const [first, second] = contract.endpoints;
|
|
93
|
+
const degree = slice.filter((edge) => edge.source.key === subject.key || edge.target.key === subject.key).length;
|
|
94
|
+
if (set.satisfies(subject.class, first.accepts))
|
|
95
|
+
check(first, first.incident, degree);
|
|
96
|
+
if (!set.sameIncident(first, second) && set.satisfies(subject.class, second.accepts))
|
|
97
|
+
check(second, second.incident, degree);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Every declared Core Node proves its own complete degree, so both bounds hold. A projected member,
|
|
102
|
+
* and the owning Domain, is only named by the Edges that reach it: the Domain may also create
|
|
103
|
+
* ordinary Edges of the same Class against it, so a minimum is unprovable here and only the maximum
|
|
104
|
+
* is enforced.
|
|
105
|
+
*/
|
|
106
|
+
function degreeSubjects(nodes, slice) {
|
|
107
|
+
const subjects = new Map(nodes.map((node) => [node.key, { ...node, minimum: true }]));
|
|
108
|
+
for (const edge of slice) {
|
|
109
|
+
for (const { key, member } of [edge.source, edge.target]) {
|
|
110
|
+
if (member === undefined || subjects.has(key))
|
|
111
|
+
continue;
|
|
112
|
+
subjects.set(key, { key, class: member.class, pointer: member.pointer, minimum: false });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return subjects.values();
|
|
116
|
+
}
|
|
@@ -18,3 +18,8 @@ export declare const name: Readonly<{
|
|
|
18
18
|
}>;
|
|
19
19
|
/** The common source and compiled grammar for a name displayed exactly as authored. */
|
|
20
20
|
export declare function isDomainNameText(value: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* The same grammar as a portable pattern: no control character, and neither first nor last a
|
|
23
|
+
* character `trim` removes, spelled out since `\s` differs between regular expression engines.
|
|
24
|
+
*/
|
|
25
|
+
export declare const DOMAIN_NAME_TEXT_PATTERN: RegExp;
|
|
@@ -22,3 +22,10 @@ const DOMAIN_NAME_CONTROL = /[\u0000-\u001f\u007f-\u009f\u2028\u2029]/u;
|
|
|
22
22
|
export function isDomainNameText(value) {
|
|
23
23
|
return value.trim() === value && !DOMAIN_NAME_CONTROL.test(value);
|
|
24
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* The same grammar as a portable pattern: no control character, and neither first nor last a
|
|
27
|
+
* character `trim` removes, spelled out since `\s` differs between regular expression engines.
|
|
28
|
+
*/
|
|
29
|
+
export const DOMAIN_NAME_TEXT_PATTERN =
|
|
30
|
+
// oxlint-disable-next-line no-control-regex
|
|
31
|
+
/^(?:[^\u0000-\u001f\u007f-\u009f\u0020\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff](?:[^\u0000-\u001f\u007f-\u009f\u2028\u2029]*[^\u0000-\u001f\u007f-\u009f\u0020\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff])?)?$/u;
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Freeze `value` and every object it reaches, in place. An object already frozen is taken as frozen
|
|
3
|
+
* through, so a value built from frozen parts is frozen without walking them again.
|
|
4
|
+
*/
|
|
1
5
|
export function deepFreeze(value) {
|
|
2
6
|
if (value === null || typeof value !== 'object' || Object.isFrozen(value)) {
|
|
3
7
|
return value;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { admissionInputFields, isAdmissionMaxAge, MAXIMUM_ADMISSION_AGE_SECONDS, } from './callable/admission.js';
|
|
1
2
|
export { isMethodExecutable } from './callable/executable.js';
|
|
2
3
|
export { isBinaryInput } from './callable/model/callable.js';
|
|
3
4
|
export type { ClassRef, CoreRef, DefinitionBase, DefinitionKey, DefinitionRef, FunctionRef, MethodKey, PolicyRef, PropertyKey, ViewRef, } from '../addressing/index.js';
|
|
@@ -6,6 +7,7 @@ export type { JsonSchema as ValueSchema, JsonSchemaObject as ValueSchemaObject,
|
|
|
6
7
|
export type { OrderingKind } from './value/ordering.js';
|
|
7
8
|
export type { ValueProgram } from './value/compile/model.js';
|
|
8
9
|
export { valueProgramIncludes } from './value/inclusion/includes.js';
|
|
10
|
+
export { isInstantValue } from './value/model/instant.js';
|
|
9
11
|
export { stateMachine } from './state/index.js';
|
|
10
12
|
export type { EventOf, StateMachine, StateOf, StateTopology } from './state/index.js';
|
|
11
13
|
export type * from './callable/model/callable.js';
|
|
@@ -13,8 +15,11 @@ export type * from './callable/resolved.js';
|
|
|
13
15
|
export type * from './class/model/class.js';
|
|
14
16
|
export type { DataDefinition, DataFacet, MediaType } from './class/model/data.js';
|
|
15
17
|
export type * from './class/model/edge.js';
|
|
16
|
-
export {
|
|
17
|
-
export
|
|
18
|
+
export { admitsForeignSubclass, inheritanceOf } from './class/inheritance.js';
|
|
19
|
+
export { edgeLifetimes, lifetimeScope } from './class/lifetime.js';
|
|
20
|
+
export type { LifetimeScope } from './class/lifetime.js';
|
|
21
|
+
export { EDGE_UNIQUE_FORMS, NODE_UNIQUE_FORMS, NO_UNIQUE_FORMS, UNIQUE_FORMS, compareEdgeUniqueFields, compareEdgeUniqueTuples, compareNodeUniqueTuples, coveringEdgeUniqueTuples, coveringNodeUniqueTuples, edgeUniqueForm, edgeUniqueFormOf, edgeUniqueKeys, edgeUniqueTuple, edgeUniqueValue, edgeUniqueValues, enforcesEdgeUniqueTuple, enforcesNodeUniqueTuple, keyableProperty, namedEdgeUniqueTuple, nodeUniqueForm, nodeUniqueKeys, nodeUniqueTuple, nodeUniqueValue, nodeUniqueValues, } from './class/unique.js';
|
|
22
|
+
export type { DeclaredEdgeUniqueTuple, DeclaredNodeUniqueTuple, EdgeUniqueFacts, NodeUniqueFacts, UniqueForms, } from './class/unique.js';
|
|
18
23
|
export type * from './class/model/property.js';
|
|
19
24
|
export type * from './class/resolved.js';
|
|
20
25
|
export type * from './class/facets.js';
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
export { admissionInputFields, isAdmissionMaxAge, MAXIMUM_ADMISSION_AGE_SECONDS, } from './callable/admission.js';
|
|
1
2
|
export { isMethodExecutable } from './callable/executable.js';
|
|
2
3
|
export { isBinaryInput } from './callable/model/callable.js';
|
|
3
4
|
export { valueProgramIncludes } from './value/inclusion/includes.js';
|
|
5
|
+
export { isInstantValue } from './value/model/instant.js';
|
|
4
6
|
export { stateMachine } from './state/index.js';
|
|
5
|
-
export {
|
|
7
|
+
export { admitsForeignSubclass, inheritanceOf } from './class/inheritance.js';
|
|
8
|
+
export { edgeLifetimes, lifetimeScope } from './class/lifetime.js';
|
|
9
|
+
export { EDGE_UNIQUE_FORMS, NODE_UNIQUE_FORMS, NO_UNIQUE_FORMS, UNIQUE_FORMS, compareEdgeUniqueFields, compareEdgeUniqueTuples, compareNodeUniqueTuples, coveringEdgeUniqueTuples, coveringNodeUniqueTuples, edgeUniqueForm, edgeUniqueFormOf, edgeUniqueKeys, edgeUniqueTuple, edgeUniqueValue, edgeUniqueValues, enforcesEdgeUniqueTuple, enforcesNodeUniqueTuple, keyableProperty, namedEdgeUniqueTuple, nodeUniqueForm, nodeUniqueKeys, nodeUniqueTuple, nodeUniqueValue, nodeUniqueValues, } from './class/unique.js';
|
|
6
10
|
export { PropertyValues } from './class/property-values.js';
|
|
7
11
|
export { isClassRuleChecks, policyVariableClass, policyVariableSelector, policyObjectKey, policyObjectOrigin, projectedMemberClass, } from './policy/model/policy.js';
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The limits of the V1 language, each defined once: every check of a source Schema, a Bundle or a
|
|
3
|
+
* compiled closure reads its bound here. Every limit is inclusive: a count equal to it is
|
|
4
|
+
* accepted, one more is refused. `schema.limits` publishes this object, and each rule of
|
|
5
|
+
* `schema.RULES` and `schema.values.RULES` that enforces some of them names them in `limits`.
|
|
6
|
+
*/
|
|
7
|
+
export declare const limits: Readonly<{
|
|
8
|
+
/** Bounds of the dependency graph of one Domain (`DV_DEPENDENCY_LIMITS`). */
|
|
9
|
+
dependency: Readonly<{
|
|
10
|
+
/** Direct dependencies one Domain declares. */
|
|
11
|
+
direct: 32;
|
|
12
|
+
/** Domains of a dependency closure, the Domain itself included. */
|
|
13
|
+
closure: 256;
|
|
14
|
+
/** Dependencies on the longest chain from a Domain: a direct dependency is at depth 1. */
|
|
15
|
+
depth: 32;
|
|
16
|
+
}>;
|
|
17
|
+
/** Bounds of one I-Regexp in a value schema (`VS_REGEX_PORTABLE`), as RFC 9485 §8 allows. */
|
|
18
|
+
regexp: Readonly<{
|
|
19
|
+
/** Code points of one source. */
|
|
20
|
+
maxCodePoints: 4096;
|
|
21
|
+
/** Groups nested in one another in one source. */
|
|
22
|
+
maxNesting: 32;
|
|
23
|
+
/** The greatest bound of a counted repetition `{n}` or `{n,m}`. */
|
|
24
|
+
maxRepeat: 1000;
|
|
25
|
+
/** States of one compiled machine; the counted-run form never expands and is not bounded. */
|
|
26
|
+
maxStates: 10000;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* Bounds of the Policy language. A named Policy is measured once normalized and once each
|
|
30
|
+
* composition is expanded into the Policies it names; a check tree, the checks of a callable or
|
|
31
|
+
* of a Node Class rule, once normalized (`PL_BUDGET`). The structure bounds the others
|
|
32
|
+
* (`STRUCTURE_MAXIMUM`).
|
|
33
|
+
*/
|
|
34
|
+
policy: Readonly<{
|
|
35
|
+
/**
|
|
36
|
+
* Levels of a Policy pattern: an Edge or sameNode is one, and each allOf, anyOf, exists and
|
|
37
|
+
* composition adds one.
|
|
38
|
+
*/
|
|
39
|
+
patternDepth: 4;
|
|
40
|
+
/**
|
|
41
|
+
* Branches of a Policy's normal form: an anyOf adds those of its operands, an allOf multiplies
|
|
42
|
+
* them.
|
|
43
|
+
*/
|
|
44
|
+
normalizedBranches: 8;
|
|
45
|
+
/** Nodes one exists declares. */
|
|
46
|
+
variablesPerExists: 4;
|
|
47
|
+
/** Graph predicates, Edges and sameNode equalities, of one normalized branch. */
|
|
48
|
+
edgePredicates: 6;
|
|
49
|
+
/** The greatest bound of a repeated Edge. */
|
|
50
|
+
repetition: 3;
|
|
51
|
+
/** Domains a Policy names: its own, and the origin of every Class and object it references. */
|
|
52
|
+
referencedDomains: 4;
|
|
53
|
+
/** Levels of a check tree: a check or sameNode is one, and each allOf and anyOf adds one. */
|
|
54
|
+
checkDepth: 4;
|
|
55
|
+
/** Branches of a check tree: an anyOf adds those of its operands, an allOf multiplies them. */
|
|
56
|
+
checkBranches: 8;
|
|
57
|
+
/** Checks and sameNode equalities of a check tree. */
|
|
58
|
+
checkLeaves: 8;
|
|
59
|
+
}>;
|
|
60
|
+
}>;
|
|
61
|
+
/** A limit by its key in `limits`, `<group>.<name>`: `policy.patternDepth`. */
|
|
62
|
+
export type LimitKey = {
|
|
63
|
+
readonly [Group in keyof typeof limits & string]: `${Group}.${keyof (typeof limits)[Group] & string}`;
|
|
64
|
+
}[keyof typeof limits & string];
|