@astrale-os/kernel-core 0.9.0-beta.65 → 0.9.0-beta.66
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/auth/authority/admission/admission.d.ts +0 -1
- package/dist/auth/authority/admission/admission.js +8 -141
- package/dist/auth/authority/admission/references.d.ts +13 -0
- package/dist/auth/authority/admission/references.js +38 -0
- package/dist/auth/authority/admission/term.d.ts +6 -0
- package/dist/auth/authority/admission/term.js +60 -0
- package/dist/auth/authority/admission/wire.d.ts +8 -0
- package/dist/auth/authority/admission/wire.js +33 -0
- package/dist/graph/graph/index.d.ts +1 -1
- package/dist/graph/graph/index.js +1 -1
- package/dist/graph/graph/model/codec.js +3 -3
- package/dist/graph/graph/model/index.d.ts +1 -1
- package/dist/graph/graph/model/index.js +1 -1
- package/dist/graph/graph/model/model.d.ts +7 -7
- package/dist/graph/graph/model/model.js +6 -6
- package/dist/graph/graph/model/wire.d.ts +0 -20
- package/dist/graph/graph/model/wire.js +2 -2
- package/dist/graph/mutate/authoring/builder.d.ts +2 -2
- package/dist/graph/mutate/authoring/builder.js +2 -2
- package/dist/graph/mutate/index.d.ts +1 -1
- package/dist/graph/mutate/language/codec.js +3 -3
- package/dist/graph/mutate/language/model.d.ts +4 -4
- package/dist/graph/mutate/result/index.d.ts +3 -3
- package/dist/graph/mutate/result/index.js +5 -5
- package/dist/graph/node/identity/id.d.ts +0 -3
- package/dist/graph/node/identity/id.js +0 -4
- package/dist/graph/query/language/codec.js +3 -3
- package/dist/graph/query/language/model.d.ts +3 -3
- package/dist/graph/reconcile/condition/model.d.ts +2 -2
- package/dist/graph/reconcile/condition/references.d.ts +0 -1
- package/dist/graph/reconcile/condition/references.js +4 -4
- package/dist/graph/reconcile/correspondence.d.ts +9 -8
- package/dist/graph/reconcile/evidence.d.ts +2 -2
- package/dist/graph/reconcile/mutation/assess.d.ts +2 -1
- package/dist/graph/reconcile/observation.d.ts +4 -3
- package/dist/graph/reconcile/planning/context.d.ts +3 -3
- package/dist/graph/reconcile/planning/model.d.ts +4 -4
- package/dist/schema/callables/{view-for.d.ts → entrypoint.d.ts} +7 -5
- package/dist/schema/callables/entrypoint.js +12 -0
- package/dist/schema/callables/function.d.ts +0 -120
- package/dist/schema/callables/index.d.ts +1 -1
- package/dist/schema/callables/index.js +1 -1
- package/dist/schema/callables/view.d.ts +2 -24
- package/dist/schema/domain/domain.d.ts +2 -121
- package/dist/schema/domain/domain.js +3 -0
- package/dist/schema/identity/identity.d.ts +0 -8
- package/dist/schema/kernel/projection/core.d.ts +7 -0
- package/dist/schema/kernel/projection/core.js +51 -0
- package/dist/schema/kernel/projection/definitions.d.ts +13 -0
- package/dist/schema/kernel/projection/definitions.js +71 -0
- package/dist/schema/kernel/projection/methods.d.ts +5 -0
- package/dist/schema/kernel/projection/methods.js +41 -0
- package/dist/schema/kernel/projection/part.d.ts +34 -0
- package/dist/schema/kernel/projection/part.js +42 -0
- package/dist/schema/kernel/projection/paths.d.ts +6 -0
- package/dist/schema/kernel/projection/{keys.js → paths.js} +11 -12
- package/dist/schema/kernel/projection/project.d.ts +1 -1
- package/dist/schema/kernel/projection/project.js +16 -290
- package/dist/schema/kernel/projection/properties.d.ts +11 -0
- package/dist/schema/kernel/projection/properties.js +36 -0
- package/dist/schema/kernel/projection/relations.d.ts +7 -0
- package/dist/schema/kernel/projection/relations.js +49 -0
- package/dist/schema/kernel/projection/types.d.ts +4 -4
- package/dist/schema/kernel/schema.d.ts +74 -357
- package/dist/schema/kernel/schema.js +3 -2
- package/dist/schema/kernel/syscalls/contracts/blob.d.ts +12 -2
- package/dist/schema/kernel/syscalls/contracts/blob.js +10 -2
- package/dist/schema/kernel/syscalls/contracts/delegate.d.ts +0 -4
- package/dist/schema/kernel/syscalls/contracts/delegate.js +0 -3
- package/dist/schema/kernel/syscalls/contracts/index.d.ts +1 -1
- package/dist/schema/kernel/syscalls/contracts/index.js +1 -1
- package/dist/schema/kernel/syscalls/contracts/install.d.ts +3 -20
- package/dist/schema/kernel/syscalls/contracts/install.js +0 -2
- package/dist/schema/kernel/syscalls/contracts/installation.d.ts +0 -36
- package/dist/schema/kernel/syscalls/contracts/installation.js +3 -3
- package/dist/schema/kernel/syscalls/contracts/view-resolve.d.ts +3 -14
- package/dist/schema/kernel/syscalls/contracts/view-resolve.js +3 -18
- package/dist/schema/kernel/syscalls/declarations/delegate.d.ts +0 -4
- package/dist/schema/kernel/syscalls/declarations/download.d.ts +5 -0
- package/dist/schema/kernel/syscalls/declarations/index.d.ts +6 -24
- package/dist/schema/kernel/syscalls/declarations/install.d.ts +0 -8
- package/dist/schema/kernel/syscalls/declarations/view-resolve.d.ts +1 -12
- package/dist/schema/kernel/syscalls/descriptors/identity.d.ts +0 -4
- package/dist/schema/kernel/syscalls/descriptors/results/view-resolution.d.ts +2 -13
- package/dist/schema/kernel/syscalls/descriptors/results/view-resolution.js +4 -119
- package/dist/schema/kernel/syscalls/descriptors/view.d.ts +1 -12
- package/package.json +2 -2
- package/dist/schema/callables/view-for.js +0 -12
- package/dist/schema/kernel/projection/keys.d.ts +0 -3
- package/dist/schema/kernel/syscalls/contracts/legacy/delegate.d.ts +0 -5
- package/dist/schema/kernel/syscalls/contracts/legacy/delegate.js +0 -25
- package/dist/schema/kernel/syscalls/contracts/legacy/install.d.ts +0 -22
- package/dist/schema/kernel/syscalls/contracts/legacy/install.js +0 -31
|
@@ -8,7 +8,6 @@ export declare const limits: {
|
|
|
8
8
|
readonly classesPerRelation: 1024;
|
|
9
9
|
readonly repeatMaximum: 16;
|
|
10
10
|
};
|
|
11
|
-
export declare const MAX_BOOLEAN_OPERANDS: 512;
|
|
12
11
|
export declare function admitAuthorityExpr(input: portable.Value): AuthorityExpr;
|
|
13
12
|
/** Internal constructor admission: the outer identity binder binds subject; no local escapes into it. */
|
|
14
13
|
export declare function admitBinderBody(input: portable.Value): AuthorityExpr;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { patterns } from '@astrale-os/kernel-dsl/v1/addressing';
|
|
2
1
|
import { isNodeId } from '../../../graph/node/index.js';
|
|
3
|
-
import { AuthValueError } from '../../error.js';
|
|
4
2
|
import { ownsExpression } from '../ownership.optimization.js';
|
|
3
|
+
import { classRef } from './references.js';
|
|
4
|
+
import { localId, term } from './term.js';
|
|
5
|
+
import { array, exact, invalid, record, required } from './wire.js';
|
|
5
6
|
export const limits = Object.freeze({
|
|
6
7
|
expressionDepth: 64,
|
|
7
8
|
operandsPerExpression: 512,
|
|
@@ -10,7 +11,7 @@ export const limits = Object.freeze({
|
|
|
10
11
|
classesPerRelation: 1024,
|
|
11
12
|
repeatMaximum: 16,
|
|
12
13
|
});
|
|
13
|
-
|
|
14
|
+
const MAX_BOOLEAN_OPERANDS = limits.operandsPerExpression;
|
|
14
15
|
export function admitAuthorityExpr(input) {
|
|
15
16
|
return admit(input, '/predicate', new Set(), false, 0);
|
|
16
17
|
}
|
|
@@ -67,7 +68,7 @@ function admit(input, path, locals, subjectBound, depth) {
|
|
|
67
68
|
return {
|
|
68
69
|
op: 'related',
|
|
69
70
|
source: term(value.source, `${path}/source`, locals, subjectBound),
|
|
70
|
-
via: array(value.via, `${path}/via`, 1, limits.classesPerRelation).map((entry, index) =>
|
|
71
|
+
via: array(value.via, `${path}/via`, 1, limits.classesPerRelation).map((entry, index) => classRef(entry, `${path}/via/${index}`)),
|
|
71
72
|
target: term(value.target, `${path}/target`, locals, subjectBound),
|
|
72
73
|
...(hasRepeat ? { repeat: repeat(value.repeat, `${path}/repeat`) } : {}),
|
|
73
74
|
};
|
|
@@ -96,11 +97,11 @@ function admit(input, path, locals, subjectBound, depth) {
|
|
|
96
97
|
return {
|
|
97
98
|
op: 'instance-of',
|
|
98
99
|
node: term(value.node, `${path}/node`, locals, subjectBound),
|
|
99
|
-
class:
|
|
100
|
+
class: classRef(value.class, `${path}/class`),
|
|
100
101
|
};
|
|
101
102
|
case 'edge-class':
|
|
102
103
|
exact(value, ['class', 'op'], path);
|
|
103
|
-
return { op: 'edge-class', class:
|
|
104
|
+
return { op: 'edge-class', class: classRef(value.class, `${path}/class`) };
|
|
104
105
|
case 'class-authority':
|
|
105
106
|
exact(value, ['class', 'evidence', 'identity', 'op', 'operation'], path);
|
|
106
107
|
return {
|
|
@@ -114,55 +115,6 @@ function admit(input, path, locals, subjectBound, depth) {
|
|
|
114
115
|
invalid(`${path}/op`, 'Unsupported authority operation');
|
|
115
116
|
}
|
|
116
117
|
}
|
|
117
|
-
function term(input, path, locals, subjectBound) {
|
|
118
|
-
const value = record(input, path);
|
|
119
|
-
switch (value.kind) {
|
|
120
|
-
case 'input':
|
|
121
|
-
exact(value, ['input', 'kind'], path);
|
|
122
|
-
if (value.input !== 'object' && value.input !== 'source' && value.input !== 'target') {
|
|
123
|
-
invalid(`${path}/input`, 'Expected object, source, or target');
|
|
124
|
-
}
|
|
125
|
-
return { kind: 'input', input: value.input };
|
|
126
|
-
case 'node':
|
|
127
|
-
exact(value, ['id', 'kind'], path);
|
|
128
|
-
if (!isNodeId(value.id))
|
|
129
|
-
invalid(`${path}/id`, 'Expected a canonical NodeId');
|
|
130
|
-
return { kind: 'node', id: value.id };
|
|
131
|
-
case 'class':
|
|
132
|
-
exact(value, ['kind', 'ref'], path);
|
|
133
|
-
return { kind: 'class', ref: classRef(value.ref, `${path}/ref`) };
|
|
134
|
-
case 'domain':
|
|
135
|
-
exact(value, ['kind', 'origin'], path);
|
|
136
|
-
return { kind: 'domain', origin: domainOrigin(value.origin, `${path}/origin`) };
|
|
137
|
-
case 'ref': {
|
|
138
|
-
exact(value, ['kind', 'ref'], path);
|
|
139
|
-
const ref = absoluteRef(value.ref, `${path}/ref`);
|
|
140
|
-
if (ref.kind === 'core')
|
|
141
|
-
return { kind: 'ref', ref: coreRef(value.ref, `${path}/ref`) };
|
|
142
|
-
if (!['class', 'function', 'policy', 'view'].includes(ref.kind))
|
|
143
|
-
invalid(`${path}/ref/kind`, 'Expected a projected Schema member');
|
|
144
|
-
definitionName(ref.name, `${path}/ref/name`);
|
|
145
|
-
return { kind: 'ref', ref: ref };
|
|
146
|
-
}
|
|
147
|
-
case 'core':
|
|
148
|
-
exact(value, ['kind', 'ref'], path);
|
|
149
|
-
return { kind: 'core', ref: coreRef(value.ref, `${path}/ref`) };
|
|
150
|
-
case 'local': {
|
|
151
|
-
exact(value, ['id', 'kind'], path);
|
|
152
|
-
const id = localId(value.id, `${path}/id`);
|
|
153
|
-
if (!locals.has(id))
|
|
154
|
-
invalid(`${path}/id`, `Local ${id} is outside its lexical scope`);
|
|
155
|
-
return { kind: 'local', id };
|
|
156
|
-
}
|
|
157
|
-
case 'subject':
|
|
158
|
-
exact(value, ['kind'], path);
|
|
159
|
-
if (!subjectBound)
|
|
160
|
-
invalid(path, 'Binder subject is outside its lexical scope');
|
|
161
|
-
return { kind: 'subject' };
|
|
162
|
-
default:
|
|
163
|
-
invalid(`${path}/kind`, 'Unsupported authority term');
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
118
|
function localDeclaration(input, path) {
|
|
167
119
|
const value = record(input, path);
|
|
168
120
|
const id = localId(value.id, `${path}/id`);
|
|
@@ -172,7 +124,7 @@ function localDeclaration(input, path) {
|
|
|
172
124
|
}
|
|
173
125
|
if (value.kind === 'classes') {
|
|
174
126
|
exact(value, ['classes', 'id', 'kind'], path);
|
|
175
|
-
const classes = array(value.classes, `${path}/classes`, 1, limits.classesPerLocal).map((entry, index) =>
|
|
127
|
+
const classes = array(value.classes, `${path}/classes`, 1, limits.classesPerLocal).map((entry, index) => classRef(entry, `${path}/classes/${index}`));
|
|
176
128
|
return {
|
|
177
129
|
id,
|
|
178
130
|
kind: 'classes',
|
|
@@ -193,61 +145,6 @@ function repeat(input, path) {
|
|
|
193
145
|
}
|
|
194
146
|
return { min, max };
|
|
195
147
|
}
|
|
196
|
-
function classRef(input, path) {
|
|
197
|
-
const value = absoluteRef(input, path);
|
|
198
|
-
if (value.kind !== 'class')
|
|
199
|
-
invalid(`${path}/kind`, 'Expected class');
|
|
200
|
-
definitionName(value.name, `${path}/name`);
|
|
201
|
-
return value;
|
|
202
|
-
}
|
|
203
|
-
function nodeClassRef(input, path) {
|
|
204
|
-
const value = absoluteRef(input, path);
|
|
205
|
-
if (value.kind !== 'class')
|
|
206
|
-
invalid(`${path}/kind`, 'Expected class');
|
|
207
|
-
definitionName(value.name, `${path}/name`);
|
|
208
|
-
return value;
|
|
209
|
-
}
|
|
210
|
-
function edgeClassRef(input, path) {
|
|
211
|
-
const value = absoluteRef(input, path);
|
|
212
|
-
if (value.kind !== 'class')
|
|
213
|
-
invalid(`${path}/kind`, 'Expected class');
|
|
214
|
-
definitionName(value.name, `${path}/name`);
|
|
215
|
-
return value;
|
|
216
|
-
}
|
|
217
|
-
function absoluteRef(input, path) {
|
|
218
|
-
const value = record(input, path);
|
|
219
|
-
exact(value, ['kind', 'name', 'origin'], path);
|
|
220
|
-
const origin = domainOrigin(value.origin, `${path}/origin`);
|
|
221
|
-
if (typeof value.kind !== 'string')
|
|
222
|
-
invalid(`${path}/kind`, 'Expected a reference kind');
|
|
223
|
-
if (typeof value.name !== 'string')
|
|
224
|
-
invalid(`${path}/name`, 'Expected a reference name');
|
|
225
|
-
return { origin, kind: value.kind, name: value.name };
|
|
226
|
-
}
|
|
227
|
-
function definitionName(input, path) {
|
|
228
|
-
if (!patterns.memberName.test(input))
|
|
229
|
-
invalid(path, 'Expected a Definition member name');
|
|
230
|
-
}
|
|
231
|
-
function coreRef(input, path) {
|
|
232
|
-
const value = absoluteRef(input, path);
|
|
233
|
-
if (value.kind !== 'core')
|
|
234
|
-
invalid(`${path}/kind`, 'Expected core');
|
|
235
|
-
if (!patterns.coreSlug.test(value.name))
|
|
236
|
-
invalid(`${path}/name`, 'Expected a Core slug');
|
|
237
|
-
return value;
|
|
238
|
-
}
|
|
239
|
-
function domainOrigin(input, path) {
|
|
240
|
-
if (typeof input !== 'string' || !patterns.origin.test(input)) {
|
|
241
|
-
invalid(path, 'Expected a canonical Domain origin');
|
|
242
|
-
}
|
|
243
|
-
return input;
|
|
244
|
-
}
|
|
245
|
-
function localId(input, path) {
|
|
246
|
-
if (!Number.isSafeInteger(input) || input < 0) {
|
|
247
|
-
invalid(path, 'Expected a non-negative safe integer');
|
|
248
|
-
}
|
|
249
|
-
return input;
|
|
250
|
-
}
|
|
251
148
|
function operation(input, path) {
|
|
252
149
|
if (input !== 'create' &&
|
|
253
150
|
input !== 'read' &&
|
|
@@ -263,33 +160,3 @@ function evidence(input, path) {
|
|
|
263
160
|
invalid(path, 'Expected allowed or owner');
|
|
264
161
|
return input;
|
|
265
162
|
}
|
|
266
|
-
function record(input, path) {
|
|
267
|
-
if (input === undefined || input === null || Array.isArray(input) || typeof input !== 'object') {
|
|
268
|
-
invalid(path, 'Expected an object');
|
|
269
|
-
}
|
|
270
|
-
return input;
|
|
271
|
-
}
|
|
272
|
-
function array(input, path, minimum, maximum) {
|
|
273
|
-
if (!Array.isArray(input) || input.length < minimum || input.length > maximum) {
|
|
274
|
-
invalid(path, `Expected ${minimum}-${maximum} entries`);
|
|
275
|
-
}
|
|
276
|
-
return input;
|
|
277
|
-
}
|
|
278
|
-
function required(input, path) {
|
|
279
|
-
if (input === undefined)
|
|
280
|
-
invalid(path, 'Expected a value');
|
|
281
|
-
return input;
|
|
282
|
-
}
|
|
283
|
-
function exact(value, expected, path) {
|
|
284
|
-
const actual = Object.keys(value).sort(compare);
|
|
285
|
-
const wanted = [...expected].sort(compare);
|
|
286
|
-
if (actual.length !== wanted.length || actual.some((key, index) => key !== wanted[index])) {
|
|
287
|
-
invalid(path, `Expected exactly ${expected.join(', ')}`);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
function compare(left, right) {
|
|
291
|
-
return left < right ? -1 : left > right ? 1 : 0;
|
|
292
|
-
}
|
|
293
|
-
function invalid(path, message) {
|
|
294
|
-
throw new AuthValueError('AUTHORITY_PREDICATE_INVALID', message, path);
|
|
295
|
-
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Key } from '@astrale-os/kernel-dsl/v1';
|
|
2
|
+
import type { ClassRef, CoreRef } from '@astrale-os/kernel-dsl/v1/addressing';
|
|
3
|
+
import type * as portable from '@astrale-os/kernel-dsl/value';
|
|
4
|
+
/** One `{ origin, kind, name }` reference with a canonical origin and an unchecked kind and name. */
|
|
5
|
+
export declare function absoluteRef(input: portable.Value | undefined, path: string): {
|
|
6
|
+
readonly origin: Key.Origin;
|
|
7
|
+
readonly kind: string;
|
|
8
|
+
readonly name: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function classRef(input: portable.Value | undefined, path: string): ClassRef;
|
|
11
|
+
export declare function coreRef(input: portable.Value | undefined, path: string): CoreRef;
|
|
12
|
+
export declare function definitionName(input: string, path: string): void;
|
|
13
|
+
export declare function domainOrigin(input: portable.Value | undefined, path: string): Key.Origin;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { patterns } from '@astrale-os/kernel-dsl/v1/addressing';
|
|
2
|
+
import { exact, invalid, record } from './wire.js';
|
|
3
|
+
/** One `{ origin, kind, name }` reference with a canonical origin and an unchecked kind and name. */
|
|
4
|
+
export function absoluteRef(input, path) {
|
|
5
|
+
const value = record(input, path);
|
|
6
|
+
exact(value, ['kind', 'name', 'origin'], path);
|
|
7
|
+
const origin = domainOrigin(value.origin, `${path}/origin`);
|
|
8
|
+
if (typeof value.kind !== 'string')
|
|
9
|
+
invalid(`${path}/kind`, 'Expected a reference kind');
|
|
10
|
+
if (typeof value.name !== 'string')
|
|
11
|
+
invalid(`${path}/name`, 'Expected a reference name');
|
|
12
|
+
return { origin, kind: value.kind, name: value.name };
|
|
13
|
+
}
|
|
14
|
+
export function classRef(input, path) {
|
|
15
|
+
const value = absoluteRef(input, path);
|
|
16
|
+
if (value.kind !== 'class')
|
|
17
|
+
invalid(`${path}/kind`, 'Expected class');
|
|
18
|
+
definitionName(value.name, `${path}/name`);
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
export function coreRef(input, path) {
|
|
22
|
+
const value = absoluteRef(input, path);
|
|
23
|
+
if (value.kind !== 'core')
|
|
24
|
+
invalid(`${path}/kind`, 'Expected core');
|
|
25
|
+
if (!patterns.coreSlug.test(value.name))
|
|
26
|
+
invalid(`${path}/name`, 'Expected a Core slug');
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
export function definitionName(input, path) {
|
|
30
|
+
if (!patterns.memberName.test(input))
|
|
31
|
+
invalid(path, 'Expected a Definition member name');
|
|
32
|
+
}
|
|
33
|
+
export function domainOrigin(input, path) {
|
|
34
|
+
if (typeof input !== 'string' || !patterns.origin.test(input)) {
|
|
35
|
+
invalid(path, 'Expected a canonical Domain origin');
|
|
36
|
+
}
|
|
37
|
+
return input;
|
|
38
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type * as portable from '@astrale-os/kernel-dsl/value';
|
|
2
|
+
import type { Term } from '../language/index.js';
|
|
3
|
+
/** Admit one term; `locals` and `subjectBound` are the lexical scope it may reference. */
|
|
4
|
+
export declare function term(input: portable.Value | undefined, path: string, locals: ReadonlySet<number>, subjectBound: boolean): Term;
|
|
5
|
+
/** A local id or repeat bound: a non-negative safe integer. */
|
|
6
|
+
export declare function localId(input: portable.Value | undefined, path: string): number;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { isNodeId } from '../../../graph/node/index.js';
|
|
2
|
+
import { absoluteRef, classRef, coreRef, definitionName, domainOrigin } from './references.js';
|
|
3
|
+
import { exact, invalid, record } from './wire.js';
|
|
4
|
+
/** Admit one term; `locals` and `subjectBound` are the lexical scope it may reference. */
|
|
5
|
+
export function term(input, path, locals, subjectBound) {
|
|
6
|
+
const value = record(input, path);
|
|
7
|
+
switch (value.kind) {
|
|
8
|
+
case 'input':
|
|
9
|
+
exact(value, ['input', 'kind'], path);
|
|
10
|
+
if (value.input !== 'object' && value.input !== 'source' && value.input !== 'target') {
|
|
11
|
+
invalid(`${path}/input`, 'Expected object, source, or target');
|
|
12
|
+
}
|
|
13
|
+
return { kind: 'input', input: value.input };
|
|
14
|
+
case 'node':
|
|
15
|
+
exact(value, ['id', 'kind'], path);
|
|
16
|
+
if (!isNodeId(value.id))
|
|
17
|
+
invalid(`${path}/id`, 'Expected a canonical NodeId');
|
|
18
|
+
return { kind: 'node', id: value.id };
|
|
19
|
+
case 'class':
|
|
20
|
+
exact(value, ['kind', 'ref'], path);
|
|
21
|
+
return { kind: 'class', ref: classRef(value.ref, `${path}/ref`) };
|
|
22
|
+
case 'domain':
|
|
23
|
+
exact(value, ['kind', 'origin'], path);
|
|
24
|
+
return { kind: 'domain', origin: domainOrigin(value.origin, `${path}/origin`) };
|
|
25
|
+
case 'ref': {
|
|
26
|
+
exact(value, ['kind', 'ref'], path);
|
|
27
|
+
const ref = absoluteRef(value.ref, `${path}/ref`);
|
|
28
|
+
if (ref.kind === 'core')
|
|
29
|
+
return { kind: 'ref', ref: coreRef(value.ref, `${path}/ref`) };
|
|
30
|
+
if (!['class', 'function', 'policy', 'view'].includes(ref.kind))
|
|
31
|
+
invalid(`${path}/ref/kind`, 'Expected a projected Schema member');
|
|
32
|
+
definitionName(ref.name, `${path}/ref/name`);
|
|
33
|
+
return { kind: 'ref', ref: ref };
|
|
34
|
+
}
|
|
35
|
+
case 'core':
|
|
36
|
+
exact(value, ['kind', 'ref'], path);
|
|
37
|
+
return { kind: 'core', ref: coreRef(value.ref, `${path}/ref`) };
|
|
38
|
+
case 'local': {
|
|
39
|
+
exact(value, ['id', 'kind'], path);
|
|
40
|
+
const id = localId(value.id, `${path}/id`);
|
|
41
|
+
if (!locals.has(id))
|
|
42
|
+
invalid(`${path}/id`, `Local ${id} is outside its lexical scope`);
|
|
43
|
+
return { kind: 'local', id };
|
|
44
|
+
}
|
|
45
|
+
case 'subject':
|
|
46
|
+
exact(value, ['kind'], path);
|
|
47
|
+
if (!subjectBound)
|
|
48
|
+
invalid(path, 'Binder subject is outside its lexical scope');
|
|
49
|
+
return { kind: 'subject' };
|
|
50
|
+
default:
|
|
51
|
+
invalid(`${path}/kind`, 'Unsupported authority term');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** A local id or repeat bound: a non-negative safe integer. */
|
|
55
|
+
export function localId(input, path) {
|
|
56
|
+
if (!Number.isSafeInteger(input) || input < 0) {
|
|
57
|
+
invalid(path, 'Expected a non-negative safe integer');
|
|
58
|
+
}
|
|
59
|
+
return input;
|
|
60
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type * as portable from '@astrale-os/kernel-dsl/value';
|
|
2
|
+
/** Fail admission at one JSON-pointer path with the stable Authority predicate code. */
|
|
3
|
+
export declare function invalid(path: string, message: string): never;
|
|
4
|
+
export declare function record(input: portable.Value | undefined, path: string): portable.Object;
|
|
5
|
+
export declare function array(input: portable.Value | undefined, path: string, minimum: number, maximum: number): readonly portable.Value[];
|
|
6
|
+
export declare function required(input: portable.Value | undefined, path: string): portable.Value;
|
|
7
|
+
/** Reject a record whose own keys differ from `expected`, in any order. */
|
|
8
|
+
export declare function exact(value: portable.Object, expected: readonly string[], path: string): void;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AuthValueError } from '../../error.js';
|
|
2
|
+
/** Fail admission at one JSON-pointer path with the stable Authority predicate code. */
|
|
3
|
+
export function invalid(path, message) {
|
|
4
|
+
throw new AuthValueError('AUTHORITY_PREDICATE_INVALID', message, path);
|
|
5
|
+
}
|
|
6
|
+
export function record(input, path) {
|
|
7
|
+
if (input === undefined || input === null || Array.isArray(input) || typeof input !== 'object') {
|
|
8
|
+
invalid(path, 'Expected an object');
|
|
9
|
+
}
|
|
10
|
+
return input;
|
|
11
|
+
}
|
|
12
|
+
export function array(input, path, minimum, maximum) {
|
|
13
|
+
if (!Array.isArray(input) || input.length < minimum || input.length > maximum) {
|
|
14
|
+
invalid(path, `Expected ${minimum}-${maximum} entries`);
|
|
15
|
+
}
|
|
16
|
+
return input;
|
|
17
|
+
}
|
|
18
|
+
export function required(input, path) {
|
|
19
|
+
if (input === undefined)
|
|
20
|
+
invalid(path, 'Expected a value');
|
|
21
|
+
return input;
|
|
22
|
+
}
|
|
23
|
+
/** Reject a record whose own keys differ from `expected`, in any order. */
|
|
24
|
+
export function exact(value, expected, path) {
|
|
25
|
+
const actual = Object.keys(value).sort(compare);
|
|
26
|
+
const wanted = [...expected].sort(compare);
|
|
27
|
+
if (actual.length !== wanted.length || actual.some((key, index) => key !== wanted[index])) {
|
|
28
|
+
invalid(path, `Expected exactly ${expected.join(', ')}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function compare(left, right) {
|
|
32
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
33
|
+
}
|
|
@@ -4,7 +4,7 @@ export type { Delta, DeltaConflict, DeltaResult } from './delta/index.js';
|
|
|
4
4
|
export type { MergeConflict, MergeResult } from './merge/index.js';
|
|
5
5
|
export { GraphData, GraphDataDecodeError, GraphSpec, GraphSpecDecodeError } from './model/index.js';
|
|
6
6
|
export type { AnonymousNodeSpec, GraphDataJson, GraphSpecEdge, GraphSpecEndpoint, GraphSpecJson, GraphSpecNode, } from './model/index.js';
|
|
7
|
-
export {
|
|
7
|
+
export { LocalAlias, isLocalAlias } from './model/index.js';
|
|
8
8
|
export type { GraphAdmissionContext, GraphClassInfo, GraphDiagnostic } from './admission/index.js';
|
|
9
9
|
export { GraphAdmissionError } from './admission/index.js';
|
|
10
10
|
export type { GraphEdges, GraphNodes } from './indexes/index.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Stable aggregate facade over Graph model, admission, indexes, delta, and merge. */
|
|
2
2
|
export { Graph } from './graph.js';
|
|
3
3
|
export { GraphData, GraphDataDecodeError, GraphSpec, GraphSpecDecodeError } from './model/index.js';
|
|
4
|
-
export {
|
|
4
|
+
export { LocalAlias, isLocalAlias } from './model/index.js';
|
|
5
5
|
export { GraphAdmissionError } from './admission/index.js';
|
|
@@ -5,7 +5,7 @@ import { node as constructNode, NodeId } from '../../node/index.js';
|
|
|
5
5
|
import { NodePath } from '../../path/index.js';
|
|
6
6
|
import { normalizeProperties } from '../../properties/index.js';
|
|
7
7
|
import { decodeWire } from '../../wire.js';
|
|
8
|
-
import {
|
|
8
|
+
import { isLocalAlias, LocalAlias } from './model.js';
|
|
9
9
|
import { graphSpecSchema } from './wire.js';
|
|
10
10
|
export class GraphDataDecodeError extends TypeError {
|
|
11
11
|
path;
|
|
@@ -124,10 +124,10 @@ function decodeEndpoint(input, path) {
|
|
|
124
124
|
return Object.freeze({ created: binding(input.created, `${path}/created`) });
|
|
125
125
|
}
|
|
126
126
|
function binding(input, path) {
|
|
127
|
-
if (!
|
|
127
|
+
if (!isLocalAlias(input)) {
|
|
128
128
|
specInvalid(path, 'Expected a local binding name of at most 64 characters');
|
|
129
129
|
}
|
|
130
|
-
return
|
|
130
|
+
return LocalAlias(input);
|
|
131
131
|
}
|
|
132
132
|
function validateGraphSpec(nodes, edges) {
|
|
133
133
|
const ids = new Set();
|
|
@@ -13,5 +13,5 @@ export declare const GraphSpec: {
|
|
|
13
13
|
encode(spec: GraphSpecValue): GraphSpecJson;
|
|
14
14
|
};
|
|
15
15
|
export type { AnonymousNodeSpec, GraphSpecEdge, GraphSpecEndpoint, GraphSpecJson, GraphSpecNode, } from './model.js';
|
|
16
|
-
export {
|
|
16
|
+
export { LocalAlias, isLocalAlias } from './model.js';
|
|
17
17
|
export { GraphSpecDecodeError } from './codec.js';
|
|
@@ -2,5 +2,5 @@ import { decodeGraphData, decodeGraphSpec, encodeGraphData, encodeGraphSpec } fr
|
|
|
2
2
|
export const GraphData = Object.freeze({ decode: decodeGraphData, encode: encodeGraphData });
|
|
3
3
|
export { GraphDataDecodeError } from './codec.js';
|
|
4
4
|
export const GraphSpec = Object.freeze({ decode: decodeGraphSpec, encode: encodeGraphSpec });
|
|
5
|
-
export {
|
|
5
|
+
export { LocalAlias, isLocalAlias } from './model.js';
|
|
6
6
|
export { GraphSpecDecodeError } from './codec.js';
|
|
@@ -2,21 +2,21 @@ import type { EdgeSpec } from '../../edge/index.js';
|
|
|
2
2
|
import type { Node, NodeId, NodeSpec } from '../../node/index.js';
|
|
3
3
|
import type { NodePath } from '../../path/index.js';
|
|
4
4
|
import type { Properties } from '../../properties/index.js';
|
|
5
|
-
declare const
|
|
5
|
+
declare const LOCAL_ALIAS_BRAND: unique symbol;
|
|
6
6
|
/** A graph-local lexical name. It is never Node identity. */
|
|
7
|
-
export type
|
|
8
|
-
readonly [
|
|
7
|
+
export type LocalAlias = string & {
|
|
8
|
+
readonly [LOCAL_ALIAS_BRAND]: true;
|
|
9
9
|
};
|
|
10
|
-
export declare function
|
|
11
|
-
export declare function
|
|
10
|
+
export declare function LocalAlias(input: string): LocalAlias;
|
|
11
|
+
export declare function isLocalAlias(input: unknown): input is LocalAlias;
|
|
12
12
|
export interface AnonymousNodeSpec extends NodeSpec {
|
|
13
|
-
readonly as:
|
|
13
|
+
readonly as: LocalAlias;
|
|
14
14
|
}
|
|
15
15
|
export type GraphSpecNode = Node | AnonymousNodeSpec;
|
|
16
16
|
export type GraphSpecEndpoint = NodeId | {
|
|
17
17
|
readonly path: NodePath;
|
|
18
18
|
} | {
|
|
19
|
-
readonly created:
|
|
19
|
+
readonly created: LocalAlias;
|
|
20
20
|
};
|
|
21
21
|
export type GraphSpecEdge = EdgeSpec<GraphSpecEndpoint>;
|
|
22
22
|
/** Detached structural graph values, including graph-local anonymous Nodes. */
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
const
|
|
2
|
-
export function
|
|
3
|
-
if (!
|
|
4
|
-
throw new TypeError(`Invalid local
|
|
1
|
+
const LOCAL_ALIAS_PATTERN = /^[A-Za-z][A-Za-z0-9_]{0,63}$/u;
|
|
2
|
+
export function LocalAlias(input) {
|
|
3
|
+
if (!isLocalAlias(input)) {
|
|
4
|
+
throw new TypeError(`Invalid local alias ${JSON.stringify(input)}.`);
|
|
5
5
|
}
|
|
6
6
|
return input;
|
|
7
7
|
}
|
|
8
|
-
export function
|
|
9
|
-
return typeof input === 'string' &&
|
|
8
|
+
export function isLocalAlias(input) {
|
|
9
|
+
return typeof input === 'string' && LOCAL_ALIAS_PATTERN.test(input);
|
|
10
10
|
}
|
|
@@ -5,11 +5,6 @@ export declare const graphNodeSchema: import("zod").ZodObject<{
|
|
|
5
5
|
class: import("zod").ZodString;
|
|
6
6
|
props: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
|
|
7
7
|
}, import("zod/v4/core").$strict>;
|
|
8
|
-
export declare const anonymousGraphNodeSchema: import("zod").ZodObject<{
|
|
9
|
-
as: import("zod").ZodString;
|
|
10
|
-
class: import("zod").ZodString;
|
|
11
|
-
props: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
|
|
12
|
-
}, import("zod/v4/core").$strict>;
|
|
13
8
|
export declare const edgeKeySchema: import("zod").ZodObject<{
|
|
14
9
|
source: import("zod").ZodString;
|
|
15
10
|
target: import("zod").ZodString;
|
|
@@ -22,21 +17,6 @@ export declare const graphEdgeSchema: import("zod").ZodObject<{
|
|
|
22
17
|
slug: import("zod").ZodOptional<ZodType<EdgeSlug, unknown, import("zod/v4/core").$ZodTypeInternals<EdgeSlug, unknown>>>;
|
|
23
18
|
props: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
|
|
24
19
|
}, import("zod/v4/core").$strict>;
|
|
25
|
-
export declare const graphSpecEdgeSchema: import("zod").ZodObject<{
|
|
26
|
-
source: import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodObject<{
|
|
27
|
-
path: import("zod").ZodString;
|
|
28
|
-
}, import("zod/v4/core").$strict>, import("zod").ZodObject<{
|
|
29
|
-
created: import("zod").ZodString;
|
|
30
|
-
}, import("zod/v4/core").$strict>]>;
|
|
31
|
-
target: import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodObject<{
|
|
32
|
-
path: import("zod").ZodString;
|
|
33
|
-
}, import("zod/v4/core").$strict>, import("zod").ZodObject<{
|
|
34
|
-
created: import("zod").ZodString;
|
|
35
|
-
}, import("zod/v4/core").$strict>]>;
|
|
36
|
-
class: import("zod").ZodString;
|
|
37
|
-
slug: import("zod").ZodOptional<ZodType<EdgeSlug, unknown, import("zod/v4/core").$ZodTypeInternals<EdgeSlug, unknown>>>;
|
|
38
|
-
props: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
|
|
39
|
-
}, import("zod/v4/core").$strict>;
|
|
40
20
|
export declare const graphSpecSchema: import("zod").ZodObject<{
|
|
41
21
|
nodes: import("zod").ZodArray<import("zod").ZodUnion<readonly [import("zod").ZodObject<{
|
|
42
22
|
id: import("zod").ZodString;
|
|
@@ -9,7 +9,7 @@ const edgeSlug = string()
|
|
|
9
9
|
.max(edgeSlugSchema.maxLength)
|
|
10
10
|
.check(fullMatch(edgeSlugSchema.fullMatch));
|
|
11
11
|
export const graphNodeSchema = strictObject({ id: text, class: text, props });
|
|
12
|
-
|
|
12
|
+
const anonymousGraphNodeSchema = strictObject({ as: binding, class: text, props });
|
|
13
13
|
export const edgeKeySchema = strictObject({ source: text, target: text, class: text });
|
|
14
14
|
export const graphEdgeSchema = edgeKeySchema.extend({ slug: edgeSlug.optional(), props });
|
|
15
15
|
const graphSpecEndpointSchema = union([
|
|
@@ -17,7 +17,7 @@ const graphSpecEndpointSchema = union([
|
|
|
17
17
|
strictObject({ path: text }),
|
|
18
18
|
strictObject({ created: binding }),
|
|
19
19
|
]);
|
|
20
|
-
|
|
20
|
+
const graphSpecEdgeSchema = strictObject({
|
|
21
21
|
source: graphSpecEndpointSchema,
|
|
22
22
|
target: graphSpecEndpointSchema,
|
|
23
23
|
class: text,
|
|
@@ -6,7 +6,7 @@ import type { DeltaInput } from '../../properties/index.js';
|
|
|
6
6
|
import type { QueryEdgeAST, QueryNodeAST } from '../../query/index.js';
|
|
7
7
|
import type { MutationAST } from '../language/index.js';
|
|
8
8
|
import type { MutationInputEdgeSelector, MutationInputEndpoint, MutationPropertyConditionsInput, MutationPropsInput } from './model.js';
|
|
9
|
-
import {
|
|
9
|
+
import { LocalAlias } from '../../graph/index.js';
|
|
10
10
|
export type MutationQueryPreconditionInput = {
|
|
11
11
|
readonly query: QueryNodeAST;
|
|
12
12
|
readonly equals: {
|
|
@@ -39,7 +39,7 @@ export interface MutationBuilder {
|
|
|
39
39
|
readonly class: ClassKey;
|
|
40
40
|
readonly props?: MutationPropsInput;
|
|
41
41
|
}): {
|
|
42
|
-
readonly created:
|
|
42
|
+
readonly created: LocalAlias;
|
|
43
43
|
};
|
|
44
44
|
updateNode(input: {
|
|
45
45
|
readonly node: NodeTarget;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LocalAlias } from '../../graph/index.js';
|
|
2
2
|
import { createMutationAST } from './create.js';
|
|
3
3
|
/** Run one synchronous author and admit its complete operation set. */
|
|
4
4
|
export function buildMutationAST(author) {
|
|
@@ -38,7 +38,7 @@ export function buildMutationAST(author) {
|
|
|
38
38
|
expect: expectation,
|
|
39
39
|
createNode(input) {
|
|
40
40
|
requireOpen();
|
|
41
|
-
const created =
|
|
41
|
+
const created = LocalAlias(input.as);
|
|
42
42
|
operations.push({
|
|
43
43
|
op: 'node.create',
|
|
44
44
|
as: created,
|
|
@@ -2,7 +2,7 @@ import type { GraphSpec } from '../graph/index.js';
|
|
|
2
2
|
import type { MutationBuilder, MutationInput } from './authoring/index.js';
|
|
3
3
|
import type { MutationAST as MutationASTValue, MutationStructuralLimits } from './language/index.js';
|
|
4
4
|
export type { MutationBuilder, MutationInput, MutationInputEdgeSelector, MutationInputEndpoint, MutationInputOperation, MutationInputPrecondition, MutationPropertyConditionsInput, MutationPropsInput, MutationQueryPreconditionInput, } from './authoring/index.js';
|
|
5
|
-
export type { EdgeCreateOperation, EdgeDeleteOperation, EdgeUpdateOperation,
|
|
5
|
+
export type { EdgeCreateOperation, EdgeDeleteOperation, EdgeUpdateOperation, LocalAlias, MutationEdgeSelector, MutationEndpoint, MutationOperation, MutationPrecondition, MutationPropertyConditions, MutationProps, MutationQueryPrecondition, MutationStructuralLimits, NodeCreateOperation, NodeDeleteOperation, NodeUpdateOperation, QueryExpectedSelection, } from './language/index.js';
|
|
6
6
|
export { MutationASTDecodeError } from './language/index.js';
|
|
7
7
|
export type MutationAST = MutationASTValue;
|
|
8
8
|
export declare const MutationAST: {
|
|
@@ -3,7 +3,7 @@ import { ClassKey } from '@astrale-os/kernel-dsl/v1/addressing';
|
|
|
3
3
|
import * as portable from '@astrale-os/kernel-dsl/value';
|
|
4
4
|
import { EdgeSlug, encodeEdgeKey } from '../../edge/index.js';
|
|
5
5
|
import { compareEdgeKeys } from '../../edge/index.js';
|
|
6
|
-
import {
|
|
6
|
+
import { isLocalAlias, LocalAlias as LocalAliasValue } from '../../graph/index.js';
|
|
7
7
|
import { NodeId } from '../../node/index.js';
|
|
8
8
|
import { compareNodeIds } from '../../node/index.js';
|
|
9
9
|
import { NodePath } from '../../path/index.js';
|
|
@@ -341,9 +341,9 @@ function compare(left, right) {
|
|
|
341
341
|
return left < right ? -1 : left > right ? 1 : 0;
|
|
342
342
|
}
|
|
343
343
|
function localBinding(value, path) {
|
|
344
|
-
if (!
|
|
344
|
+
if (!isLocalAlias(value))
|
|
345
345
|
invalid(path, 'Expected a local binding name of at most 64 characters');
|
|
346
|
-
return
|
|
346
|
+
return LocalAliasValue(value);
|
|
347
347
|
}
|
|
348
348
|
function propertyKey(value, path) {
|
|
349
349
|
if (typeof value !== 'string' || !PropertyKey.is(value)) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { PropertyKey } from '@astrale-os/kernel-dsl/v1';
|
|
2
2
|
import type { ClassKey } from '@astrale-os/kernel-dsl/v1/addressing';
|
|
3
3
|
import type { EdgeSlug } from '../../edge/index.js';
|
|
4
|
-
import type {
|
|
4
|
+
import type { LocalAlias } from '../../graph/index.js';
|
|
5
5
|
import type { NodePath } from '../../path/index.js';
|
|
6
6
|
import type { Delta as PropertiesDelta, Properties } from '../../properties/index.js';
|
|
7
7
|
import type { QueryEdgeAST, QueryNodeAST } from '../../query/index.js';
|
|
@@ -14,10 +14,10 @@ export type MutationStructuralLimits = Readonly<{
|
|
|
14
14
|
queryExpectedIdentities: 4096;
|
|
15
15
|
}>;
|
|
16
16
|
export declare const MUTATION_AST_LIMITS: MutationStructuralLimits;
|
|
17
|
-
export type {
|
|
17
|
+
export type { LocalAlias } from '../../graph/index.js';
|
|
18
18
|
export type MutationProps = Properties;
|
|
19
19
|
export type MutationEndpoint = NodePath | {
|
|
20
|
-
readonly created:
|
|
20
|
+
readonly created: LocalAlias;
|
|
21
21
|
};
|
|
22
22
|
export interface MutationEdgeSelector {
|
|
23
23
|
readonly source: NodePath;
|
|
@@ -55,7 +55,7 @@ export type MutationPrecondition = {
|
|
|
55
55
|
} | MutationQueryPrecondition;
|
|
56
56
|
export interface NodeCreateOperation {
|
|
57
57
|
readonly op: 'node.create';
|
|
58
|
-
readonly as:
|
|
58
|
+
readonly as: LocalAlias;
|
|
59
59
|
readonly class: ClassKey;
|
|
60
60
|
readonly props: MutationProps;
|
|
61
61
|
}
|