@agentshouse/mdmodel 0.1.0-cad192ab63d5f → 0.1.0-caefdbe3e3d42
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/API.md +227 -182
- package/README.md +21 -22
- package/dist/blocks.d.ts.map +1 -1
- package/dist/blocks.js +35 -20
- package/dist/condition.d.ts +43 -14
- package/dist/condition.d.ts.map +1 -1
- package/dist/condition.js +225 -129
- package/dist/definition.d.ts +17 -1
- package/dist/definition.d.ts.map +1 -1
- package/dist/definition.js +238 -22
- package/dist/divide.d.ts.map +1 -1
- package/dist/divide.js +27 -17
- package/dist/document.d.ts +5 -5
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +304 -187
- package/dist/index.d.ts +21 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -6
- package/dist/kinds.d.ts +18 -0
- package/dist/kinds.d.ts.map +1 -0
- package/dist/kinds.js +141 -0
- package/dist/links.d.ts +2 -0
- package/dist/links.d.ts.map +1 -1
- package/dist/links.js +107 -50
- package/dist/paths.d.ts +9 -1
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +28 -2
- package/dist/pattern.d.ts +10 -0
- package/dist/pattern.d.ts.map +1 -0
- package/dist/pattern.js +355 -0
- package/dist/project.d.ts +1 -0
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +38 -15
- package/dist/query/language.d.ts +218 -0
- package/dist/query/language.d.ts.map +1 -0
- package/dist/query/language.js +526 -0
- package/dist/query/match.d.ts +12 -0
- package/dist/query/match.d.ts.map +1 -0
- package/dist/query/match.js +118 -0
- package/dist/query/rows.d.ts +32 -0
- package/dist/query/rows.d.ts.map +1 -0
- package/dist/query/rows.js +161 -0
- package/dist/query/sql.d.ts +39 -0
- package/dist/query/sql.d.ts.map +1 -0
- package/dist/query/sql.js +279 -0
- package/dist/references.d.ts.map +1 -1
- package/dist/references.js +6 -1
- package/dist/reserved.d.ts +5 -0
- package/dist/reserved.d.ts.map +1 -0
- package/dist/reserved.js +20 -0
- package/dist/schema.d.ts +1 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +55 -4
- package/dist/types.d.ts +35 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/validate.d.ts +28 -3
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +308 -77
- package/dist/yaml.d.ts.map +1 -1
- package/dist/yaml.js +36 -3
- package/fixtures/README.md +26 -6
- package/fixtures/cases/conditional-section/context.json +1 -0
- package/fixtures/cases/conditional-section/expected.json +6 -0
- package/fixtures/cases/conditional-section/library/questions/hosting.md +9 -0
- package/fixtures/cases/conditional-section/library/questions/payments.md +12 -0
- package/fixtures/cases/conditional-section/schema.yaml +14 -0
- package/fixtures/cases/cross-room-link/context.json +1 -0
- package/fixtures/cases/cross-room-link/expected.json +1 -0
- package/fixtures/cases/cross-room-link/library/clients/acme.md +6 -0
- package/fixtures/cases/cross-room-link/schema.yaml +3 -0
- package/fixtures/cases/cross-room-reference/context.json +1 -0
- package/fixtures/cases/cross-room-reference/expected.json +1 -0
- package/fixtures/cases/cross-room-reference/library/clients/acme.md +9 -0
- package/fixtures/cases/cross-room-reference/schema.yaml +9 -0
- package/fixtures/cases/link-into-a-reserved-name/context.json +1 -0
- package/fixtures/cases/link-into-a-reserved-name/expected.json +5 -0
- package/fixtures/cases/link-into-a-reserved-name/library/notes/a.md +6 -0
- package/fixtures/cases/link-into-a-reserved-name/schema.yaml +3 -0
- package/fixtures/cases/link-into-a-reserved-name-from-an-untyped-document/context.json +1 -0
- package/fixtures/cases/link-into-a-reserved-name-from-an-untyped-document/expected.json +5 -0
- package/fixtures/cases/link-into-a-reserved-name-from-an-untyped-document/library/notes/b.md +5 -0
- package/fixtures/cases/member-on-an-untyped-document/context.json +1 -0
- package/fixtures/cases/member-on-an-untyped-document/expected.json +6 -0
- package/fixtures/cases/member-on-an-untyped-document/library/note.md +4 -0
- package/fixtures/cases/member-on-another-type/context.json +1 -0
- package/fixtures/cases/member-on-another-type/expected.json +6 -0
- package/fixtures/cases/member-on-another-type/library/note.md +4 -0
- package/fixtures/cases/member-on-another-type/schema.yaml +7 -0
- package/fixtures/cases/reference-into-a-reserved-name/context.json +1 -0
- package/fixtures/cases/reference-into-a-reserved-name/expected.json +6 -0
- package/fixtures/cases/reference-into-a-reserved-name/library/notes/a.md +4 -0
- package/fixtures/cases/reference-into-a-reserved-name/library/settings/brief.md +1 -0
- package/fixtures/cases/reference-into-a-reserved-name/schema.yaml +3 -0
- package/fixtures/cases/room-md-declares-a-type/context.json +1 -0
- package/fixtures/cases/room-md-declares-a-type/expected.json +6 -0
- package/fixtures/cases/room-md-declares-a-type/library/ROOM.md +5 -0
- package/fixtures/cases/typed-path-names-another-type/context.json +11 -0
- package/fixtures/cases/typed-path-names-another-type/expected.json +6 -0
- package/fixtures/cases/typed-path-names-another-type/library/settings/prefs/one.md +3 -0
- package/fixtures/cases/typed-path-names-another-type/schema.yaml +6 -0
- package/fixtures/cases/typed-path-names-its-type/context.json +11 -0
- package/fixtures/cases/typed-path-names-its-type/expected.json +3 -0
- package/fixtures/cases/typed-path-names-its-type/library/settings/prefs/deeper/two.md +1 -0
- package/fixtures/cases/typed-path-names-its-type/library/settings/prefs/one.md +4 -0
- package/fixtures/cases/typed-path-names-its-type/schema.yaml +6 -0
- package/fixtures/cases/typed-path-names-no-type/context.json +11 -0
- package/fixtures/cases/typed-path-names-no-type/expected.json +6 -0
- package/fixtures/cases/typed-path-names-no-type/library/settings/prefs/one.md +1 -0
- package/fixtures/cases/typed-path-names-no-type/schema.yaml +6 -0
- package/fixtures/cases/unnamed-typed-path-checks-its-fields/context.json +11 -0
- package/fixtures/cases/unnamed-typed-path-checks-its-fields/expected.json +6 -0
- package/fixtures/cases/unnamed-typed-path-checks-its-fields/library/rooms/team/tasks/plan.md +4 -0
- package/fixtures/cases/unnamed-typed-path-checks-its-fields/schema.yaml +5 -0
- package/fixtures/cases/unnamed-typed-path-names-a-type/context.json +11 -0
- package/fixtures/cases/unnamed-typed-path-names-a-type/expected.json +6 -0
- package/fixtures/cases/unnamed-typed-path-names-a-type/library/rooms/team/tasks/plan.md +6 -0
- package/fixtures/cases/unnamed-typed-path-names-a-type/schema.yaml +5 -0
- package/fixtures/cases/unnamed-typed-path-reads-its-type/context.json +11 -0
- package/fixtures/cases/unnamed-typed-path-reads-its-type/expected.json +3 -0
- package/fixtures/cases/unnamed-typed-path-reads-its-type/library/rooms/team/plan.md +1 -0
- package/fixtures/cases/unnamed-typed-path-reads-its-type/library/rooms/team/tasks/plan.md +5 -0
- package/fixtures/cases/unnamed-typed-path-reads-its-type/schema.yaml +5 -0
- package/fixtures/cases/unnamed-typed-path-without-a-body/context.json +11 -0
- package/fixtures/cases/unnamed-typed-path-without-a-body/expected.json +5 -0
- package/fixtures/cases/unnamed-typed-path-without-a-body/library/rooms/team/tasks/plan.md +5 -0
- package/fixtures/cases/unnamed-typed-path-without-a-body/schema.yaml +5 -0
- package/fixtures/division.json +26 -26
- package/fixtures/queries.json +913 -0
- package/package.json +7 -2
package/dist/condition.js
CHANGED
|
@@ -1,30 +1,35 @@
|
|
|
1
|
-
import { ARRAY_INDEX, escapePointer, fieldFacts, itemFacts, memberFacts, pointerSegments, } from './definition.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
1
|
+
import { ARRAY_INDEX, escapePointer, fieldFacts, itemFacts, memberFacts, pointerFacts, pointerSegments, } from './definition.js';
|
|
2
|
+
import { dated, instant, kindOf } from './kinds.js';
|
|
3
|
+
import { roomPath, target } from './paths.js';
|
|
4
|
+
import { plain } from './yaml.js';
|
|
5
|
+
export const CONDITION_OPERATORS = [
|
|
6
|
+
'eq',
|
|
7
|
+
'in',
|
|
8
|
+
'exists',
|
|
9
|
+
'contains',
|
|
10
|
+
'gt',
|
|
11
|
+
'gte',
|
|
12
|
+
'lt',
|
|
13
|
+
'lte',
|
|
14
|
+
'prefix',
|
|
15
|
+
];
|
|
16
|
+
export const TEXT_FIELD = '/text';
|
|
17
|
+
export const WRITE_DOORS = ['browser', 'agent', 'client', 'function'];
|
|
5
18
|
const PROSE = { kind: 'prose' };
|
|
6
19
|
const NULL = { kind: 'null' };
|
|
7
20
|
const UNREADABLE = { kind: 'unreadable' };
|
|
8
21
|
const UNREAD = { present: undefined, values: [undefined], items: [undefined] };
|
|
9
22
|
const NO_ITEM = { present: false, values: [], items: [] };
|
|
10
|
-
const
|
|
11
|
-
const DATE_TIME = /^(\d{4})-(\d{2})-(\d{2})[Tt](\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?(?:[Zz]|([+-])(\d{2}):(\d{2}))$/u;
|
|
23
|
+
const HEADER = /^\/headers\/[!#$%&'*+.^_`|~0-9a-z-]+$/u;
|
|
12
24
|
export function factKind(facts) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (facts.values !== undefined)
|
|
16
|
-
return 'enum';
|
|
17
|
-
if (facts.type === 'number' || facts.type === 'integer')
|
|
25
|
+
const kind = kindOf(facts);
|
|
26
|
+
if (kind === 'integer')
|
|
18
27
|
return 'number';
|
|
19
|
-
if (
|
|
20
|
-
return 'boolean';
|
|
21
|
-
if (facts.type !== 'string')
|
|
22
|
-
return null;
|
|
23
|
-
if (facts.format === 'date')
|
|
24
|
-
return 'date';
|
|
25
|
-
if (facts.format === 'date-time')
|
|
28
|
+
if (kind === 'date-time')
|
|
26
29
|
return 'time';
|
|
27
|
-
|
|
30
|
+
if (kind === 'time')
|
|
31
|
+
return 'string';
|
|
32
|
+
return kind;
|
|
28
33
|
}
|
|
29
34
|
function fits(kind, facts, value) {
|
|
30
35
|
if (!scalar(value))
|
|
@@ -71,7 +76,7 @@ function factOf(value, declared, place) {
|
|
|
71
76
|
return UNREADABLE;
|
|
72
77
|
if (kind !== 'reference')
|
|
73
78
|
return { kind, value };
|
|
74
|
-
const reached = target(place.path, value);
|
|
79
|
+
const reached = target(place.path, value) ?? roomPath(value);
|
|
75
80
|
const resolved = reached === null ? undefined : place.resolve(reached);
|
|
76
81
|
if (resolved === undefined)
|
|
77
82
|
return UNREADABLE;
|
|
@@ -181,10 +186,9 @@ function documentRead({ reached, several, missing }, held) {
|
|
|
181
186
|
};
|
|
182
187
|
}
|
|
183
188
|
function readDocument(facts, path) {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
return facts.type === null ? undefined : single({ kind: 'string', value: facts.type });
|
|
189
|
+
const own = tested(DOCUMENT_TESTS, path);
|
|
190
|
+
if (own !== undefined)
|
|
191
|
+
return own.read(facts, path);
|
|
188
192
|
if (path.startsWith('/sections/'))
|
|
189
193
|
return facts.sections.includes(path.slice('/sections/'.length))
|
|
190
194
|
? single({ kind: 'prose' })
|
|
@@ -195,55 +199,159 @@ function readDocument(facts, path) {
|
|
|
195
199
|
return documentRead(walked(rootOf(facts, '/members'), path.slice('/members'.length)), memberHeld);
|
|
196
200
|
return undefined;
|
|
197
201
|
}
|
|
198
|
-
function readActor(actor, path) {
|
|
199
|
-
const value = path === '/user'
|
|
200
|
-
? actor.user
|
|
201
|
-
: path === '/site'
|
|
202
|
-
? actor.site
|
|
203
|
-
: path === '/door'
|
|
204
|
-
? actor.door
|
|
205
|
-
: undefined;
|
|
206
|
-
return value === undefined ? undefined : single({ kind: 'actor', value });
|
|
207
|
-
}
|
|
208
202
|
export function datePointers(fields) {
|
|
209
203
|
return Object.entries(fields)
|
|
210
204
|
.filter(([, facts]) => facts.type === 'string' && facts.format === 'date')
|
|
211
|
-
.map(([name]) => `/fields/${name}`)
|
|
205
|
+
.map(([name]) => `/fields/${escapePointer(name)}`)
|
|
212
206
|
.sort();
|
|
213
207
|
}
|
|
214
|
-
export function
|
|
215
|
-
|
|
208
|
+
export function valuedChange(definition, field) {
|
|
209
|
+
if (!field.startsWith('/fields/'))
|
|
210
|
+
return false;
|
|
211
|
+
const reached = pointerFacts(definition, field.slice('/fields'.length));
|
|
212
|
+
return (reached !== undefined &&
|
|
213
|
+
!reached.through &&
|
|
214
|
+
reached.facts.type !== 'array' &&
|
|
215
|
+
!reached.facts.prose &&
|
|
216
|
+
factKind(reached.facts) !== null);
|
|
217
|
+
}
|
|
218
|
+
export function changeFields(definition) {
|
|
219
|
+
return [
|
|
220
|
+
...Object.keys(definition.fields).map((name) => `/fields/${escapePointer(name)}`),
|
|
221
|
+
...Object.keys(definition.sections).map((heading) => `/sections/${heading}`),
|
|
222
|
+
];
|
|
223
|
+
}
|
|
224
|
+
export function memberPointers(definition, memberType) {
|
|
225
|
+
return Object.entries(definition.fields)
|
|
226
|
+
.filter(([, facts]) => (facts.type === 'array' ? facts.items : facts)?.reference?.includes(memberType) === true)
|
|
227
|
+
.map(([name]) => `/members/${escapePointer(name)}`);
|
|
228
|
+
}
|
|
229
|
+
function kindOperators(kind) {
|
|
230
|
+
switch (kind) {
|
|
231
|
+
case 'string':
|
|
232
|
+
return ['eq', 'in', 'prefix', 'exists'];
|
|
233
|
+
case 'boolean':
|
|
234
|
+
return ['eq', 'exists'];
|
|
235
|
+
case 'number':
|
|
236
|
+
case 'date':
|
|
237
|
+
case 'time':
|
|
238
|
+
return ['eq', 'in', 'gt', 'gte', 'lt', 'lte', 'exists'];
|
|
239
|
+
default:
|
|
240
|
+
return ['eq', 'in', 'exists'];
|
|
241
|
+
}
|
|
216
242
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
return
|
|
243
|
+
function pointerOperators({ facts, through }) {
|
|
244
|
+
const scalar = facts.type === 'array' ? facts.items : facts;
|
|
245
|
+
const kind = scalar === undefined || scalar.prose ? null : factKind(scalar);
|
|
246
|
+
if (kind === null)
|
|
247
|
+
return ['exists'];
|
|
248
|
+
if (facts.type === 'array')
|
|
249
|
+
return ['contains', 'exists'];
|
|
250
|
+
const own = kindOperators(kind);
|
|
251
|
+
return through ? [...own.filter((operator) => operator !== 'exists'), 'contains', 'exists'] : own;
|
|
252
|
+
}
|
|
253
|
+
function typeOperators(definition, path, memberType) {
|
|
254
|
+
if (path.startsWith('/sections/'))
|
|
255
|
+
return Object.hasOwn(definition.sections, path.slice('/sections/'.length)) ? ['exists'] : [];
|
|
256
|
+
const pointer = path.startsWith('/fields/')
|
|
257
|
+
? path.slice('/fields'.length)
|
|
258
|
+
: memberType !== null && memberPointers(definition, memberType).includes(path)
|
|
259
|
+
? path.slice('/members'.length)
|
|
260
|
+
: undefined;
|
|
261
|
+
const reached = pointer === undefined ? undefined : pointerFacts(definition, pointer);
|
|
262
|
+
return reached === undefined ? [] : pointerOperators(reached);
|
|
263
|
+
}
|
|
264
|
+
function envelope(path, kind, value) {
|
|
265
|
+
return {
|
|
266
|
+
path,
|
|
267
|
+
names: (named) => named === path,
|
|
268
|
+
kind,
|
|
269
|
+
operators: kindOperators(kind),
|
|
270
|
+
read: (facts) => {
|
|
271
|
+
const held = value(facts);
|
|
272
|
+
return held === null || held === undefined ? undefined : single({ kind, value: held });
|
|
273
|
+
},
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
function tested(tests, path) {
|
|
277
|
+
return tests.find(({ names }) => names(path));
|
|
278
|
+
}
|
|
279
|
+
function reader(tests, facts) {
|
|
280
|
+
return (path) => tested(tests, path)?.read(facts, path);
|
|
281
|
+
}
|
|
282
|
+
const DOCUMENT_TESTS = [
|
|
283
|
+
{
|
|
284
|
+
path: '/path',
|
|
285
|
+
names: (named) => named === '/path',
|
|
286
|
+
kind: 'string',
|
|
287
|
+
operators: ['eq', 'in', 'prefix'],
|
|
288
|
+
read: (facts) => single({ kind: 'string', value: facts.path }),
|
|
289
|
+
},
|
|
290
|
+
envelope('/type', 'enum', (facts) => facts.type),
|
|
291
|
+
];
|
|
292
|
+
const ACTOR_TESTS = [
|
|
293
|
+
envelope('/user', 'enum', (actor) => actor.user),
|
|
294
|
+
envelope('/site', 'enum', (actor) => actor.site),
|
|
295
|
+
envelope('/app', 'enum', (actor) => actor.app),
|
|
296
|
+
envelope('/door', 'enum', (actor) => actor.door),
|
|
297
|
+
];
|
|
298
|
+
const ITEM_TESTS = [
|
|
299
|
+
envelope('/delivery', 'enum', (item) => item.delivery),
|
|
300
|
+
envelope('/source', 'enum', (item) => item.source),
|
|
301
|
+
envelope('/container', 'string', (item) => item.container),
|
|
302
|
+
envelope('/author', 'string', (item) => item.author),
|
|
303
|
+
{
|
|
304
|
+
path: '/headers/<lowercase name>',
|
|
305
|
+
names: (named) => HEADER.test(named),
|
|
306
|
+
kind: 'string',
|
|
307
|
+
operators: kindOperators('string'),
|
|
308
|
+
read: (item, path) => {
|
|
309
|
+
const name = path.slice('/headers/'.length);
|
|
310
|
+
return Object.hasOwn(item.headers, name)
|
|
311
|
+
? single({ kind: 'string', value: item.headers[name] })
|
|
312
|
+
: undefined;
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
path: '/json/<JSON Pointer>',
|
|
317
|
+
names: (named) => named.startsWith('/json/'),
|
|
318
|
+
kind: null,
|
|
319
|
+
operators: CONDITION_OPERATORS,
|
|
320
|
+
read: (item, path) => item.json === null ? UNREAD : jsonRead(pointed(item.json.value, path.slice('/json'.length))),
|
|
321
|
+
},
|
|
322
|
+
];
|
|
323
|
+
const MESSAGE_TESTS = [
|
|
324
|
+
envelope('/sender', 'enum', (message) => message.sender),
|
|
325
|
+
envelope('/agent_function', 'string', (message) => message.agent_function),
|
|
326
|
+
envelope('/path', 'string', (message) => message.path),
|
|
327
|
+
];
|
|
328
|
+
export const DOCUMENT_PATHS = DOCUMENT_TESTS.map(({ path }) => path);
|
|
329
|
+
export const ACTOR_PATHS = ACTOR_TESTS.map(({ path }) => path);
|
|
330
|
+
export const ITEM_PATHS = ITEM_TESTS.map(({ path }) => path);
|
|
331
|
+
export const MESSAGE_PATHS = MESSAGE_TESTS.map(({ path }) => path);
|
|
332
|
+
export function testOperators(definitions, path, memberType) {
|
|
333
|
+
const own = tested(DOCUMENT_TESTS, path);
|
|
334
|
+
if (own !== undefined)
|
|
335
|
+
return own.operators;
|
|
336
|
+
return [
|
|
337
|
+
...new Set(definitions.flatMap((definition) => typeOperators(definition, path, memberType))),
|
|
338
|
+
];
|
|
339
|
+
}
|
|
340
|
+
export function actorOperators(path) {
|
|
341
|
+
return tested(ACTOR_TESTS, path)?.operators ?? [];
|
|
342
|
+
}
|
|
343
|
+
export function itemOperators(path) {
|
|
344
|
+
return tested(ITEM_TESTS, path)?.operators ?? [];
|
|
345
|
+
}
|
|
346
|
+
export function messageOperators(path) {
|
|
347
|
+
return tested(MESSAGE_TESTS, path)?.operators ?? [];
|
|
348
|
+
}
|
|
349
|
+
export function itemKind(path) {
|
|
350
|
+
return tested(ITEM_TESTS, path)?.kind ?? null;
|
|
240
351
|
}
|
|
241
352
|
export function pointed(value, pointer) {
|
|
242
|
-
if (pointer === '')
|
|
243
|
-
return value;
|
|
244
353
|
let reached = value;
|
|
245
|
-
for (const
|
|
246
|
-
const token = part.replaceAll('~1', '/').replaceAll('~0', '~');
|
|
354
|
+
for (const token of pointerSegments(pointer)) {
|
|
247
355
|
if (Array.isArray(reached)) {
|
|
248
356
|
if (!ARRAY_INDEX.test(token))
|
|
249
357
|
return undefined;
|
|
@@ -282,46 +390,15 @@ function jsonRead(value) {
|
|
|
282
390
|
return single({ kind: 'prose' });
|
|
283
391
|
return { present: true, values: [], items: value.filter(scalar).map(jsonHeld), loose: true };
|
|
284
392
|
}
|
|
285
|
-
function
|
|
286
|
-
if (path.startsWith('/json/')) {
|
|
287
|
-
if (item.json === null)
|
|
288
|
-
return UNREAD;
|
|
289
|
-
return jsonRead(pointed(item.json.value, path.slice('/json'.length)));
|
|
290
|
-
}
|
|
291
|
-
if (path.startsWith('/headers/')) {
|
|
292
|
-
const name = path.slice('/headers/'.length);
|
|
293
|
-
return Object.hasOwn(item.headers, name)
|
|
294
|
-
? single({ kind: 'string', value: item.headers[name] })
|
|
295
|
-
: undefined;
|
|
296
|
-
}
|
|
297
|
-
if (path === '/has_attachment')
|
|
298
|
-
return single({ kind: 'boolean', value: item.has_attachment });
|
|
299
|
-
const value = path === '/delivery'
|
|
300
|
-
? item.delivery
|
|
301
|
-
: path === '/source'
|
|
302
|
-
? item.source
|
|
303
|
-
: path === '/provider'
|
|
304
|
-
? item.provider
|
|
305
|
-
: path === '/container'
|
|
306
|
-
? item.container
|
|
307
|
-
: path === '/author'
|
|
308
|
-
? item.author
|
|
309
|
-
: null;
|
|
310
|
-
return value === null ? undefined : single({ kind: 'string', value });
|
|
311
|
-
}
|
|
312
|
-
function wanted(value, owner) {
|
|
313
|
-
return isRecord(value) && value.owner === true ? owner : value;
|
|
314
|
-
}
|
|
315
|
-
function equal(held, value, owner) {
|
|
393
|
+
function equal(held, value) {
|
|
316
394
|
if (!('value' in held))
|
|
317
395
|
return undefined;
|
|
318
|
-
|
|
319
|
-
if (typeof expected !== typeof held.value)
|
|
396
|
+
if (typeof value !== typeof held.value)
|
|
320
397
|
return undefined;
|
|
321
398
|
if (held.kind !== 'time')
|
|
322
|
-
return
|
|
399
|
+
return value === held.value;
|
|
323
400
|
const left = instant(held.value);
|
|
324
|
-
const right = instant(
|
|
401
|
+
const right = instant(value);
|
|
325
402
|
return left === undefined || right === undefined ? undefined : left === right;
|
|
326
403
|
}
|
|
327
404
|
function sign(left, right) {
|
|
@@ -358,11 +435,11 @@ function allOf(truths) {
|
|
|
358
435
|
return false;
|
|
359
436
|
return truths.some((truth) => truth === undefined) ? undefined : true;
|
|
360
437
|
}
|
|
361
|
-
function compared(test, held
|
|
438
|
+
function compared(test, held) {
|
|
362
439
|
if ('eq' in test)
|
|
363
|
-
return equal(held, test.eq
|
|
440
|
+
return equal(held, test.eq);
|
|
364
441
|
if ('in' in test)
|
|
365
|
-
return anyOf(test.in.map((value) => equal(held, value
|
|
442
|
+
return anyOf(test.in.map((value) => equal(held, value)));
|
|
366
443
|
if ('prefix' in test) {
|
|
367
444
|
if (!('value' in held) || typeof held.value !== 'string')
|
|
368
445
|
return undefined;
|
|
@@ -378,7 +455,7 @@ function compared(test, held, owner) {
|
|
|
378
455
|
return ordered(held, test.lt, (sign) => sign < 0);
|
|
379
456
|
return ordered(held, test.lte, (sign) => sign <= 0);
|
|
380
457
|
}
|
|
381
|
-
function leaf(test, read
|
|
458
|
+
function leaf(test, read) {
|
|
382
459
|
if ('exists' in test) {
|
|
383
460
|
const present = read === undefined ? false : read.present;
|
|
384
461
|
return present === undefined ? undefined : present === test.exists;
|
|
@@ -388,28 +465,39 @@ function leaf(test, read, owner) {
|
|
|
388
465
|
if ('contains' in test) {
|
|
389
466
|
if (read.items === null)
|
|
390
467
|
return undefined;
|
|
391
|
-
const truths = read.items.map((item) => item === undefined ? undefined : equal(item, test.contains
|
|
468
|
+
const truths = read.items.map((item) => item === undefined ? undefined : equal(item, test.contains));
|
|
392
469
|
return read.loose === true && !truths.includes(true) ? false : anyOf(truths);
|
|
393
470
|
}
|
|
394
471
|
if (read.values.length === 0)
|
|
395
472
|
return read === NO_ITEM ? false : undefined;
|
|
396
|
-
return anyOf(read.values.map((value) => (value === undefined ? undefined : compared(test, value
|
|
473
|
+
return anyOf(read.values.map((value) => (value === undefined ? undefined : compared(test, value))));
|
|
397
474
|
}
|
|
398
|
-
function evaluated(test, read
|
|
475
|
+
function evaluated(test, read) {
|
|
399
476
|
if ('all' in test)
|
|
400
|
-
return allOf(test.all.map((part) => evaluated(part, read
|
|
477
|
+
return allOf(test.all.map((part) => evaluated(part, read)));
|
|
401
478
|
if ('any' in test)
|
|
402
|
-
return anyOf(test.any.map((part) => evaluated(part, read
|
|
479
|
+
return anyOf(test.any.map((part) => evaluated(part, read)));
|
|
403
480
|
if ('not' in test) {
|
|
404
|
-
const truth = evaluated(test.not, read
|
|
481
|
+
const truth = evaluated(test.not, read);
|
|
405
482
|
return truth === undefined ? undefined : !truth;
|
|
406
483
|
}
|
|
407
|
-
return leaf(test, read(test.path)
|
|
484
|
+
return leaf(test, read(test.path));
|
|
408
485
|
}
|
|
409
|
-
export function
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
486
|
+
export function members(document, path) {
|
|
487
|
+
if (!path.startsWith('/members/'))
|
|
488
|
+
return [];
|
|
489
|
+
const read = readDocument(document, path);
|
|
490
|
+
const values = read === undefined ? [] : [...read.values, ...(read.items ?? [])];
|
|
491
|
+
return [
|
|
492
|
+
...new Set(values.flatMap((value) => value !== undefined && value.kind === 'member' && 'value' in value
|
|
493
|
+
? [String(value.value)]
|
|
494
|
+
: [])),
|
|
495
|
+
].sort();
|
|
496
|
+
}
|
|
497
|
+
export function holds(test, document) {
|
|
498
|
+
return evaluated(test, (path) => readDocument(document, path));
|
|
499
|
+
}
|
|
500
|
+
export function inScope(scope, document) {
|
|
413
501
|
if (document === null)
|
|
414
502
|
return false;
|
|
415
503
|
if ('type' in scope)
|
|
@@ -418,10 +506,10 @@ function inScope(scope, document) {
|
|
|
418
506
|
return document.id === scope.document;
|
|
419
507
|
return scope.folder === '/' || document.path.startsWith(`${scope.folder}/`);
|
|
420
508
|
}
|
|
421
|
-
function matched(condition, test, document
|
|
509
|
+
function matched(condition, test, document) {
|
|
422
510
|
if (!inScope(condition.scope, document))
|
|
423
511
|
return false;
|
|
424
|
-
return test === undefined || holds(test, document
|
|
512
|
+
return test === undefined || holds(test, document) === true;
|
|
425
513
|
}
|
|
426
514
|
function reachedAt(document, field) {
|
|
427
515
|
if (document === null)
|
|
@@ -454,10 +542,10 @@ function valueOf(fact) {
|
|
|
454
542
|
function signature(reached) {
|
|
455
543
|
return JSON.stringify(reached.map(({ fact }) => valueOf(fact)));
|
|
456
544
|
}
|
|
457
|
-
function among(values, document, field
|
|
458
|
-
return holds({ path: field, in: values }, document
|
|
545
|
+
function among(values, document, field) {
|
|
546
|
+
return holds({ path: field, in: values }, document) === true;
|
|
459
547
|
}
|
|
460
|
-
function fieldChanged(condition, event
|
|
548
|
+
function fieldChanged(condition, event) {
|
|
461
549
|
const { field, from, to } = condition;
|
|
462
550
|
const before = reachedAt(event.before, field);
|
|
463
551
|
const after = reachedAt(event.after, field);
|
|
@@ -471,32 +559,40 @@ function fieldChanged(condition, event, owner) {
|
|
|
471
559
|
return false;
|
|
472
560
|
if (from === 'new'
|
|
473
561
|
? event.before !== null
|
|
474
|
-
: from !== undefined && (event.before === null || !among(from, event.before, field
|
|
562
|
+
: from !== undefined && (event.before === null || !among(from, event.before, field)))
|
|
475
563
|
return false;
|
|
476
564
|
if (to === 'deleted'
|
|
477
565
|
? event.after !== null
|
|
478
|
-
: to !== undefined && (event.after === null || !among(to, event.after, field
|
|
566
|
+
: to !== undefined && (event.after === null || !among(to, event.after, field)))
|
|
479
567
|
return false;
|
|
480
568
|
return true;
|
|
481
569
|
}
|
|
482
|
-
export function fires(condition, event
|
|
483
|
-
if (condition.
|
|
484
|
-
|
|
570
|
+
export function fires(condition, event) {
|
|
571
|
+
if (condition.moved_between_rooms !== undefined &&
|
|
572
|
+
condition.moved_between_rooms !== event.moved_between_rooms)
|
|
573
|
+
return false;
|
|
574
|
+
if (condition.by !== undefined && evaluated(condition.by, reader(ACTOR_TESTS, event.by)) !== true)
|
|
485
575
|
return false;
|
|
486
576
|
if (condition.mode === 'starts_matching') {
|
|
487
577
|
if (event.before === null && !condition.new_documents)
|
|
488
578
|
return false;
|
|
489
|
-
return (matched(condition, condition.match, event.after
|
|
490
|
-
!matched(condition, condition.match, event.before
|
|
579
|
+
return (matched(condition, condition.match, event.after) &&
|
|
580
|
+
!matched(condition, condition.match, event.before));
|
|
491
581
|
}
|
|
492
582
|
const side = event.after ?? event.before;
|
|
493
|
-
return matched(condition, condition.match, side
|
|
583
|
+
return matched(condition, condition.match, side) && fieldChanged(condition, event);
|
|
494
584
|
}
|
|
495
|
-
export function itemFires(condition, item
|
|
585
|
+
export function itemFires(condition, item) {
|
|
496
586
|
if (condition.source !== undefined && item.source !== condition.source)
|
|
497
587
|
return false;
|
|
498
588
|
if (condition.address !== undefined && item.address !== condition.address)
|
|
499
589
|
return false;
|
|
590
|
+
return (condition.match === undefined || evaluated(condition.match, reader(ITEM_TESTS, item)) === true);
|
|
591
|
+
}
|
|
592
|
+
export function notificationFires(condition, notification) {
|
|
593
|
+
return condition.match === undefined || holds(condition.match, notification) === true;
|
|
594
|
+
}
|
|
595
|
+
export function messageFires(condition, message) {
|
|
500
596
|
return (condition.match === undefined ||
|
|
501
|
-
evaluated(condition.match, (
|
|
597
|
+
evaluated(condition.match, reader(MESSAGE_TESTS, message)) === true);
|
|
502
598
|
}
|
package/dist/definition.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export type ValueFacts = {
|
|
|
5
5
|
readonly format?: string;
|
|
6
6
|
readonly values?: readonly unknown[];
|
|
7
7
|
readonly reference?: readonly string[];
|
|
8
|
+
readonly crossRoom?: true;
|
|
8
9
|
readonly prose: boolean;
|
|
9
10
|
readonly conditional?: true;
|
|
10
11
|
readonly prefix?: readonly ValueFacts[];
|
|
@@ -29,12 +30,26 @@ export type Shape = {
|
|
|
29
30
|
readonly schema: Readonly<Record<string, unknown>>;
|
|
30
31
|
readonly defs: Readonly<Record<string, unknown>>;
|
|
31
32
|
};
|
|
33
|
+
export type RuleValue = string | number | boolean | null;
|
|
34
|
+
export type Transition = {
|
|
35
|
+
readonly from: RuleValue;
|
|
36
|
+
readonly to: RuleValue;
|
|
37
|
+
readonly roles?: readonly string[];
|
|
38
|
+
};
|
|
39
|
+
export type FieldRules = {
|
|
40
|
+
readonly changeRoles?: readonly string[];
|
|
41
|
+
readonly initialRoles?: readonly string[];
|
|
42
|
+
readonly transitions?: readonly Transition[];
|
|
43
|
+
};
|
|
32
44
|
export type Definition = {
|
|
33
45
|
readonly name: string;
|
|
34
46
|
readonly memberDocument: boolean;
|
|
35
47
|
readonly frontmatter: ValueFacts;
|
|
36
48
|
readonly fields: Readonly<Record<string, ValueFacts>>;
|
|
37
49
|
readonly sections: Readonly<Record<string, SectionSpec>>;
|
|
50
|
+
readonly rules: Readonly<Record<string, FieldRules>>;
|
|
51
|
+
readonly createRoles?: readonly string[];
|
|
52
|
+
readonly deleteRoles?: readonly string[];
|
|
38
53
|
readonly shape: Shape;
|
|
39
54
|
};
|
|
40
55
|
export type Failure = {
|
|
@@ -45,6 +60,7 @@ export declare const JSON_TYPES: readonly JsonType[];
|
|
|
45
60
|
export declare const BUILT_IN_TYPE = "any";
|
|
46
61
|
export declare const ATTACHMENT = "attachment";
|
|
47
62
|
export declare const ARRAY_INDEX: RegExp;
|
|
63
|
+
export declare const JSON_POINTER: RegExp;
|
|
48
64
|
export declare function escapePointer(key: string): string;
|
|
49
65
|
export declare function pointerSegments(pointer: string): string[];
|
|
50
66
|
export declare function refTarget(reference: string, defs: Readonly<Record<string, unknown>>): {
|
|
@@ -62,5 +78,5 @@ export type PointerFacts = {
|
|
|
62
78
|
export declare function crossedFacts(facts: ValueFacts): ValueFacts[];
|
|
63
79
|
export declare function fieldFacts(definition: Definition, key: string): ValueFacts | undefined;
|
|
64
80
|
export declare function pointerFacts(definition: Definition, pointer: string): PointerFacts | undefined;
|
|
65
|
-
export declare function readSchema(text: string): VerifiedModel | Failure;
|
|
81
|
+
export declare function readSchema(text: string, provided?: VerifiedModel): VerifiedModel | Failure;
|
|
66
82
|
//# sourceMappingURL=definition.d.ts.map
|
package/dist/definition.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../src/definition.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../src/definition.ts"],"names":[],"mappings":"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"}
|