@astrale-os/kernel-dsl 0.2.0-beta.47 → 0.2.0-beta.49
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/patterns.d.ts +0 -5
- package/dist/v1/addressing/patterns.js +5 -5
- package/dist/v1/builder/callable/authoring.d.ts +1 -1
- package/dist/v1/builder/class/authoring.d.ts +0 -12
- package/dist/v1/builder/class/property.d.ts +1 -1
- package/dist/v1/builder/index.d.ts +1 -1
- package/dist/v1/builder/lowering/callable.d.ts +2 -1
- package/dist/v1/builder/lowering/core.d.ts +3 -2
- package/dist/v1/builder/lowering/schema/compile.js +14 -1
- package/dist/v1/builder/lowering/value/zod.d.ts +3 -2
- package/dist/v1/builder/lowering/view.d.ts +2 -1
- package/dist/v1/builder/schema/define.d.ts +4 -2
- package/dist/v1/builder/schema/handle.d.ts +2 -1
- package/dist/v1/builder/schema/input.d.ts +8 -0
- package/dist/v1/builder/schema/projection/callable.d.ts +51 -0
- package/dist/v1/builder/schema/projection/callable.js +1 -0
- package/dist/v1/builder/schema/projection/class.d.ts +89 -0
- package/dist/v1/builder/schema/projection/class.js +1 -0
- package/dist/v1/builder/schema/projection/core-input.d.ts +32 -0
- package/dist/v1/builder/schema/projection/core-input.js +1 -0
- package/dist/v1/builder/schema/projection/domain.d.ts +59 -0
- package/dist/v1/builder/schema/projection/domain.js +1 -0
- package/dist/v1/builder/schema/projection/identity.d.ts +39 -0
- package/dist/v1/builder/schema/projection/identity.js +1 -0
- package/dist/v1/builder/schema/projection/model.d.ts +59 -0
- package/dist/v1/builder/schema/projection/model.js +1 -0
- package/dist/v1/builder/schema/projection/property.d.ts +32 -0
- package/dist/v1/builder/schema/projection/property.js +1 -0
- package/dist/v1/builder/schema/projection/resolved-class.d.ts +76 -0
- package/dist/v1/builder/schema/projection/resolved-class.js +1 -0
- package/dist/v1/builder/schema/projection.d.ts +4 -375
- package/dist/v1/bundle/structure.d.ts +2 -1
- package/dist/v1/compiled/admission/accept.d.ts +1 -1
- package/dist/v1/compiled/admission/accept.js +7 -1005
- package/dist/v1/compiled/admission/closure.d.ts +3 -0
- package/dist/v1/compiled/admission/closure.js +173 -0
- package/dist/v1/compiled/admission/diagnostic.d.ts +7 -0
- package/dist/v1/compiled/admission/diagnostic.js +13 -0
- package/dist/v1/compiled/admission/revision.js +2 -0
- package/dist/v1/compiled/admission/semantics/cardinality.d.ts +5 -0
- package/dist/v1/compiled/admission/semantics/cardinality.js +113 -0
- package/dist/v1/compiled/admission/semantics/class.d.ts +5 -0
- package/dist/v1/compiled/admission/semantics/class.js +125 -0
- package/dist/v1/compiled/admission/semantics/context.d.ts +60 -0
- package/dist/v1/compiled/admission/semantics/context.js +81 -0
- package/dist/v1/compiled/admission/semantics/core.d.ts +35 -0
- package/dist/v1/compiled/admission/semantics/core.js +123 -0
- package/dist/v1/compiled/admission/semantics/edge.d.ts +8 -0
- package/dist/v1/compiled/admission/semantics/edge.js +89 -0
- package/dist/v1/compiled/admission/semantics/policy/admit.d.ts +4 -0
- package/dist/v1/compiled/admission/semantics/policy/admit.js +57 -0
- package/dist/v1/compiled/admission/semantics/policy/callable.d.ts +5 -0
- package/dist/v1/compiled/admission/semantics/policy/callable.js +72 -0
- package/dist/v1/compiled/admission/semantics/policy/contracts.d.ts +24 -0
- package/dist/v1/compiled/admission/semantics/policy/contracts.js +45 -0
- package/dist/v1/compiled/admission/semantics/policy/equality.d.ts +8 -0
- package/dist/v1/compiled/admission/semantics/policy/equality.js +27 -0
- package/dist/v1/compiled/admission/semantics/policy/measure.d.ts +9 -0
- package/dist/v1/compiled/admission/semantics/policy/measure.js +81 -0
- package/dist/v1/compiled/admission/semantics/policy/parity.d.ts +4 -0
- package/dist/v1/compiled/admission/semantics/policy/parity.js +126 -0
- package/dist/v1/compiled/admission/semantics/policy/pattern.d.ts +8 -0
- package/dist/v1/compiled/admission/semantics/policy/pattern.js +78 -0
- package/dist/v1/compiled/admission/semantics/policy/typing.d.ts +28 -0
- package/dist/v1/compiled/admission/semantics/policy/typing.js +206 -0
- package/dist/v1/compiled/admission/semantics/policy/variants.d.ts +10 -0
- package/dist/v1/compiled/admission/semantics/policy/variants.js +65 -0
- package/dist/v1/compiled/admission/semantics.d.ts +1 -1
- package/dist/v1/compiled/admission/semantics.js +8 -1222
- package/dist/v1/compiled/admission/wire/callable.d.ts +6 -0
- package/dist/v1/compiled/admission/wire/callable.js +90 -0
- package/dist/v1/compiled/admission/wire/class.d.ts +4 -0
- package/dist/v1/compiled/admission/wire/class.js +117 -0
- package/dist/v1/compiled/admission/wire/core.d.ts +5 -0
- package/dist/v1/compiled/admission/wire/core.js +32 -0
- package/dist/v1/compiled/admission/wire/dependency.d.ts +14 -0
- package/dist/v1/compiled/admission/wire/dependency.js +43 -0
- package/dist/v1/compiled/admission/wire/entry.d.ts +5 -0
- package/dist/v1/compiled/admission/wire/entry.js +100 -0
- package/dist/v1/compiled/admission/wire/pattern.d.ts +12 -0
- package/dist/v1/compiled/admission/wire/pattern.js +111 -0
- package/dist/v1/compiled/admission/wire/policy.d.ts +5 -0
- package/dist/v1/compiled/admission/wire/policy.js +168 -0
- package/dist/v1/compiled/admission/wire/program.d.ts +4 -0
- package/dist/v1/compiled/admission/wire/program.js +52 -0
- package/dist/v1/compiled/admission/wire/property.d.ts +4 -0
- package/dist/v1/compiled/admission/wire/property.js +74 -0
- package/dist/v1/compiled/admission/wire/reference.d.ts +8 -0
- package/dist/v1/compiled/admission/wire/reference.js +33 -0
- package/dist/v1/compiled/admission/wire/value.d.ts +29 -0
- package/dist/v1/compiled/admission/wire/value.js +98 -0
- package/dist/v1/compiled/admission/wire/view.d.ts +3 -0
- package/dist/v1/compiled/admission/wire/view.js +17 -0
- package/dist/v1/compiled/compiler/compile.js +2 -0
- package/dist/v1/compiled/model/schema.d.ts +5 -1
- package/dist/v1/domain/projection/classes.js +2 -9
- package/dist/v1/index.d.ts +1 -1
- package/dist/v1/language/class/inheritance.d.ts +12 -0
- package/dist/v1/language/class/inheritance.js +25 -0
- package/dist/v1/language/class/resolved.d.ts +5 -1
- package/dist/v1/language/definition/metadata.d.ts +8 -0
- package/dist/v1/language/definition/metadata.js +12 -0
- package/dist/v1/language/value/model/blob.d.ts +0 -2
- package/dist/v1/language/value/model/blob.js +2 -2
- package/dist/v1/language/value/model/instant.d.ts +0 -2
- package/dist/v1/language/value/model/instant.js +1 -1
- package/dist/v1/language/value/model/schema.d.ts +2 -1
- package/dist/v1/language/value/model/schema.js +1 -5
- package/dist/v1/language/value/reference/registry.d.ts +2 -1
- package/dist/v1/language/value/regexp/syntax.d.ts +2 -1
- package/dist/v1/language/view/model/view.d.ts +2 -10
- package/dist/v1/schema/analysis/class.d.ts +2 -1
- package/dist/v1/schema/canonical/revision.d.ts +2 -1
- package/dist/v1/schema/compatibility/comparators/classes.d.ts +2 -1
- package/dist/v1/schema/compatibility/coordinate.d.ts +2 -1
- package/dist/v1/schema/compatibility/references.js +1 -10
- package/dist/v1/schema/compatibility/report.d.ts +2 -1
- package/dist/v1/schema/compatibility/scope.d.ts +0 -4
- package/dist/v1/schema/compatibility/scope.js +1 -1
- package/dist/v1/schema/diagnostic.d.ts +1 -1
- package/dist/v1/schema/model/schema.d.ts +5 -1
- package/dist/v1/schema/normalization/domain.js +11 -6
- package/dist/v1/schema/resolution/definition.index.d.ts +1 -2
- package/dist/v1/schema/resolution/definition.index.js +0 -3
- package/dist/v1/schema/resolution/origins.d.ts +1 -1
- package/dist/v1/schema/resolution/origins.js +0 -5
- package/dist/v1/schema/validation/class.js +10 -50
- package/dist/v1/schema/validation/core.js +1 -27
- package/dist/v1/schema/validation/domain.d.ts +2 -1
- package/dist/v1/schema/validation/domain.structure.d.ts +0 -2
- package/dist/v1/schema/validation/domain.structure.js +8 -8
- package/dist/v1/schema/validation/policy/context.js +5 -16
- package/dist/v1/schema/validation/view.js +14 -9
- package/dist/value/accept.d.ts +1 -1
- package/dist/value/accept.js +32 -6
- package/dist/value/canonical.js +10 -2
- package/dist/value/immutable.optimization.d.ts +4 -1
- package/dist/value/immutable.optimization.js +8 -2
- package/dist/value/limits.d.ts +1 -1
- package/dist/value/unicode.d.ts +3 -0
- package/dist/value/unicode.js +27 -0
- package/package.json +1 -1
|
@@ -1,22 +1,14 @@
|
|
|
1
1
|
import { accept as acceptPortable } from '@astrale-os/kernel-dsl/value';
|
|
2
2
|
import { dependencyLimits } from '../../addressing/domain-dependency.js';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { PropertyValues } from '../../language/class/property-values.js';
|
|
7
|
-
import { admitStateTopology } from '../../language/state/topology.js';
|
|
8
|
-
import { bindValueProgram } from '../../language/value/compile/load.js';
|
|
9
|
-
import { isValueObject } from '../../language/value/model/object.js';
|
|
10
|
-
import { classifyValueProgramOrdering } from '../../language/value/ordering.js';
|
|
11
|
-
import { compilePattern } from '../../language/value/regexp/compile.js';
|
|
12
|
-
import { isIRegexp } from '../../language/value/regexp/syntax.js';
|
|
13
|
-
import { invalidCompiled } from '../diagnostic.js';
|
|
14
|
-
import { revisionOfCompiledEntry } from './revision.js';
|
|
3
|
+
import {} from '../model/schema.js';
|
|
4
|
+
import { validateClosure } from './closure.js';
|
|
5
|
+
import { invalid, pointer } from './diagnostic.js';
|
|
15
6
|
import { validateCompiledSemantics } from './semantics.js';
|
|
7
|
+
import { dependency } from './wire/dependency.js';
|
|
8
|
+
import { entry } from './wire/entry.js';
|
|
9
|
+
import {} from './wire/pattern.js';
|
|
10
|
+
import { object, exact, array } from './wire/value.js';
|
|
16
11
|
const MAXIMUM_COMPILED_SCHEMA_MEMBERS = 1_000_000;
|
|
17
|
-
function pointer(parent, member) {
|
|
18
|
-
return `${parent}/${String(member).replaceAll('~', '~0').replaceAll('/', '~1')}`;
|
|
19
|
-
}
|
|
20
12
|
/** Admit one detached compiled closure before indices and declarations become executable. */
|
|
21
13
|
export function acceptCompiledSchema(input) {
|
|
22
14
|
const root = object(acceptPortable(input, { limits: { maxMembers: MAXIMUM_COMPILED_SCHEMA_MEMBERS } }), 'CompiledSchema', '');
|
|
@@ -77,996 +69,6 @@ export function acceptCompiledSchema(input) {
|
|
|
77
69
|
validateCompiledSemantics(candidate);
|
|
78
70
|
return deepFreeze(candidate);
|
|
79
71
|
}
|
|
80
|
-
function entry(input, entryIndex, path, machines) {
|
|
81
|
-
const value = object(input, `closure[${entryIndex}]`, path);
|
|
82
|
-
exact(value, ['origin', 'revision', 'dependencies', 'definitions', 'facts', 'values', 'patterns'], 'entry', path);
|
|
83
|
-
const origin = originValue(value.origin, 'entry origin', `${path}/origin`);
|
|
84
|
-
const revision = revisionValue(value.revision, 'entry revision', `${path}/revision`);
|
|
85
|
-
const dependenciesPath = `${path}/dependencies`;
|
|
86
|
-
const dependencies = dependencyMap(value.dependencies, dependenciesPath);
|
|
87
|
-
const dependencyOrigins = new Set();
|
|
88
|
-
for (const [alias, dependency] of Object.entries(dependencies)) {
|
|
89
|
-
if (dependencyOrigins.has(dependency.origin))
|
|
90
|
-
invalid('duplicate dependency', undefined, `${pointer(dependenciesPath, alias)}/origin`);
|
|
91
|
-
dependencyOrigins.add(dependency.origin);
|
|
92
|
-
}
|
|
93
|
-
const valuesPath = `${path}/values`;
|
|
94
|
-
const patternsPath = `${path}/patterns`;
|
|
95
|
-
const patterns = array(value.patterns, 'entry patterns', patternsPath).map((item, index) => pattern(item, index, `${patternsPath}/${index}`, machines));
|
|
96
|
-
const values = array(value.values, 'values', valuesPath).map((item, index) => program(item, index, `${valuesPath}/${index}`, patterns));
|
|
97
|
-
const bound = values.map((value) => bindValueProgram(value, patterns));
|
|
98
|
-
const definitionsPath = `${path}/definitions`;
|
|
99
|
-
const definitions = object(value.definitions, 'definitions', definitionsPath);
|
|
100
|
-
exact(definitions, ['classes', 'functions', 'policies', 'views', 'core'], 'definitions', definitionsPath);
|
|
101
|
-
const classesPath = `${definitionsPath}/classes`;
|
|
102
|
-
const classes = array(definitions.classes, 'classes', classesPath).map((item, index) => compiledClass(item, bound, `${classesPath}/${index}`));
|
|
103
|
-
const functionsPath = `${definitionsPath}/functions`;
|
|
104
|
-
const functions = array(definitions.functions, 'functions', functionsPath).map((item, index) => compiledFunction(item, bound, `${functionsPath}/${index}`));
|
|
105
|
-
const factsPath = `${path}/facts`;
|
|
106
|
-
const facts = object(value.facts, 'facts', factsPath);
|
|
107
|
-
exact(facts, ['core'], 'facts', factsPath);
|
|
108
|
-
const policiesPath = `${definitionsPath}/policies`;
|
|
109
|
-
const viewsPath = `${definitionsPath}/views`;
|
|
110
|
-
const coreDefinitionsPath = `${definitionsPath}/core`;
|
|
111
|
-
const coreFactsPath = `${factsPath}/core`;
|
|
112
|
-
const accepted = {
|
|
113
|
-
origin,
|
|
114
|
-
revision,
|
|
115
|
-
dependencies,
|
|
116
|
-
definitions: {
|
|
117
|
-
classes,
|
|
118
|
-
functions,
|
|
119
|
-
policies: array(definitions.policies, 'policies', policiesPath).map((item, index) => compiledPolicy(item, `${policiesPath}/${index}`)),
|
|
120
|
-
views: array(definitions.views, 'views', viewsPath).map((item, index) => compiledView(item, `${viewsPath}/${index}`)),
|
|
121
|
-
core: array(definitions.core, 'core definitions', coreDefinitionsPath).map((item, index) => compiledCoreDefinition(item, `${coreDefinitionsPath}/${index}`)),
|
|
122
|
-
},
|
|
123
|
-
facts: {
|
|
124
|
-
core: array(facts.core, 'core facts', coreFactsPath).map((item, index) => compiledCoreEdge(item, `${coreFactsPath}/${index}`)),
|
|
125
|
-
},
|
|
126
|
-
values,
|
|
127
|
-
patterns,
|
|
128
|
-
};
|
|
129
|
-
const collections = [
|
|
130
|
-
['classes', accepted.definitions.classes],
|
|
131
|
-
['functions', accepted.definitions.functions],
|
|
132
|
-
['policies', accepted.definitions.policies],
|
|
133
|
-
['views', accepted.definitions.views],
|
|
134
|
-
['core', accepted.definitions.core],
|
|
135
|
-
];
|
|
136
|
-
for (const [collection, definitions] of collections) {
|
|
137
|
-
for (const [index, definition] of definitions.entries()) {
|
|
138
|
-
if (definition.ref.origin !== origin)
|
|
139
|
-
invalid('Definition owner origin', undefined, `${definitionsPath}/${collection}/${index}/ref/origin`);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
if (revisionOfCompiledEntry(accepted) !== revision) {
|
|
143
|
-
invalid('entry revision', 'COMPILED_CANONICAL_MISMATCH', `${path}/revision`);
|
|
144
|
-
}
|
|
145
|
-
return accepted;
|
|
146
|
-
}
|
|
147
|
-
function compiledClass(input, values, path) {
|
|
148
|
-
const value = object(input, 'Compiled Class', path);
|
|
149
|
-
if (value.kind !== 'node' && value.kind !== 'edge')
|
|
150
|
-
invalid('Class kind', undefined, `${path}/kind`);
|
|
151
|
-
exact(value, value.kind === 'node'
|
|
152
|
-
? ['ref', 'kind', 'abstract', 'extends', 'properties', 'methods', 'policies']
|
|
153
|
-
: [
|
|
154
|
-
'ref',
|
|
155
|
-
'kind',
|
|
156
|
-
'abstract',
|
|
157
|
-
'extends',
|
|
158
|
-
'orientation',
|
|
159
|
-
'endpoints',
|
|
160
|
-
'constraints',
|
|
161
|
-
'properties',
|
|
162
|
-
'policies',
|
|
163
|
-
], 'Compiled Class', path, value.kind === 'node' ? ['data', 'description', 'icon'] : ['description']);
|
|
164
|
-
definitionRef(value.ref, 'class', 'Class ref', `${path}/ref`);
|
|
165
|
-
boolean(value.abstract, 'Class abstract', `${path}/abstract`);
|
|
166
|
-
description(value.description, 'Class description', `${path}/description`);
|
|
167
|
-
const extendsPath = `${path}/extends`;
|
|
168
|
-
const parents = array(value.extends, 'Class extends', extendsPath).map((parent, index) => definitionRef(parent, 'class', 'Class parent', `${extendsPath}/${index}`));
|
|
169
|
-
unique(parents.map(Key.of), 'Class parents', extendsPath);
|
|
170
|
-
const propertiesPath = `${path}/properties`;
|
|
171
|
-
const properties = array(value.properties, 'Class properties', propertiesPath).map((property, index) => compiledProperty(property, values, value.kind === 'node', `${propertiesPath}/${index}`));
|
|
172
|
-
unique(properties.map((property) => property.name), 'Class Properties', propertiesPath);
|
|
173
|
-
if (value.kind === 'node') {
|
|
174
|
-
if (value.data !== undefined)
|
|
175
|
-
dataDefinition(value.data, `${path}/data`);
|
|
176
|
-
boundedString(value.icon, 1, 8000, 'Class icon', `${path}/icon`);
|
|
177
|
-
classPolicies(value.policies, `${path}/policies`);
|
|
178
|
-
const methodsPath = `${path}/methods`;
|
|
179
|
-
const methods = array(value.methods, 'Class methods', methodsPath);
|
|
180
|
-
for (const [index, method] of methods.entries())
|
|
181
|
-
compiledCallable(method, values, true, `${methodsPath}/${index}`);
|
|
182
|
-
unique(methods.map((method, index) => string(object(method, 'Compiled Method', `${methodsPath}/${index}`).name, 'Method name', `${methodsPath}/${index}/name`)), 'Class Methods', methodsPath);
|
|
183
|
-
}
|
|
184
|
-
else {
|
|
185
|
-
classPolicies(value.policies, `${path}/policies`);
|
|
186
|
-
edgeContract(value, path);
|
|
187
|
-
}
|
|
188
|
-
return { ...value, properties };
|
|
189
|
-
}
|
|
190
|
-
function compiledFunction(input, values, path) {
|
|
191
|
-
const value = object(input, 'Compiled Function', path);
|
|
192
|
-
compiledCallable(value, values, false, path);
|
|
193
|
-
definitionRef(value.ref, 'function', 'Function ref', `${path}/ref`);
|
|
194
|
-
return value;
|
|
195
|
-
}
|
|
196
|
-
function compiledProperty(input, values, node, path) {
|
|
197
|
-
const value = object(input, 'Compiled Property', path);
|
|
198
|
-
exact(value, ['name', 'required', 'value'], 'Compiled Property', path, [
|
|
199
|
-
'auto',
|
|
200
|
-
'description',
|
|
201
|
-
'immutable',
|
|
202
|
-
'ordering',
|
|
203
|
-
'state',
|
|
204
|
-
]);
|
|
205
|
-
memberName(value.name, 'Property name', `${path}/name`);
|
|
206
|
-
boolean(value.required, 'Property required', `${path}/required`);
|
|
207
|
-
description(value.description, 'Property description', `${path}/description`);
|
|
208
|
-
if (value.auto !== undefined)
|
|
209
|
-
propertyAuto(value.auto, `${path}/auto`);
|
|
210
|
-
if (value.immutable !== undefined && value.immutable !== 'create' && value.immutable !== 'once') {
|
|
211
|
-
invalid('Property immutability', undefined, `${path}/immutable`);
|
|
212
|
-
}
|
|
213
|
-
const valueIndex = index(value.value, values.length, 'Property value', `${path}/value`);
|
|
214
|
-
let state;
|
|
215
|
-
if (value.state !== undefined) {
|
|
216
|
-
if (!node)
|
|
217
|
-
invalid('Property state placement', 'COMPILED_SOURCE_INVALID', `${path}/state`);
|
|
218
|
-
let topology;
|
|
219
|
-
try {
|
|
220
|
-
topology = admitStateTopology(value.state);
|
|
221
|
-
}
|
|
222
|
-
catch {
|
|
223
|
-
invalid('Property state topology', 'COMPILED_SOURCE_INVALID', `${path}/state`);
|
|
224
|
-
}
|
|
225
|
-
const program = values[valueIndex];
|
|
226
|
-
const schema = program.nodes[program.root].schema;
|
|
227
|
-
const states = Object.keys(topology.transitions);
|
|
228
|
-
const schemaObject = schema;
|
|
229
|
-
const schemaMatches = schema !== null &&
|
|
230
|
-
typeof schema === 'object' &&
|
|
231
|
-
!Array.isArray(schema) &&
|
|
232
|
-
Object.keys(schemaObject).length === 2 &&
|
|
233
|
-
schemaObject.type === 'string' &&
|
|
234
|
-
Array.isArray(schemaObject.enum) &&
|
|
235
|
-
schemaObject.enum.length === states.length &&
|
|
236
|
-
schemaObject.enum.every((state, index) => state === states[index]);
|
|
237
|
-
if (!value.required || value.auto !== undefined || !schemaMatches) {
|
|
238
|
-
invalid('Property state contract', 'COMPILED_SOURCE_INVALID', `${path}/state`);
|
|
239
|
-
}
|
|
240
|
-
state = topology;
|
|
241
|
-
}
|
|
242
|
-
if (value.ordering !== classifyValueProgramOrdering(values[valueIndex])) {
|
|
243
|
-
invalid('Property ordering', 'COMPILED_CANONICAL_MISMATCH', `${path}/ordering`);
|
|
244
|
-
}
|
|
245
|
-
return {
|
|
246
|
-
...value,
|
|
247
|
-
...(state === undefined ? {} : { state }),
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
|
-
function compiledCallable(input, values, method, path) {
|
|
251
|
-
const value = object(input, 'Compiled Callable', path);
|
|
252
|
-
exact(value, method
|
|
253
|
-
? ['name', 'auth', 'static', 'abstract', 'input', 'output']
|
|
254
|
-
: ['ref', 'auth', 'input', 'output'], 'Compiled Callable', path, ['policy', 'description', 'execution', 'fields']);
|
|
255
|
-
if (method) {
|
|
256
|
-
memberName(value.name, 'Method name', `${path}/name`);
|
|
257
|
-
boolean(value.static, 'Method static', `${path}/static`);
|
|
258
|
-
boolean(value.abstract, 'Method abstract', `${path}/abstract`);
|
|
259
|
-
}
|
|
260
|
-
if (value.auth !== 'anonymous' && value.auth !== 'authenticated' && value.auth !== 'authorized') {
|
|
261
|
-
invalid('Callable auth', undefined, `${path}/auth`);
|
|
262
|
-
}
|
|
263
|
-
description(value.description, 'Callable description', `${path}/description`);
|
|
264
|
-
if (value.policy !== undefined) {
|
|
265
|
-
if (value.auth !== 'authorized') {
|
|
266
|
-
invalid('Callable Policy placement', undefined, `${path}/policy`);
|
|
267
|
-
}
|
|
268
|
-
policyCheck(value.policy, 0, `${path}/policy`);
|
|
269
|
-
}
|
|
270
|
-
let inputIndex;
|
|
271
|
-
if (!method && typeof value.input === 'object' && value.input !== null) {
|
|
272
|
-
const inputPath = `${path}/input`;
|
|
273
|
-
const binary = object(value.input, 'Binary input', inputPath);
|
|
274
|
-
exact(binary, ['mode', 'metadata', 'maximumBytes'], 'Binary input', inputPath);
|
|
275
|
-
if (binary.mode !== 'binary')
|
|
276
|
-
invalid('Binary input mode', undefined, `${inputPath}/mode`);
|
|
277
|
-
inputIndex = index(binary.metadata, values.length, 'Binary input metadata', `${inputPath}/metadata`);
|
|
278
|
-
const maximumBytes = integer(binary.maximumBytes, 'Binary input maximumBytes', `${inputPath}/maximumBytes`);
|
|
279
|
-
if (maximumBytes < 1)
|
|
280
|
-
invalid('Binary input maximumBytes', undefined, `${inputPath}/maximumBytes`);
|
|
281
|
-
}
|
|
282
|
-
else {
|
|
283
|
-
inputIndex = index(value.input, values.length, 'Callable input', `${path}/input`);
|
|
284
|
-
}
|
|
285
|
-
if (value.fields !== undefined) {
|
|
286
|
-
const fieldsPath = `${path}/fields`;
|
|
287
|
-
for (const [field, nodes] of Object.entries(object(value.fields, 'Callable fields', fieldsPath))) {
|
|
288
|
-
const fieldPath = pointer(fieldsPath, field);
|
|
289
|
-
const fieldNodes = array(nodes, 'Callable field nodes', fieldPath);
|
|
290
|
-
if (fieldNodes.length === 0)
|
|
291
|
-
invalid('Callable field nodes', undefined, fieldPath);
|
|
292
|
-
for (const [indexValue, node] of fieldNodes.entries()) {
|
|
293
|
-
index(node, values[inputIndex].nodes.length, 'Callable field', `${fieldPath}/${indexValue}`);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
const outputPath = `${path}/output`;
|
|
298
|
-
const output = object(value.output, 'Callable output', outputPath);
|
|
299
|
-
if (output.mode === 'binary')
|
|
300
|
-
exact(output, ['mode'], 'binary output', outputPath);
|
|
301
|
-
else {
|
|
302
|
-
if (output.mode !== 'value' && output.mode !== 'stream')
|
|
303
|
-
invalid('Callable output mode', undefined, `${outputPath}/mode`);
|
|
304
|
-
exact(output, ['mode', 'value'], 'Callable output', outputPath);
|
|
305
|
-
index(output.value, values.length, 'Callable output value', `${outputPath}/value`);
|
|
306
|
-
}
|
|
307
|
-
if (value.execution !== undefined) {
|
|
308
|
-
const executionPath = `${path}/execution`;
|
|
309
|
-
const execution = object(value.execution, 'Callable execution', executionPath);
|
|
310
|
-
exact(execution, ['durable'], 'Callable execution', executionPath);
|
|
311
|
-
// Ordinary execution is canonically absent; only the durable modifier is retained.
|
|
312
|
-
if (!boolean(execution.durable, 'Callable execution durable', `${executionPath}/durable`)) {
|
|
313
|
-
invalid('Callable execution', 'COMPILED_CANONICAL_MISMATCH', `${executionPath}/durable`);
|
|
314
|
-
}
|
|
315
|
-
if (value.auth === 'anonymous') {
|
|
316
|
-
invalid('durable Callable auth', 'COMPILED_SOURCE_INVALID', `${path}/auth`);
|
|
317
|
-
}
|
|
318
|
-
if (typeof value.input === 'object' && value.input !== null) {
|
|
319
|
-
invalid('durable Callable input', 'COMPILED_SOURCE_INVALID', `${path}/input`);
|
|
320
|
-
}
|
|
321
|
-
if (output.mode !== 'value') {
|
|
322
|
-
invalid('durable Callable output', 'COMPILED_SOURCE_INVALID', `${outputPath}/mode`);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
function compiledPolicy(input, path) {
|
|
327
|
-
const value = object(input, 'Policy', path);
|
|
328
|
-
exact(value, ['ref', 'expression'], 'Policy', path, ['description']);
|
|
329
|
-
definitionRef(value.ref, 'policy', 'Policy ref', `${path}/ref`);
|
|
330
|
-
description(value.description, 'Policy description', `${path}/description`);
|
|
331
|
-
policyExpression(value.expression, 0, `${path}/expression`);
|
|
332
|
-
return value;
|
|
333
|
-
}
|
|
334
|
-
function compiledView(input, path) {
|
|
335
|
-
const value = object(input, 'View', path);
|
|
336
|
-
exact(value, ['ref', 'target'], 'View', path, ['description']);
|
|
337
|
-
definitionRef(value.ref, 'view', 'View ref', `${path}/ref`);
|
|
338
|
-
description(value.description, 'View description', `${path}/description`);
|
|
339
|
-
const targetPath = `${path}/target`;
|
|
340
|
-
const target = object(value.target, 'View target', targetPath);
|
|
341
|
-
if (target.kind === 'domain') {
|
|
342
|
-
exact(target, ['kind'], 'Domain View target', targetPath);
|
|
343
|
-
}
|
|
344
|
-
else if (target.kind === 'definition') {
|
|
345
|
-
exact(target, ['kind', 'definitions'], 'Definition View target', targetPath);
|
|
346
|
-
const definitionsPath = `${targetPath}/definitions`;
|
|
347
|
-
const definitions = array(target.definitions, 'View target definitions', definitionsPath).map((item, index) => definitionRef(item, 'class', 'View target Class', `${definitionsPath}/${index}`));
|
|
348
|
-
if (definitions.length === 0)
|
|
349
|
-
invalid('View target definitions', undefined, definitionsPath);
|
|
350
|
-
unique(definitions.map(Key.of), 'View target definitions', definitionsPath);
|
|
351
|
-
}
|
|
352
|
-
else {
|
|
353
|
-
invalid('View target', undefined, targetPath);
|
|
354
|
-
}
|
|
355
|
-
return value;
|
|
356
|
-
}
|
|
357
|
-
function compiledCoreDefinition(input, path) {
|
|
358
|
-
const value = object(input, 'Core Definition', path);
|
|
359
|
-
exact(value, ['ref', 'class', 'properties'], 'Core Definition', path);
|
|
360
|
-
definitionRef(value.ref, 'core', 'Core ref', `${path}/ref`);
|
|
361
|
-
definitionRef(value.class, 'class', 'Core Class', `${path}/class`);
|
|
362
|
-
propertyValues(value.properties, 'Core Properties', `${path}/properties`);
|
|
363
|
-
return value;
|
|
364
|
-
}
|
|
365
|
-
function compiledCoreEdge(input, path) {
|
|
366
|
-
const value = object(input, 'Core Edge', path);
|
|
367
|
-
exact(value, ['class', 'source', 'target', 'properties'], 'Core Edge', path);
|
|
368
|
-
definitionRef(value.class, 'class', 'Core Edge Class', `${path}/class`);
|
|
369
|
-
coreEndpoint(value.source, 'Core Edge source', `${path}/source`);
|
|
370
|
-
coreEndpoint(value.target, 'Core Edge target', `${path}/target`);
|
|
371
|
-
propertyValues(value.properties, 'Core Edge Properties', `${path}/properties`);
|
|
372
|
-
return value;
|
|
373
|
-
}
|
|
374
|
-
function propertyAuto(input, path) {
|
|
375
|
-
const value = object(input, 'Property auto', path);
|
|
376
|
-
exact(value, ['on', 'set'], 'Property auto', path);
|
|
377
|
-
const eventsPath = `${path}/on`;
|
|
378
|
-
const events = array(value.on, 'Property auto events', eventsPath);
|
|
379
|
-
if (events.length === 0 || events.some((event) => event !== 'create' && event !== 'update')) {
|
|
380
|
-
invalid('Property auto events', undefined, eventsPath);
|
|
381
|
-
}
|
|
382
|
-
unique(events.map(String), 'Property auto events', eventsPath);
|
|
383
|
-
if (value.set !== 'instant')
|
|
384
|
-
invalid('Property auto setter', undefined, `${path}/set`);
|
|
385
|
-
}
|
|
386
|
-
function classPolicies(input, path) {
|
|
387
|
-
const value = object(input, 'Class Policies', path);
|
|
388
|
-
exact(value, [], 'Class Policies', path, ['read', 'traverse']);
|
|
389
|
-
if (value.read !== undefined)
|
|
390
|
-
definitionRef(value.read, 'policy', 'Class read Policy', `${path}/read`);
|
|
391
|
-
if (value.traverse !== undefined)
|
|
392
|
-
definitionRef(value.traverse, 'policy', 'Class traverse Policy', `${path}/traverse`);
|
|
393
|
-
}
|
|
394
|
-
function edgeContract(value, path) {
|
|
395
|
-
const constraintsPath = `${path}/constraints`;
|
|
396
|
-
const constraints = object(value.constraints, 'Edge constraints', constraintsPath);
|
|
397
|
-
exact(constraints, [], 'Edge constraints', constraintsPath, ['noSelf', 'acyclic']);
|
|
398
|
-
if (constraints.noSelf !== undefined && constraints.noSelf !== true)
|
|
399
|
-
invalid('Edge noSelf constraint', undefined, `${constraintsPath}/noSelf`);
|
|
400
|
-
if (constraints.acyclic !== undefined && constraints.acyclic !== true)
|
|
401
|
-
invalid('Edge acyclic constraint', undefined, `${constraintsPath}/acyclic`);
|
|
402
|
-
if (value.orientation === 'directed') {
|
|
403
|
-
const endpointsPath = `${path}/endpoints`;
|
|
404
|
-
const endpoints = object(value.endpoints, 'directed Edge endpoints', endpointsPath);
|
|
405
|
-
exact(endpoints, ['source', 'target'], 'directed Edge endpoints', endpointsPath);
|
|
406
|
-
edgeEndpoint(endpoints.source, 'outgoing', 'directed Edge source', `${endpointsPath}/source`);
|
|
407
|
-
edgeEndpoint(endpoints.target, 'incoming', 'directed Edge target', `${endpointsPath}/target`);
|
|
408
|
-
if (object(endpoints.source, 'directed Edge source', `${endpointsPath}/source`).role ===
|
|
409
|
-
object(endpoints.target, 'directed Edge target', `${endpointsPath}/target`).role) {
|
|
410
|
-
invalid('Edge endpoint roles', undefined, endpointsPath);
|
|
411
|
-
}
|
|
412
|
-
return;
|
|
413
|
-
}
|
|
414
|
-
if (value.orientation !== 'undirected' || constraints.acyclic !== undefined) {
|
|
415
|
-
invalid('Edge orientation', undefined, `${path}/orientation`);
|
|
416
|
-
}
|
|
417
|
-
const endpointsPath = `${path}/endpoints`;
|
|
418
|
-
const endpoints = array(value.endpoints, 'undirected Edge endpoints', endpointsPath);
|
|
419
|
-
if (endpoints.length !== 2)
|
|
420
|
-
invalid('undirected Edge endpoints', undefined, endpointsPath);
|
|
421
|
-
edgeEndpoint(endpoints[0], 'incident', 'undirected first endpoint', `${endpointsPath}/0`);
|
|
422
|
-
edgeEndpoint(endpoints[1], 'incident', 'undirected second endpoint', `${endpointsPath}/1`);
|
|
423
|
-
if (object(endpoints[0], 'undirected first endpoint', `${endpointsPath}/0`).role ===
|
|
424
|
-
object(endpoints[1], 'undirected second endpoint', `${endpointsPath}/1`).role) {
|
|
425
|
-
invalid('Edge endpoint roles', undefined, endpointsPath);
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
function edgeEndpoint(input, count, label, path) {
|
|
429
|
-
const value = object(input, label, path);
|
|
430
|
-
exact(value, ['role', 'accepts', count], label, path);
|
|
431
|
-
memberName(value.role, `${label} role`, `${path}/role`);
|
|
432
|
-
const acceptsPath = `${path}/accepts`;
|
|
433
|
-
const accepts = array(value.accepts, `${label} accepts`, acceptsPath).map((item, index) => definitionRef(item, 'class', `${label} accepted Class`, `${acceptsPath}/${index}`));
|
|
434
|
-
if (accepts.length === 0)
|
|
435
|
-
invalid(`${label} accepts`, undefined, acceptsPath);
|
|
436
|
-
unique(accepts.map(Key.of), `${label} accepts`, acceptsPath);
|
|
437
|
-
if (value[count] !== '0..*' &&
|
|
438
|
-
value[count] !== '1..*' &&
|
|
439
|
-
value[count] !== '0..1' &&
|
|
440
|
-
value[count] !== '1') {
|
|
441
|
-
invalid(`${label} ${count}`, undefined, `${path}/${count}`);
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
function policyExpression(input, depth, path) {
|
|
445
|
-
if (depth > 64)
|
|
446
|
-
invalid('Policy expression depth', undefined, path);
|
|
447
|
-
const value = object(input, 'Policy expression', path);
|
|
448
|
-
if (Object.hasOwn(value, 'match')) {
|
|
449
|
-
exact(value, ['match'], 'Policy expression', path);
|
|
450
|
-
policyPattern(value.match, depth + 1, `${path}/match`);
|
|
451
|
-
return;
|
|
452
|
-
}
|
|
453
|
-
const member = Object.hasOwn(value, 'allOf') ? 'allOf' : 'anyOf';
|
|
454
|
-
exact(value, [member], 'Policy expression', path);
|
|
455
|
-
const memberPath = pointer(path, member);
|
|
456
|
-
const refs = array(value[member], `Policy ${member}`, memberPath).map((item, index) => definitionRef(item, 'policy', `Policy ${member} ref`, `${memberPath}/${index}`));
|
|
457
|
-
if (refs.length === 0)
|
|
458
|
-
invalid(`Policy ${member}`, undefined, memberPath);
|
|
459
|
-
unique(refs.map(Key.of), `Policy ${member}`, memberPath);
|
|
460
|
-
}
|
|
461
|
-
function policyPattern(input, depth, path) {
|
|
462
|
-
if (depth > 64)
|
|
463
|
-
invalid('Policy pattern depth', undefined, path);
|
|
464
|
-
const value = object(input, 'Policy pattern', path);
|
|
465
|
-
if (Object.hasOwn(value, 'sameNode')) {
|
|
466
|
-
exact(value, ['sameNode'], 'Policy equality', path);
|
|
467
|
-
const pair = object(value.sameNode, 'Policy equality', `${path}/sameNode`);
|
|
468
|
-
exact(pair, ['left', 'right'], 'Policy equality operands', `${path}/sameNode`);
|
|
469
|
-
policyTerm(pair.left, false, `${path}/sameNode/left`);
|
|
470
|
-
policyTerm(pair.right, false, `${path}/sameNode/right`);
|
|
471
|
-
return;
|
|
472
|
-
}
|
|
473
|
-
if (Object.hasOwn(value, 'exists')) {
|
|
474
|
-
exact(value, ['exists'], 'Policy exists', path);
|
|
475
|
-
const existsPath = `${path}/exists`;
|
|
476
|
-
const exists = object(value.exists, 'Policy exists', existsPath);
|
|
477
|
-
exact(exists, ['nodes', 'where'], 'Policy exists', existsPath);
|
|
478
|
-
const nodesPath = `${existsPath}/nodes`;
|
|
479
|
-
const nodes = array(exists.nodes, 'Policy variables', nodesPath);
|
|
480
|
-
if (nodes.length < 1 || nodes.length > 4)
|
|
481
|
-
invalid('Policy variables', undefined, nodesPath);
|
|
482
|
-
for (const [index, node] of nodes.entries()) {
|
|
483
|
-
const variablePath = `${nodesPath}/${index}`;
|
|
484
|
-
const variable = object(node, 'Policy variable', variablePath);
|
|
485
|
-
policyTerm(variable.variable, true, `${variablePath}/variable`);
|
|
486
|
-
if (Object.hasOwn(variable, 'class')) {
|
|
487
|
-
exact(variable, ['variable', 'class'], 'Policy variable', variablePath);
|
|
488
|
-
definitionRef(variable.class, 'class', 'Policy variable Class', `${variablePath}/class`);
|
|
489
|
-
}
|
|
490
|
-
else {
|
|
491
|
-
exact(variable, ['variable', 'selector'], 'Policy variable', variablePath);
|
|
492
|
-
const selectorPath = `${variablePath}/selector`;
|
|
493
|
-
const selector = object(variable.selector, 'Policy variable selector', selectorPath);
|
|
494
|
-
if (selector.kind === 'any') {
|
|
495
|
-
exact(selector, ['kind'], 'Policy variable selector', selectorPath);
|
|
496
|
-
}
|
|
497
|
-
else if (selector.kind === 'satisfies') {
|
|
498
|
-
exact(selector, ['kind', 'class'], 'Policy variable selector', selectorPath);
|
|
499
|
-
definitionRef(selector.class, 'class', 'Policy variable selector Class', `${selectorPath}/class`);
|
|
500
|
-
}
|
|
501
|
-
else {
|
|
502
|
-
invalid('Policy variable selector kind', undefined, `${selectorPath}/kind`);
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
policyPattern(exists.where, depth + 1, `${existsPath}/where`);
|
|
507
|
-
return;
|
|
508
|
-
}
|
|
509
|
-
if (Object.hasOwn(value, 'allOf') || Object.hasOwn(value, 'anyOf')) {
|
|
510
|
-
const member = Object.hasOwn(value, 'allOf') ? 'allOf' : 'anyOf';
|
|
511
|
-
exact(value, [member], 'Policy pattern composition', path);
|
|
512
|
-
const memberPath = pointer(path, member);
|
|
513
|
-
const expressions = array(value[member], `Policy pattern ${member}`, memberPath);
|
|
514
|
-
if (expressions.length === 0)
|
|
515
|
-
invalid(`Policy pattern ${member}`, undefined, memberPath);
|
|
516
|
-
for (const [index, expression] of expressions.entries())
|
|
517
|
-
policyPattern(expression, depth + 1, `${memberPath}/${index}`);
|
|
518
|
-
return;
|
|
519
|
-
}
|
|
520
|
-
exact(value, ['source', 'class', 'target'], 'Policy Edge pattern', path, ['repeat']);
|
|
521
|
-
policyTerm(value.source, false, `${path}/source`);
|
|
522
|
-
definitionRef(value.class, 'class', 'Policy Edge Class', `${path}/class`);
|
|
523
|
-
policyTerm(value.target, false, `${path}/target`);
|
|
524
|
-
if (value.repeat !== undefined) {
|
|
525
|
-
const repeatPath = `${path}/repeat`;
|
|
526
|
-
const repeat = object(value.repeat, 'Policy repeat', repeatPath);
|
|
527
|
-
exact(repeat, ['min', 'max'], 'Policy repeat', repeatPath);
|
|
528
|
-
const minimum = boundedInteger(repeat.min, 0, 3, 'Policy repeat minimum', `${repeatPath}/min`);
|
|
529
|
-
const maximum = boundedInteger(repeat.max, 0, 3, 'Policy repeat maximum', `${repeatPath}/max`);
|
|
530
|
-
if (minimum > maximum)
|
|
531
|
-
invalid('Policy repeat order', undefined, repeatPath);
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
function policyTerm(input, variableOnly, path) {
|
|
535
|
-
const value = object(input, 'Policy pattern term', path);
|
|
536
|
-
if (!variableOnly && value.kind === 'ref') {
|
|
537
|
-
exact(value, ['kind', 'ref'], 'Policy reference term', path);
|
|
538
|
-
policyObjectRef(value.ref, `${path}/ref`);
|
|
539
|
-
return;
|
|
540
|
-
}
|
|
541
|
-
if (value.kind === 'variable') {
|
|
542
|
-
exact(value, ['kind', 'id'], 'Policy variable term', path);
|
|
543
|
-
integer(value.id, 'Policy variable id', `${path}/id`);
|
|
544
|
-
return;
|
|
545
|
-
}
|
|
546
|
-
if (variableOnly ||
|
|
547
|
-
(value.kind !== 'subject' &&
|
|
548
|
-
value.kind !== 'object' &&
|
|
549
|
-
value.kind !== 'source' &&
|
|
550
|
-
value.kind !== 'target')) {
|
|
551
|
-
invalid('Policy pattern term', undefined, `${path}/kind`);
|
|
552
|
-
}
|
|
553
|
-
exact(value, ['kind'], 'Policy pattern term', path);
|
|
554
|
-
}
|
|
555
|
-
function policyCheck(input, depth, path) {
|
|
556
|
-
if (depth > 64)
|
|
557
|
-
invalid('Callable Policy depth', undefined, path);
|
|
558
|
-
const value = object(input, 'Callable Policy', path);
|
|
559
|
-
if (Object.hasOwn(value, 'sameNode')) {
|
|
560
|
-
exact(value, ['sameNode'], 'Callable equality', path);
|
|
561
|
-
const pair = object(value.sameNode, 'Callable equality', `${path}/sameNode`);
|
|
562
|
-
exact(pair, ['left', 'right'], 'Callable equality operands', `${path}/sameNode`);
|
|
563
|
-
policyCheckObject(pair.left, `${path}/sameNode/left`);
|
|
564
|
-
policyCheckObject(pair.right, `${path}/sameNode/right`);
|
|
565
|
-
return;
|
|
566
|
-
}
|
|
567
|
-
if (Object.hasOwn(value, 'check')) {
|
|
568
|
-
exact(value, ['check', 'object'], 'Callable Policy check', path);
|
|
569
|
-
definitionRef(value.check, 'policy', 'Callable Policy ref', `${path}/check`);
|
|
570
|
-
policyCheckObject(value.object, `${path}/object`);
|
|
571
|
-
return;
|
|
572
|
-
}
|
|
573
|
-
const member = Object.hasOwn(value, 'allOf') ? 'allOf' : 'anyOf';
|
|
574
|
-
exact(value, [member], 'Callable Policy composition', path);
|
|
575
|
-
const memberPath = pointer(path, member);
|
|
576
|
-
const expressions = array(value[member], `Callable Policy ${member}`, memberPath);
|
|
577
|
-
if (expressions.length === 0)
|
|
578
|
-
invalid(`Callable Policy ${member}`, undefined, memberPath);
|
|
579
|
-
for (const [index, expression] of expressions.entries())
|
|
580
|
-
policyCheck(expression, depth + 1, `${memberPath}/${index}`);
|
|
581
|
-
}
|
|
582
|
-
function policyCheckObject(input, objectPath) {
|
|
583
|
-
const target = object(input, 'Callable Policy object', objectPath);
|
|
584
|
-
if (target.kind === 'self')
|
|
585
|
-
exact(target, ['kind'], 'Callable Policy self', objectPath);
|
|
586
|
-
else if (target.kind === 'input') {
|
|
587
|
-
exact(target, ['kind', 'field'], 'Callable Policy input', objectPath);
|
|
588
|
-
memberName(target.field, 'Callable Policy input field', `${objectPath}/field`);
|
|
589
|
-
}
|
|
590
|
-
else if (target.kind === 'ref') {
|
|
591
|
-
exact(target, ['kind', 'ref'], 'Callable Policy object ref', objectPath);
|
|
592
|
-
policyObjectRef(target.ref, `${objectPath}/ref`);
|
|
593
|
-
}
|
|
594
|
-
else
|
|
595
|
-
invalid('Callable Policy object', undefined, `${objectPath}/kind`);
|
|
596
|
-
}
|
|
597
|
-
function coreEndpoint(input, label, path) {
|
|
598
|
-
const value = object(input, label, path);
|
|
599
|
-
if (value.kind === 'domain')
|
|
600
|
-
exact(value, ['kind'], label, path);
|
|
601
|
-
else
|
|
602
|
-
projectedMemberRef(value, label, path);
|
|
603
|
-
}
|
|
604
|
-
function policyObjectRef(input, path) {
|
|
605
|
-
projectedMemberRef(object(input, 'Policy object ref', path), 'Policy object ref', path);
|
|
606
|
-
}
|
|
607
|
-
function projectedMemberRef(ref, label, path) {
|
|
608
|
-
if (ref.kind !== 'method') {
|
|
609
|
-
definitionRef(ref, undefined, label, path);
|
|
610
|
-
return;
|
|
611
|
-
}
|
|
612
|
-
exact(ref, ['kind', 'owner', 'name'], `${label} Method`, path);
|
|
613
|
-
definitionRef(ref.owner, 'class', `${label} Method owner`, `${path}/owner`);
|
|
614
|
-
if (typeof ref.name !== 'string' || !MEMBER_NAME_PATTERN.test(ref.name))
|
|
615
|
-
invalid(`${label} Method name`, undefined, `${path}/name`);
|
|
616
|
-
}
|
|
617
|
-
function definitionRef(input, kind, label, path) {
|
|
618
|
-
if (!isDefinitionRef(input) || (kind !== undefined && input.kind !== kind))
|
|
619
|
-
invalid(label, undefined, path);
|
|
620
|
-
return input;
|
|
621
|
-
}
|
|
622
|
-
function propertyValues(input, label, path) {
|
|
623
|
-
try {
|
|
624
|
-
PropertyValues.accept(input, path);
|
|
625
|
-
}
|
|
626
|
-
catch {
|
|
627
|
-
invalid(label, undefined, path);
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
function dataDefinition(input, path) {
|
|
631
|
-
const value = object(input, 'Class data', path);
|
|
632
|
-
exact(value, ['mediaType'], 'Class data', path);
|
|
633
|
-
if (typeof value.mediaType !== 'string' || !MEDIA_TYPE_PATTERN.test(value.mediaType))
|
|
634
|
-
invalid('Class data mediaType', undefined, `${path}/mediaType`);
|
|
635
|
-
}
|
|
636
|
-
function validateClosure(candidate) {
|
|
637
|
-
validateDependencyCycles(candidate);
|
|
638
|
-
const definitions = new Map();
|
|
639
|
-
for (const [entryIndex, entry] of candidate.closure.entries()) {
|
|
640
|
-
const collections = [
|
|
641
|
-
['classes', entry.definitions.classes],
|
|
642
|
-
['functions', entry.definitions.functions],
|
|
643
|
-
['policies', entry.definitions.policies],
|
|
644
|
-
['views', entry.definitions.views],
|
|
645
|
-
['core', entry.definitions.core],
|
|
646
|
-
];
|
|
647
|
-
for (const [collection, values] of collections) {
|
|
648
|
-
for (const [definitionIndex, definition] of values.entries()) {
|
|
649
|
-
const path = `/closure/${entryIndex}/definitions/${collection}/${definitionIndex}`;
|
|
650
|
-
const key = Key.of(definition.ref);
|
|
651
|
-
if (definitions.has(key))
|
|
652
|
-
invalid('duplicate Definition', undefined, `${path}/ref`);
|
|
653
|
-
definitions.set(key, { value: definition, path });
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
const requireDefinition = (ref, label, path) => {
|
|
658
|
-
const result = definitions.get(Key.of(ref));
|
|
659
|
-
if (result === undefined)
|
|
660
|
-
invalid(label, 'COMPILED_SOURCE_INVALID', path);
|
|
661
|
-
return result.value;
|
|
662
|
-
};
|
|
663
|
-
for (const [entryIndex, entry] of candidate.closure.entries()) {
|
|
664
|
-
const visibleOrigins = new Set([
|
|
665
|
-
entry.origin,
|
|
666
|
-
...Object.values(entry.dependencies).map(({ origin }) => origin),
|
|
667
|
-
]);
|
|
668
|
-
const collections = [
|
|
669
|
-
['definitions/classes', entry.definitions.classes],
|
|
670
|
-
['definitions/functions', entry.definitions.functions],
|
|
671
|
-
['definitions/policies', entry.definitions.policies],
|
|
672
|
-
['definitions/views', entry.definitions.views],
|
|
673
|
-
['definitions/core', entry.definitions.core],
|
|
674
|
-
['facts/core', entry.facts.core],
|
|
675
|
-
];
|
|
676
|
-
for (const [collection, values] of collections) {
|
|
677
|
-
for (const [definitionIndex, definition] of values.entries()) {
|
|
678
|
-
walk(definition, `/closure/${entryIndex}/${collection}/${definitionIndex}`, (ref, path) => {
|
|
679
|
-
const resolved = requireDefinition(ref, 'unresolved Definition ref', path);
|
|
680
|
-
if (!visibleOrigins.has(ref.origin))
|
|
681
|
-
invalid('non-direct dependency ref', 'COMPILED_SOURCE_INVALID', path);
|
|
682
|
-
if (resolved.ref === undefined)
|
|
683
|
-
invalid('resolved Definition', 'COMPILED_SOURCE_INVALID', path);
|
|
684
|
-
});
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
const classes = new Map();
|
|
689
|
-
for (const [entryIndex, entry] of candidate.closure.entries())
|
|
690
|
-
for (const [classIndex, definition] of entry.definitions.classes.entries())
|
|
691
|
-
classes.set(Key.of(definition.ref), {
|
|
692
|
-
value: definition,
|
|
693
|
-
path: `/closure/${entryIndex}/definitions/classes/${classIndex}`,
|
|
694
|
-
});
|
|
695
|
-
const visiting = new Set();
|
|
696
|
-
const visited = new Set();
|
|
697
|
-
const visitClass = (key) => {
|
|
698
|
-
if (visited.has(key))
|
|
699
|
-
return;
|
|
700
|
-
if (visiting.has(key))
|
|
701
|
-
invalid('Class inheritance cycle', 'COMPILED_SOURCE_INVALID', `${classes.get(key)?.path ?? ''}/extends`);
|
|
702
|
-
const definition = classes.get(key);
|
|
703
|
-
if (definition === undefined)
|
|
704
|
-
invalid('Class inheritance ref', 'COMPILED_SOURCE_INVALID', '/closure');
|
|
705
|
-
visiting.add(key);
|
|
706
|
-
for (const [parentIndex, parentRef] of definition.value.extends.entries()) {
|
|
707
|
-
const parent = classes.get(Key.of(parentRef));
|
|
708
|
-
if (parent === undefined || parent.value.kind !== definition.value.kind) {
|
|
709
|
-
invalid('Class inheritance kind', 'COMPILED_SOURCE_INVALID', `${definition.path}/extends/${parentIndex}`);
|
|
710
|
-
}
|
|
711
|
-
visitClass(Key.of(parentRef));
|
|
712
|
-
}
|
|
713
|
-
visiting.delete(key);
|
|
714
|
-
visited.add(key);
|
|
715
|
-
};
|
|
716
|
-
for (const key of classes.keys())
|
|
717
|
-
visitClass(key);
|
|
718
|
-
for (const definition of classes.values()) {
|
|
719
|
-
if (definition.value.kind !== 'edge')
|
|
720
|
-
continue;
|
|
721
|
-
const endpoints = definition.value.orientation === 'directed'
|
|
722
|
-
? [
|
|
723
|
-
definition.value.endpoints.source,
|
|
724
|
-
definition.value.endpoints.target,
|
|
725
|
-
]
|
|
726
|
-
: definition.value.endpoints;
|
|
727
|
-
for (const [endpointIndex, endpoint] of endpoints.entries()) {
|
|
728
|
-
const endpointPath = definition.value.orientation === 'directed'
|
|
729
|
-
? `${definition.path}/endpoints/${endpointIndex === 0 ? 'source' : 'target'}`
|
|
730
|
-
: `${definition.path}/endpoints/${endpointIndex}`;
|
|
731
|
-
for (const [acceptedIndex, accepted] of endpoint.accepts.entries()) {
|
|
732
|
-
if (classes.get(Key.of(accepted))?.value.kind !== 'node') {
|
|
733
|
-
invalid('Edge endpoint Class', 'COMPILED_SOURCE_INVALID', `${endpointPath}/accepts/${acceptedIndex}`);
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
for (const [entryIndex, entry] of candidate.closure.entries()) {
|
|
739
|
-
for (const [definitionIndex, definition] of entry.definitions.core.entries()) {
|
|
740
|
-
const owner = classes.get(Key.of(definition.class));
|
|
741
|
-
if (owner?.value.kind !== 'node' || owner.value.abstract) {
|
|
742
|
-
invalid('Core exact Class', 'COMPILED_SOURCE_INVALID', `/closure/${entryIndex}/definitions/core/${definitionIndex}/class`);
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
for (const [edgeIndex, edge] of entry.facts.core.entries()) {
|
|
746
|
-
const owner = classes.get(Key.of(edge.class));
|
|
747
|
-
if (owner?.value.kind !== 'edge' || owner.value.abstract) {
|
|
748
|
-
invalid('Core Edge exact Class', 'COMPILED_SOURCE_INVALID', `/closure/${entryIndex}/facts/core/${edgeIndex}/class`);
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
function validateDependencyCycles(candidate) {
|
|
754
|
-
const byOrigin = new Map(candidate.closure.map((entry, index) => [entry.origin, { entry, index }]));
|
|
755
|
-
const active = new Set();
|
|
756
|
-
const visited = new Set();
|
|
757
|
-
const frames = [];
|
|
758
|
-
const push = (origin, depth) => {
|
|
759
|
-
if (depth > dependencyLimits.depth) {
|
|
760
|
-
invalid('dependency depth limit', 'COMPILED_DEPENDENCY_LIMITS', `/closure/${byOrigin.get(origin)?.index ?? 0}/dependencies`);
|
|
761
|
-
}
|
|
762
|
-
active.add(origin);
|
|
763
|
-
frames.push({
|
|
764
|
-
origin,
|
|
765
|
-
depth,
|
|
766
|
-
dependencies: Object.values(byOrigin.get(origin)?.entry.dependencies ?? {}),
|
|
767
|
-
index: 0,
|
|
768
|
-
});
|
|
769
|
-
};
|
|
770
|
-
push(candidate.root.origin, 0);
|
|
771
|
-
while (frames.length > 0) {
|
|
772
|
-
const frame = frames.at(-1);
|
|
773
|
-
const dependency = frame.dependencies[frame.index++];
|
|
774
|
-
if (dependency === undefined) {
|
|
775
|
-
frames.pop();
|
|
776
|
-
active.delete(frame.origin);
|
|
777
|
-
visited.add(frame.origin);
|
|
778
|
-
continue;
|
|
779
|
-
}
|
|
780
|
-
if (active.has(dependency.origin)) {
|
|
781
|
-
invalid('dependency cycle', 'COMPILED_DEPENDENCY_CYCLE', `/closure/${byOrigin.get(dependency.origin)?.index ?? 0}/dependencies`);
|
|
782
|
-
}
|
|
783
|
-
if (!visited.has(dependency.origin))
|
|
784
|
-
push(dependency.origin, frame.depth + 1);
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
function walk(input, path, visit) {
|
|
788
|
-
if (isDefinitionRef(input)) {
|
|
789
|
-
visit(input, path);
|
|
790
|
-
return;
|
|
791
|
-
}
|
|
792
|
-
if (input === null || typeof input !== 'object')
|
|
793
|
-
return;
|
|
794
|
-
if (Array.isArray(input)) {
|
|
795
|
-
for (const [index, value] of input.entries())
|
|
796
|
-
walk(value, `${path}/${index}`, visit);
|
|
797
|
-
return;
|
|
798
|
-
}
|
|
799
|
-
for (const [key, value] of Object.entries(input))
|
|
800
|
-
walk(value, pointer(path, key), visit);
|
|
801
|
-
}
|
|
802
|
-
function program(input, programIndex, path, table) {
|
|
803
|
-
const value = object(input, `values[${programIndex}]`, path);
|
|
804
|
-
exact(value, ['root', 'nodes', 'patterns'], 'ValueProgram', path);
|
|
805
|
-
const nodesPath = `${path}/nodes`;
|
|
806
|
-
const nodes = array(value.nodes, 'ValueProgram nodes', nodesPath).map((node, index) => valueNode(node, index, `${nodesPath}/${index}`));
|
|
807
|
-
const root = index(value.root, nodes.length, 'ValueProgram root', `${path}/root`);
|
|
808
|
-
const patternsPath = `${path}/patterns`;
|
|
809
|
-
const patterns = array(value.patterns, 'ValueProgram patterns', patternsPath).map((item, position) => index(item, table.length, 'ValueProgram pattern', `${patternsPath}/${position}`));
|
|
810
|
-
const sources = patterns.map((index) => table[index].source);
|
|
811
|
-
unique(sources, 'patterns', patternsPath);
|
|
812
|
-
const available = new Set(sources);
|
|
813
|
-
for (const [nodeIndex, node] of nodes.entries()) {
|
|
814
|
-
if (isValueObject(node.schema)) {
|
|
815
|
-
const required = [node.schema.pattern, node.schema.fullMatch];
|
|
816
|
-
if (isValueObject(node.schema.patternProperties)) {
|
|
817
|
-
required.push(...Object.keys(node.schema.patternProperties));
|
|
818
|
-
}
|
|
819
|
-
for (const source of required) {
|
|
820
|
-
if (typeof source === 'string' && !available.has(source)) {
|
|
821
|
-
invalid('ValueProgram pattern binding', undefined, patternsPath);
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
for (const [name, child] of Object.entries(node.children))
|
|
826
|
-
index(child, nodes.length, 'ValueNode child', pointer(`${nodesPath}/${nodeIndex}/children`, name));
|
|
827
|
-
if (node.reference !== undefined)
|
|
828
|
-
index(node.reference, nodes.length, 'ValueNode reference', `${nodesPath}/${nodeIndex}/reference`);
|
|
829
|
-
}
|
|
830
|
-
return { root, nodes, patterns };
|
|
831
|
-
}
|
|
832
|
-
function valueNode(input, nodeIndex, path) {
|
|
833
|
-
const value = object(input, `nodes[${nodeIndex}]`, path);
|
|
834
|
-
exact(value, ['schema', 'children'], 'ValueNode', path, ['reference']);
|
|
835
|
-
const children = {};
|
|
836
|
-
const childrenPath = `${path}/children`;
|
|
837
|
-
for (const [name, child] of Object.entries(object(value.children, 'ValueNode children', childrenPath))) {
|
|
838
|
-
children[name] = integer(child, 'ValueNode child', pointer(childrenPath, name));
|
|
839
|
-
}
|
|
840
|
-
return {
|
|
841
|
-
schema: value.schema,
|
|
842
|
-
children,
|
|
843
|
-
...(value.reference === undefined
|
|
844
|
-
? {}
|
|
845
|
-
: { reference: integer(value.reference, 'reference', `${path}/reference`) }),
|
|
846
|
-
};
|
|
847
|
-
}
|
|
848
|
-
/**
|
|
849
|
-
* Admit one received pattern as data and return the machine compiled from its source. A received
|
|
850
|
-
* machine never decides membership: it may come from another compiler, from a host with other
|
|
851
|
-
* Unicode data, or from a forger, and the artifact carries no compiler version that could tell a
|
|
852
|
-
* current machine from those, so it is ignored rather than compared. Its source decides, through
|
|
853
|
-
* the same bounded `isIRegexp` and `compilePattern` that source resolution uses.
|
|
854
|
-
*/
|
|
855
|
-
function pattern(input, patternIndex, path, machines) {
|
|
856
|
-
const value = object(input, `patterns[${patternIndex}]`, path);
|
|
857
|
-
const { source } = Object.hasOwn(value, 'runs')
|
|
858
|
-
? runPattern(value, path)
|
|
859
|
-
: nfaPattern(value, path);
|
|
860
|
-
let machine = machines.get(source);
|
|
861
|
-
if (machine === undefined) {
|
|
862
|
-
if (!isIRegexp(source))
|
|
863
|
-
invalid('Pattern source', 'COMPILED_SOURCE_INVALID', `${path}/source`);
|
|
864
|
-
machine = compilePattern(source);
|
|
865
|
-
machines.set(source, machine);
|
|
866
|
-
}
|
|
867
|
-
return machine;
|
|
868
|
-
}
|
|
869
|
-
function nfaPattern(value, path) {
|
|
870
|
-
exact(value, ['source', 'start', 'states'], 'Pattern', path);
|
|
871
|
-
if (typeof value.source !== 'string')
|
|
872
|
-
invalid('Pattern source', undefined, `${path}/source`);
|
|
873
|
-
const statesPath = `${path}/states`;
|
|
874
|
-
const states = array(value.states, 'Pattern states', statesPath).map((item, stateIndex) => {
|
|
875
|
-
const statePath = `${statesPath}/${stateIndex}`;
|
|
876
|
-
const state = object(item, 'Pattern state', statePath);
|
|
877
|
-
exact(state, ['epsilon', 'transitions'], 'Pattern state', statePath, ['accepting']);
|
|
878
|
-
if (state.accepting !== undefined && state.accepting !== true)
|
|
879
|
-
invalid('accepting', undefined, `${statePath}/accepting`);
|
|
880
|
-
const epsilonPath = `${statePath}/epsilon`;
|
|
881
|
-
const transitionsPath = `${statePath}/transitions`;
|
|
882
|
-
return {
|
|
883
|
-
epsilon: array(state.epsilon, 'epsilon', epsilonPath).map((target, index) => integer(target, 'epsilon', `${epsilonPath}/${index}`)),
|
|
884
|
-
transitions: array(state.transitions, 'transitions', transitionsPath).map((transitionValue, transitionIndex) => {
|
|
885
|
-
const transitionPath = `${transitionsPath}/${transitionIndex}`;
|
|
886
|
-
const transition = object(transitionValue, 'transition', transitionPath);
|
|
887
|
-
exact(transition, ['to', 'ranges'], 'transition', transitionPath);
|
|
888
|
-
const rangesPath = `${transitionPath}/ranges`;
|
|
889
|
-
return {
|
|
890
|
-
to: integer(transition.to, 'transition target', `${transitionPath}/to`),
|
|
891
|
-
ranges: array(transition.ranges, 'ranges', rangesPath).map((rangeValue, rangeIndex) => {
|
|
892
|
-
const rangePath = `${rangesPath}/${rangeIndex}`;
|
|
893
|
-
const range = array(rangeValue, 'range', rangePath);
|
|
894
|
-
if (range.length !== 2)
|
|
895
|
-
invalid('range', undefined, rangePath);
|
|
896
|
-
const minimum = scalar(range[0], 'range minimum', `${rangePath}/0`);
|
|
897
|
-
const maximum = scalar(range[1], 'range maximum', `${rangePath}/1`);
|
|
898
|
-
if (minimum > maximum)
|
|
899
|
-
invalid('range order', undefined, rangePath);
|
|
900
|
-
return [minimum, maximum];
|
|
901
|
-
}),
|
|
902
|
-
};
|
|
903
|
-
}),
|
|
904
|
-
...(state.accepting === true ? { accepting: true } : {}),
|
|
905
|
-
};
|
|
906
|
-
});
|
|
907
|
-
const start = index(value.start, states.length, 'Pattern start', `${path}/start`);
|
|
908
|
-
for (const [stateIndex, state] of states.entries()) {
|
|
909
|
-
state.epsilon.forEach((target, indexValue) => index(target, states.length, 'epsilon', `${statesPath}/${stateIndex}/epsilon/${indexValue}`));
|
|
910
|
-
state.transitions.forEach(({ to }, transitionIndex) => index(to, states.length, 'transition', `${statesPath}/${stateIndex}/transitions/${transitionIndex}/to`));
|
|
911
|
-
}
|
|
912
|
-
return { source: value.source, start, states };
|
|
913
|
-
}
|
|
914
|
-
function runPattern(value, path) {
|
|
915
|
-
exact(value, ['source', 'runs'], 'RunPattern', path);
|
|
916
|
-
if (typeof value.source !== 'string')
|
|
917
|
-
invalid('Pattern source', undefined, `${path}/source`);
|
|
918
|
-
const entries = array(value.runs, 'scalar runs', `${path}/runs`);
|
|
919
|
-
if (entries.length === 0 || entries.length > 4096) {
|
|
920
|
-
invalid('scalar run count', undefined, `${path}/runs`);
|
|
921
|
-
}
|
|
922
|
-
const runs = entries.map((entry, position) => {
|
|
923
|
-
const runPath = `${path}/runs/${position}`;
|
|
924
|
-
const run = object(entry, 'scalar run', runPath);
|
|
925
|
-
exact(run, ['ranges', 'minimum'], 'scalar run', runPath, ['maximum']);
|
|
926
|
-
const minimum = boundedInteger(run.minimum, 0, 1000, 'run minimum', `${runPath}/minimum`);
|
|
927
|
-
const maximum = run.maximum === undefined
|
|
928
|
-
? undefined
|
|
929
|
-
: boundedInteger(run.maximum, minimum, 1000, 'run maximum', `${runPath}/maximum`);
|
|
930
|
-
if (position !== entries.length - 1 && minimum !== maximum) {
|
|
931
|
-
invalid('exact scalar prefix', undefined, `${runPath}/maximum`);
|
|
932
|
-
}
|
|
933
|
-
let previous = -1;
|
|
934
|
-
const ranges = array(run.ranges, 'scalar ranges', `${runPath}/ranges`).map((entry, index) => {
|
|
935
|
-
const rangePath = `${runPath}/ranges/${index}`;
|
|
936
|
-
const range = array(entry, 'scalar range', rangePath);
|
|
937
|
-
if (range.length !== 2)
|
|
938
|
-
invalid('scalar range', undefined, rangePath);
|
|
939
|
-
const minimum = scalar(range[0], 'range minimum', `${rangePath}/0`);
|
|
940
|
-
const maximum = scalar(range[1], 'range maximum', `${rangePath}/1`);
|
|
941
|
-
if (minimum > maximum ||
|
|
942
|
-
minimum <= previous ||
|
|
943
|
-
(minimum >= 0xd800 && minimum <= 0xdfff) ||
|
|
944
|
-
(maximum >= 0xd800 && maximum <= 0xdfff))
|
|
945
|
-
invalid('ordered scalar range', undefined, rangePath);
|
|
946
|
-
previous = maximum;
|
|
947
|
-
return [minimum, maximum];
|
|
948
|
-
});
|
|
949
|
-
return { ranges, minimum, ...(maximum === undefined ? {} : { maximum }) };
|
|
950
|
-
});
|
|
951
|
-
return { source: value.source, runs };
|
|
952
|
-
}
|
|
953
|
-
function dependency(input, label, path) {
|
|
954
|
-
const value = object(input, label, path);
|
|
955
|
-
exact(value, ['origin', 'revision'], label, path);
|
|
956
|
-
return {
|
|
957
|
-
origin: originValue(value.origin, label, `${path}/origin`),
|
|
958
|
-
revision: revisionValue(value.revision, label, `${path}/revision`),
|
|
959
|
-
};
|
|
960
|
-
}
|
|
961
|
-
function dependencyMap(input, path) {
|
|
962
|
-
const value = object(input, 'dependencies', path);
|
|
963
|
-
const accepted = Object.create(null);
|
|
964
|
-
for (const [alias, inputDependency] of Object.entries(value).sort(([left], [right]) => compare(left, right))) {
|
|
965
|
-
const aliasPath = pointer(path, alias);
|
|
966
|
-
if (!DEPENDENCY_ALIAS_PATTERN.test(alias) ||
|
|
967
|
-
alias === '__proto__' ||
|
|
968
|
-
alias === 'prototype' ||
|
|
969
|
-
alias === 'constructor') {
|
|
970
|
-
invalid('dependency alias', undefined, aliasPath);
|
|
971
|
-
}
|
|
972
|
-
accepted[alias] = dependency(inputDependency, `dependency ${alias}`, aliasPath);
|
|
973
|
-
}
|
|
974
|
-
return accepted;
|
|
975
|
-
}
|
|
976
|
-
function originValue(input, label, path) {
|
|
977
|
-
if (typeof input !== 'string' || !DOMAIN_ORIGIN_PATTERN.test(input))
|
|
978
|
-
invalid(label, undefined, path);
|
|
979
|
-
return input;
|
|
980
|
-
}
|
|
981
|
-
function revisionValue(input, label, path) {
|
|
982
|
-
if (typeof input !== 'string' || !DOMAIN_REVISION_PATTERN.test(input))
|
|
983
|
-
invalid(label, undefined, path);
|
|
984
|
-
return input;
|
|
985
|
-
}
|
|
986
|
-
function object(input, label, path) {
|
|
987
|
-
if (input === null || typeof input !== 'object' || Array.isArray(input))
|
|
988
|
-
invalid(label, undefined, path);
|
|
989
|
-
return input;
|
|
990
|
-
}
|
|
991
|
-
function array(input, label, path) {
|
|
992
|
-
if (!Array.isArray(input))
|
|
993
|
-
invalid(label, undefined, path);
|
|
994
|
-
return input;
|
|
995
|
-
}
|
|
996
|
-
function exact(value, required, label, path, optional = []) {
|
|
997
|
-
const allowed = new Set([...required, ...optional]);
|
|
998
|
-
const unknown = Object.keys(value)
|
|
999
|
-
.filter((key) => !allowed.has(key))
|
|
1000
|
-
.sort(compare)[0];
|
|
1001
|
-
if (unknown !== undefined)
|
|
1002
|
-
invalid(label, undefined, pointer(path, unknown));
|
|
1003
|
-
const missing = required.find((key) => !Object.hasOwn(value, key));
|
|
1004
|
-
if (missing !== undefined)
|
|
1005
|
-
invalid(label, undefined, pointer(path, missing));
|
|
1006
|
-
}
|
|
1007
|
-
function integer(input, label, path) {
|
|
1008
|
-
if (!Number.isSafeInteger(input) || input < 0)
|
|
1009
|
-
invalid(label, undefined, path);
|
|
1010
|
-
return input;
|
|
1011
|
-
}
|
|
1012
|
-
function boundedInteger(input, minimum, maximum, label, path) {
|
|
1013
|
-
const value = integer(input, label, path);
|
|
1014
|
-
if (value < minimum || value > maximum)
|
|
1015
|
-
invalid(label, undefined, path);
|
|
1016
|
-
return value;
|
|
1017
|
-
}
|
|
1018
|
-
function boolean(input, label, path) {
|
|
1019
|
-
if (typeof input !== 'boolean')
|
|
1020
|
-
invalid(label, undefined, path);
|
|
1021
|
-
return input;
|
|
1022
|
-
}
|
|
1023
|
-
function string(input, label, path) {
|
|
1024
|
-
if (typeof input !== 'string')
|
|
1025
|
-
invalid(label, undefined, path);
|
|
1026
|
-
return input;
|
|
1027
|
-
}
|
|
1028
|
-
function memberName(input, label, path) {
|
|
1029
|
-
const value = string(input, label, path);
|
|
1030
|
-
if (!MEMBER_NAME_PATTERN.test(value))
|
|
1031
|
-
invalid(label, undefined, path);
|
|
1032
|
-
return value;
|
|
1033
|
-
}
|
|
1034
|
-
function boundedString(input, minimum, maximum, label, path) {
|
|
1035
|
-
if (input === undefined)
|
|
1036
|
-
return;
|
|
1037
|
-
const value = string(input, label, path);
|
|
1038
|
-
if (value.length < minimum || value.length > maximum)
|
|
1039
|
-
invalid(label, undefined, path);
|
|
1040
|
-
}
|
|
1041
|
-
function description(input, label, path) {
|
|
1042
|
-
boundedString(input, 1, 1000, label, path);
|
|
1043
|
-
}
|
|
1044
|
-
function unique(values, label, path) {
|
|
1045
|
-
const seen = new Set();
|
|
1046
|
-
for (const [indexValue, value] of values.entries()) {
|
|
1047
|
-
if (seen.has(value))
|
|
1048
|
-
invalid(label, undefined, `${path}/${indexValue}`);
|
|
1049
|
-
seen.add(value);
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
function index(input, length, label, path) {
|
|
1053
|
-
const value = integer(input, label, path);
|
|
1054
|
-
if (value >= length)
|
|
1055
|
-
invalid(label, undefined, path);
|
|
1056
|
-
return value;
|
|
1057
|
-
}
|
|
1058
|
-
function scalar(input, label, path) {
|
|
1059
|
-
const value = integer(input, label, path);
|
|
1060
|
-
if (value > 0x10ffff)
|
|
1061
|
-
invalid(label, undefined, path);
|
|
1062
|
-
return value;
|
|
1063
|
-
}
|
|
1064
|
-
function invalid(label, code = 'COMPILED_STRUCTURE_INVALID', path = '') {
|
|
1065
|
-
return invalidCompiled(code, `Invalid compiled Schema ${label}.`, path);
|
|
1066
|
-
}
|
|
1067
|
-
function compare(left, right) {
|
|
1068
|
-
return left < right ? -1 : left > right ? 1 : 0;
|
|
1069
|
-
}
|
|
1070
72
|
function deepFreeze(input) {
|
|
1071
73
|
if (input === null || typeof input !== 'object' || Object.isFrozen(input))
|
|
1072
74
|
return input;
|