@astrale-os/kernel-dsl 0.2.0-beta.38 → 0.2.0-beta.39
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/language/callable/composition.d.ts +13 -1
- package/dist/v1/language/callable/composition.js +13 -3
- package/dist/v1/language/value/evaluate/evaluator.js +66 -10
- package/dist/v1/schema/analysis/class.d.ts +21 -0
- package/dist/v1/schema/analysis/class.js +18 -9
- package/dist/v1/schema/compatibility/api.d.ts +2 -0
- package/dist/v1/schema/compatibility/api.js +1 -0
- package/dist/v1/schema/compatibility/comparators/callables.d.ts +28 -0
- package/dist/v1/schema/compatibility/comparators/callables.js +77 -0
- package/dist/v1/schema/compatibility/comparators/classes.d.ts +28 -0
- package/dist/v1/schema/compatibility/comparators/classes.js +96 -0
- package/dist/v1/schema/compatibility/comparators/index.d.ts +12 -0
- package/dist/v1/schema/compatibility/comparators/index.js +41 -0
- package/dist/v1/schema/compatibility/comparators/members.d.ts +4 -0
- package/dist/v1/schema/compatibility/comparators/members.js +49 -0
- package/dist/v1/schema/compatibility/comparators/values.d.ts +5 -0
- package/dist/v1/schema/compatibility/comparators/values.js +37 -0
- package/dist/v1/schema/compatibility/compare.d.ts +5 -57
- package/dist/v1/schema/compatibility/compare.js +19 -162
- package/dist/v1/schema/compatibility/coordinate.d.ts +2 -7
- package/dist/v1/schema/compatibility/coordinate.js +2 -6
- package/dist/v1/schema/compatibility/evidence.d.ts +5 -0
- package/dist/v1/schema/compatibility/evidence.js +51 -0
- package/dist/v1/schema/compatibility/fields.d.ts +6 -0
- package/dist/v1/schema/compatibility/fields.js +5 -0
- package/dist/v1/schema/compatibility/index.d.ts +5 -4
- package/dist/v1/schema/compatibility/index.js +3 -2
- package/dist/v1/schema/compatibility/legacy/index.d.ts +58 -0
- package/dist/v1/schema/compatibility/legacy/index.js +145 -0
- package/dist/v1/schema/compatibility/meaning/footprint.d.ts +7 -0
- package/dist/v1/schema/compatibility/meaning/footprint.js +57 -0
- package/dist/v1/schema/compatibility/meaning/index.d.ts +3 -0
- package/dist/v1/schema/compatibility/meaning/index.js +14 -0
- package/dist/v1/schema/compatibility/model.d.ts +96 -0
- package/dist/v1/schema/compatibility/model.js +1 -0
- package/dist/v1/schema/compatibility/references.d.ts +30 -0
- package/dist/v1/schema/compatibility/references.js +122 -0
- package/dist/v1/schema/compatibility/report.d.ts +26 -0
- package/dist/v1/schema/compatibility/report.js +100 -0
- package/dist/v1/schema/compatibility/scope.d.ts +27 -0
- package/dist/v1/schema/compatibility/scope.js +78 -0
- package/dist/v1/schema/compatibility/structure/index.d.ts +3 -0
- package/dist/v1/schema/compatibility/structure/index.js +16 -0
- package/dist/v1/schema/compatibility/structure/inheritance.d.ts +7 -0
- package/dist/v1/schema/compatibility/structure/inheritance.js +68 -0
- package/dist/v1/schema/compatibility/structure/requirements.d.ts +7 -0
- package/dist/v1/schema/compatibility/structure/requirements.js +70 -0
- package/dist/v1/schema/compatibility/subjects.d.ts +34 -0
- package/dist/v1/schema/compatibility/subjects.js +86 -0
- package/dist/v1/schema/fingerprint.d.ts +2 -2
- package/dist/v1/schema/fingerprint.js +1 -1
- package/dist/v1/schema/index.d.ts +3 -0
- package/dist/v1/schema/index.js +2 -0
- package/package.json +2 -2
- package/dist/v1/schema/compatibility/footprint.d.ts +0 -25
- package/dist/v1/schema/compatibility/footprint.js +0 -264
- package/dist/v1/schema/compatibility/meaning.d.ts +0 -44
- package/dist/v1/schema/compatibility/meaning.js +0 -234
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
import { json } from '@astrale-os/kernel-dsl/value';
|
|
2
|
-
import { Key } from '../../addressing/index.js';
|
|
3
|
-
import { compareUnicode } from '../../addressing/ordering.js';
|
|
4
|
-
import { isValueObject as isJsonObject } from '../../language/value/model/object.js';
|
|
5
|
-
import { SCHEMA_ARRAY_KEYWORDS, SCHEMA_MAP_KEYWORDS, SCHEMA_SINGLE_KEYWORDS, } from '../../language/value/syntax/keywords.js';
|
|
6
|
-
import { digestDomainSchemaBytes } from '../canonical/domain.digest.js';
|
|
7
|
-
import { deepFreeze } from '../canonical/freeze.js';
|
|
8
|
-
import { effectiveDefinition, effectiveMethod } from './context.js';
|
|
9
|
-
import { keyForDefinitionRef } from './coordinate.js';
|
|
10
|
-
import { ANNOTATION_KEYWORDS } from './fields.js';
|
|
11
|
-
/**
|
|
12
|
-
* The meaning of one coordinate is a portable value built from the fields `fields.ts` classifies
|
|
13
|
-
* as counting at the coordinate's usage level; `__tests__/fields.test.ts` proves the two agree.
|
|
14
|
-
* Comparison works on these values, so every difference can name its exact path.
|
|
15
|
-
*/
|
|
16
|
-
export function meaningForCoordinate(context, coordinate, requirement) {
|
|
17
|
-
const owner = context.schemas.get(Key.origin(coordinate.key));
|
|
18
|
-
if (owner === undefined)
|
|
19
|
-
return undefined;
|
|
20
|
-
if (coordinate.kind === 'class')
|
|
21
|
-
return classMeaning(context, coordinate, requirement)?.meaning;
|
|
22
|
-
if (coordinate.kind === 'member')
|
|
23
|
-
return memberMeaning(owner, coordinate.ref);
|
|
24
|
-
const analysis = effectiveDefinition(context, owner, coordinate.owner);
|
|
25
|
-
if (analysis === undefined)
|
|
26
|
-
return undefined;
|
|
27
|
-
if (coordinate.kind === 'property') {
|
|
28
|
-
const field = analysis.properties.get(coordinate.key);
|
|
29
|
-
return field === undefined ? undefined : propertyMeaning(field);
|
|
30
|
-
}
|
|
31
|
-
const method = effectiveMethod(analysis, coordinate.key);
|
|
32
|
-
return method === undefined ? undefined : methodMeaning(method);
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* A reference needs the Class to exist with its kind, abstractness and orientation; inheritance
|
|
36
|
-
* additionally takes on the source ancestors, class policies, data contract and, for an Edge, the
|
|
37
|
-
* endpoint and constraint contracts. A target projected onto a source requirement keeps only the
|
|
38
|
-
* ancestors the source named, so a superset satisfies it while a removal changes it.
|
|
39
|
-
*/
|
|
40
|
-
export function classMeaning(context, coordinate, onto) {
|
|
41
|
-
const owner = context.schemas.get(coordinate.ref.origin);
|
|
42
|
-
const declaration = owner?.classes[coordinate.ref.name];
|
|
43
|
-
const analysis = owner === undefined ? undefined : effectiveDefinition(context, owner, coordinate.ref);
|
|
44
|
-
if (owner === undefined || declaration === undefined || analysis === undefined)
|
|
45
|
-
return undefined;
|
|
46
|
-
const ancestors = ancestorKeys(context, coordinate.ref);
|
|
47
|
-
const requirement = Object.freeze({
|
|
48
|
-
ancestors,
|
|
49
|
-
properties: new Set(analysis.properties.keys()),
|
|
50
|
-
});
|
|
51
|
-
const meaning = {
|
|
52
|
-
coordinate: 'class',
|
|
53
|
-
level: coordinate.level,
|
|
54
|
-
kind: declaration.kind,
|
|
55
|
-
abstract: declaration.abstract,
|
|
56
|
-
...(declaration.kind === 'edge' ? { orientation: declaration.orientation } : {}),
|
|
57
|
-
...(coordinate.level === 'inherit'
|
|
58
|
-
? {
|
|
59
|
-
extends: onto === undefined
|
|
60
|
-
? ancestors
|
|
61
|
-
: onto.ancestors.filter((ancestor) => ancestors.includes(ancestor)),
|
|
62
|
-
policies: Object.fromEntries(Object.entries(declaration.policies)
|
|
63
|
-
.filter(([, ref]) => ref !== undefined)
|
|
64
|
-
.map(([role, ref]) => [role, keyForDefinitionRef(ref)])),
|
|
65
|
-
...(declaration.kind === 'node'
|
|
66
|
-
? {
|
|
67
|
-
data: analysis.data === undefined
|
|
68
|
-
? null
|
|
69
|
-
: {
|
|
70
|
-
owner: keyForDefinitionRef(analysis.data.owner),
|
|
71
|
-
declaration: analysis.data.declaration,
|
|
72
|
-
},
|
|
73
|
-
}
|
|
74
|
-
: { endpoints: declaration.endpoints, constraints: declaration.constraints }),
|
|
75
|
-
}
|
|
76
|
-
: {}),
|
|
77
|
-
};
|
|
78
|
-
return { meaning: deepFreeze(meaning), requirement };
|
|
79
|
-
}
|
|
80
|
-
export function memberMeaning(owner, ref) {
|
|
81
|
-
const meaning = memberMeaningOf(owner, ref);
|
|
82
|
-
return meaning === undefined ? undefined : deepFreeze(meaning);
|
|
83
|
-
}
|
|
84
|
-
function memberMeaningOf(owner, ref) {
|
|
85
|
-
if (ref.origin !== owner.origin)
|
|
86
|
-
return undefined;
|
|
87
|
-
switch (ref.kind) {
|
|
88
|
-
case 'function': {
|
|
89
|
-
const declaration = owner.functions[ref.name];
|
|
90
|
-
return declaration === undefined
|
|
91
|
-
? undefined
|
|
92
|
-
: { coordinate: 'function', ...callableContract(declaration) };
|
|
93
|
-
}
|
|
94
|
-
case 'policy': {
|
|
95
|
-
const declaration = owner.policies[ref.name];
|
|
96
|
-
return declaration === undefined
|
|
97
|
-
? undefined
|
|
98
|
-
: { coordinate: 'policy', expression: declaration.expression };
|
|
99
|
-
}
|
|
100
|
-
case 'view': {
|
|
101
|
-
const declaration = owner.views[ref.name];
|
|
102
|
-
return declaration === undefined
|
|
103
|
-
? undefined
|
|
104
|
-
: { coordinate: 'view', target: declaration.target };
|
|
105
|
-
}
|
|
106
|
-
case 'core': {
|
|
107
|
-
const node = owner.core.nodes[ref.name];
|
|
108
|
-
return node === undefined
|
|
109
|
-
? undefined
|
|
110
|
-
: {
|
|
111
|
-
coordinate: 'core',
|
|
112
|
-
class: node.class,
|
|
113
|
-
properties: node.properties,
|
|
114
|
-
edges: incidentCoreEdges(owner, ref.name).map((edge) => ({
|
|
115
|
-
class: edge.class,
|
|
116
|
-
source: edge.source,
|
|
117
|
-
target: edge.target,
|
|
118
|
-
properties: edge.properties,
|
|
119
|
-
})),
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
export function propertyMeaning(field) {
|
|
125
|
-
return deepFreeze({
|
|
126
|
-
coordinate: 'property',
|
|
127
|
-
owner: keyForDefinitionRef(field.owner),
|
|
128
|
-
name: field.name,
|
|
129
|
-
schema: semanticValueSchema(field.schema),
|
|
130
|
-
required: field.required,
|
|
131
|
-
...(field.auto === undefined ? {} : { auto: field.auto }),
|
|
132
|
-
...(field.state === undefined ? {} : { state: field.state }),
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
export function methodMeaning(method) {
|
|
136
|
-
return deepFreeze({
|
|
137
|
-
coordinate: 'method',
|
|
138
|
-
owner: keyForDefinitionRef(method.owner),
|
|
139
|
-
name: method.name,
|
|
140
|
-
...callableContract(method.declaration),
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Fingerprint the contract a caller compiles against, independently of its Domain revision: the
|
|
145
|
-
* exact key, the owner, dispatch and abstractness of a Method, and the semantic input and output
|
|
146
|
-
* contracts; authorization is excluded (DM-CALLABLE-FINGERPRINT). A static consumer pins this
|
|
147
|
-
* instead of a Domain revision, so a dependency release that leaves the callable contract untouched
|
|
148
|
-
* keeps every bound invocation valid.
|
|
149
|
-
*/
|
|
150
|
-
export function callableFingerprint(callable) {
|
|
151
|
-
// This digest input travels in every bound invocation and is recomputed by the Kernel; its
|
|
152
|
-
// shape is frozen, `kind` included, so a Kernel upgrade never invalidates an unchanged pin.
|
|
153
|
-
return fingerprintMeaning('owner' in callable
|
|
154
|
-
? {
|
|
155
|
-
kind: 'method',
|
|
156
|
-
key: callable.key,
|
|
157
|
-
owner: callable.owner.key,
|
|
158
|
-
...callableContract(callable),
|
|
159
|
-
}
|
|
160
|
-
: { kind: 'function', key: callable.key, ...callableContract(callable) });
|
|
161
|
-
}
|
|
162
|
-
/** The `always` fields of CALLABLE_FIELDS: dispatch shape and the semantic input and output. */
|
|
163
|
-
function callableContract(declaration) {
|
|
164
|
-
return {
|
|
165
|
-
...('static' in declaration
|
|
166
|
-
? { static: declaration.static, abstract: declaration.abstract }
|
|
167
|
-
: {}),
|
|
168
|
-
input: semanticValueSchema(declaration.input),
|
|
169
|
-
output: semanticOutput(declaration.output),
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
function semanticOutput(output) {
|
|
173
|
-
switch (output.mode) {
|
|
174
|
-
case 'value':
|
|
175
|
-
return { mode: 'value', schema: semanticValueSchema(output.schema) };
|
|
176
|
-
case 'stream':
|
|
177
|
-
return { mode: 'stream', item: semanticValueSchema(output.item) };
|
|
178
|
-
case 'binary':
|
|
179
|
-
return { mode: 'binary' };
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
/** Drop annotation keywords wherever a schema keyword nests a schema; never inside data. */
|
|
183
|
-
export function semanticValueSchema(value) {
|
|
184
|
-
if (typeof value === 'boolean')
|
|
185
|
-
return value;
|
|
186
|
-
const semantic = {};
|
|
187
|
-
for (const [keyword, entry] of Object.entries(value)) {
|
|
188
|
-
if (ANNOTATION_KEYWORDS.includes(keyword))
|
|
189
|
-
continue;
|
|
190
|
-
if (SCHEMA_SINGLE_KEYWORDS.has(keyword) && isJsonSchema(entry)) {
|
|
191
|
-
semantic[keyword] = semanticValueSchema(entry);
|
|
192
|
-
}
|
|
193
|
-
else if (SCHEMA_ARRAY_KEYWORDS.has(keyword) && Array.isArray(entry)) {
|
|
194
|
-
semantic[keyword] = entry.map((item) => isJsonSchema(item) ? semanticValueSchema(item) : item);
|
|
195
|
-
}
|
|
196
|
-
else if (SCHEMA_MAP_KEYWORDS.has(keyword) && isJsonObject(entry)) {
|
|
197
|
-
semantic[keyword] = Object.fromEntries(Object.entries(entry).map(([name, item]) => [
|
|
198
|
-
name,
|
|
199
|
-
isJsonSchema(item) ? semanticValueSchema(item) : item,
|
|
200
|
-
]));
|
|
201
|
-
}
|
|
202
|
-
else {
|
|
203
|
-
semantic[keyword] = entry;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
return semantic;
|
|
207
|
-
}
|
|
208
|
-
export function fingerprintMeaning(value) {
|
|
209
|
-
return digestDomainSchemaBytes(json.encode(value));
|
|
210
|
-
}
|
|
211
|
-
function ancestorKeys(context, ref) {
|
|
212
|
-
const seen = new Set();
|
|
213
|
-
const visit = (current) => {
|
|
214
|
-
const declaration = context.schemas.get(current.origin)?.classes[current.name];
|
|
215
|
-
if (declaration === undefined)
|
|
216
|
-
return;
|
|
217
|
-
for (const parent of declaration.extends) {
|
|
218
|
-
const key = keyForDefinitionRef(parent);
|
|
219
|
-
if (seen.has(key))
|
|
220
|
-
continue;
|
|
221
|
-
seen.add(key);
|
|
222
|
-
visit(parent);
|
|
223
|
-
}
|
|
224
|
-
};
|
|
225
|
-
visit(ref);
|
|
226
|
-
return [...seen].sort(compareUnicode);
|
|
227
|
-
}
|
|
228
|
-
function incidentCoreEdges(owner, name) {
|
|
229
|
-
return owner.core.edges.filter((edge) => (edge.source.kind === 'core' && edge.source.name === name) ||
|
|
230
|
-
(edge.target.kind === 'core' && edge.target.name === name));
|
|
231
|
-
}
|
|
232
|
-
function isJsonSchema(value) {
|
|
233
|
-
return typeof value === 'boolean' || isJsonObject(value);
|
|
234
|
-
}
|