@agentshouse/mdmodel 0.1.0-cc9fa0498a7f7 → 0.1.0-cd90851746292
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 +231 -225
- package/README.md +16 -19
- package/dist/blocks.d.ts.map +1 -1
- package/dist/blocks.js +35 -20
- package/dist/condition.d.ts +41 -11
- package/dist/condition.d.ts.map +1 -1
- package/dist/condition.js +223 -87
- package/dist/definition.d.ts +17 -1
- package/dist/definition.d.ts.map +1 -1
- package/dist/definition.js +319 -43
- package/dist/divide.d.ts.map +1 -1
- package/dist/divide.js +27 -17
- package/dist/document.d.ts +6 -3
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +326 -176
- package/dist/index.d.ts +13 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -6
- package/dist/links.d.ts +3 -0
- package/dist/links.d.ts.map +1 -1
- package/dist/links.js +108 -51
- package/dist/paths.d.ts +10 -1
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +118 -12
- 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/references.d.ts +2 -2
- package/dist/references.d.ts.map +1 -1
- package/dist/references.js +6 -1
- 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 +50 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/validate.d.ts +30 -2
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +317 -114
- package/dist/yaml.d.ts.map +1 -1
- package/dist/yaml.js +66 -21
- package/fixtures/README.md +10 -5
- 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/division.json +26 -26
- package/package.json +10 -3
package/dist/condition.js
CHANGED
|
@@ -1,13 +1,26 @@
|
|
|
1
|
-
import { ARRAY_INDEX, escapePointer, fieldFacts, itemFacts, memberFacts, pointerSegments, } from './definition.js';
|
|
2
|
-
import { target } from './paths.js';
|
|
3
|
-
import {
|
|
4
|
-
export const
|
|
1
|
+
import { ARRAY_INDEX, escapePointer, fieldFacts, itemFacts, memberFacts, pointerFacts, pointerSegments, } from './definition.js';
|
|
2
|
+
import { roomPath, target } from './paths.js';
|
|
3
|
+
import { plain } from './yaml.js';
|
|
4
|
+
export const CONDITION_OPERATORS = [
|
|
5
|
+
'eq',
|
|
6
|
+
'in',
|
|
7
|
+
'exists',
|
|
8
|
+
'contains',
|
|
9
|
+
'gt',
|
|
10
|
+
'gte',
|
|
11
|
+
'lt',
|
|
12
|
+
'lte',
|
|
13
|
+
'prefix',
|
|
14
|
+
];
|
|
15
|
+
export const TEXT_FIELD = '/text';
|
|
16
|
+
export const WRITE_DOORS = ['browser', 'agent', 'client', 'function'];
|
|
5
17
|
const PROSE = { kind: 'prose' };
|
|
6
18
|
const NULL = { kind: 'null' };
|
|
7
19
|
const UNREADABLE = { kind: 'unreadable' };
|
|
8
20
|
const UNREAD = { present: undefined, values: [undefined], items: [undefined] };
|
|
9
21
|
const NO_ITEM = { present: false, values: [], items: [] };
|
|
10
22
|
const DATE = /^\d{4}-\d{2}-\d{2}$/u;
|
|
23
|
+
const HEADER = /^\/headers\/[!#$%&'*+.^_`|~0-9a-z-]+$/u;
|
|
11
24
|
const DATE_TIME = /^(\d{4})-(\d{2})-(\d{2})[Tt](\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?(?:[Zz]|([+-])(\d{2}):(\d{2}))$/u;
|
|
12
25
|
export function factKind(facts) {
|
|
13
26
|
if (facts.reference !== undefined)
|
|
@@ -71,7 +84,7 @@ function factOf(value, declared, place) {
|
|
|
71
84
|
return UNREADABLE;
|
|
72
85
|
if (kind !== 'reference')
|
|
73
86
|
return { kind, value };
|
|
74
|
-
const reached = target(place.path, value);
|
|
87
|
+
const reached = target(place.path, value) ?? roomPath(value);
|
|
75
88
|
const resolved = reached === null ? undefined : place.resolve(reached);
|
|
76
89
|
if (resolved === undefined)
|
|
77
90
|
return UNREADABLE;
|
|
@@ -181,10 +194,9 @@ function documentRead({ reached, several, missing }, held) {
|
|
|
181
194
|
};
|
|
182
195
|
}
|
|
183
196
|
function readDocument(facts, path) {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
return facts.type === null ? undefined : single({ kind: 'string', value: facts.type });
|
|
197
|
+
const own = tested(DOCUMENT_TESTS, path);
|
|
198
|
+
if (own !== undefined)
|
|
199
|
+
return own.read(facts, path);
|
|
188
200
|
if (path.startsWith('/sections/'))
|
|
189
201
|
return facts.sections.includes(path.slice('/sections/'.length))
|
|
190
202
|
? single({ kind: 'prose' })
|
|
@@ -195,22 +207,156 @@ function readDocument(facts, path) {
|
|
|
195
207
|
return documentRead(walked(rootOf(facts, '/members'), path.slice('/members'.length)), memberHeld);
|
|
196
208
|
return undefined;
|
|
197
209
|
}
|
|
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
210
|
export function datePointers(fields) {
|
|
209
211
|
return Object.entries(fields)
|
|
210
212
|
.filter(([, facts]) => facts.type === 'string' && facts.format === 'date')
|
|
211
|
-
.map(([name]) => `/fields/${name}`)
|
|
213
|
+
.map(([name]) => `/fields/${escapePointer(name)}`)
|
|
212
214
|
.sort();
|
|
213
215
|
}
|
|
216
|
+
export function valuedChange(definition, field) {
|
|
217
|
+
if (!field.startsWith('/fields/'))
|
|
218
|
+
return false;
|
|
219
|
+
const reached = pointerFacts(definition, field.slice('/fields'.length));
|
|
220
|
+
return (reached !== undefined &&
|
|
221
|
+
!reached.through &&
|
|
222
|
+
reached.facts.type !== 'array' &&
|
|
223
|
+
!reached.facts.prose &&
|
|
224
|
+
factKind(reached.facts) !== null);
|
|
225
|
+
}
|
|
226
|
+
export function changeFields(definition) {
|
|
227
|
+
return [
|
|
228
|
+
...Object.keys(definition.fields).map((name) => `/fields/${escapePointer(name)}`),
|
|
229
|
+
...Object.keys(definition.sections).map((heading) => `/sections/${heading}`),
|
|
230
|
+
];
|
|
231
|
+
}
|
|
232
|
+
export function memberPointers(definition, memberType) {
|
|
233
|
+
return Object.entries(definition.fields)
|
|
234
|
+
.filter(([, facts]) => (facts.type === 'array' ? facts.items : facts)?.reference?.includes(memberType) === true)
|
|
235
|
+
.map(([name]) => `/members/${escapePointer(name)}`);
|
|
236
|
+
}
|
|
237
|
+
function kindOperators(kind) {
|
|
238
|
+
switch (kind) {
|
|
239
|
+
case 'string':
|
|
240
|
+
return ['eq', 'in', 'prefix', 'exists'];
|
|
241
|
+
case 'boolean':
|
|
242
|
+
return ['eq', 'exists'];
|
|
243
|
+
case 'number':
|
|
244
|
+
case 'date':
|
|
245
|
+
case 'time':
|
|
246
|
+
return ['eq', 'in', 'gt', 'gte', 'lt', 'lte', 'exists'];
|
|
247
|
+
default:
|
|
248
|
+
return ['eq', 'in', 'exists'];
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
function pointerOperators({ facts, through }) {
|
|
252
|
+
const scalar = facts.type === 'array' ? facts.items : facts;
|
|
253
|
+
const kind = scalar === undefined || scalar.prose ? null : factKind(scalar);
|
|
254
|
+
if (kind === null)
|
|
255
|
+
return ['exists'];
|
|
256
|
+
if (facts.type === 'array')
|
|
257
|
+
return ['contains', 'exists'];
|
|
258
|
+
const own = kindOperators(kind);
|
|
259
|
+
return through ? [...own.filter((operator) => operator !== 'exists'), 'contains', 'exists'] : own;
|
|
260
|
+
}
|
|
261
|
+
function typeOperators(definition, path, memberType) {
|
|
262
|
+
if (path.startsWith('/sections/'))
|
|
263
|
+
return Object.hasOwn(definition.sections, path.slice('/sections/'.length)) ? ['exists'] : [];
|
|
264
|
+
const pointer = path.startsWith('/fields/')
|
|
265
|
+
? path.slice('/fields'.length)
|
|
266
|
+
: memberType !== null && memberPointers(definition, memberType).includes(path)
|
|
267
|
+
? path.slice('/members'.length)
|
|
268
|
+
: undefined;
|
|
269
|
+
const reached = pointer === undefined ? undefined : pointerFacts(definition, pointer);
|
|
270
|
+
return reached === undefined ? [] : pointerOperators(reached);
|
|
271
|
+
}
|
|
272
|
+
function envelope(path, kind, value) {
|
|
273
|
+
return {
|
|
274
|
+
path,
|
|
275
|
+
names: (named) => named === path,
|
|
276
|
+
kind,
|
|
277
|
+
operators: kindOperators(kind),
|
|
278
|
+
read: (facts) => {
|
|
279
|
+
const held = value(facts);
|
|
280
|
+
return held === null || held === undefined ? undefined : single({ kind, value: held });
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
function tested(tests, path) {
|
|
285
|
+
return tests.find(({ names }) => names(path));
|
|
286
|
+
}
|
|
287
|
+
function reader(tests, facts) {
|
|
288
|
+
return (path) => tested(tests, path)?.read(facts, path);
|
|
289
|
+
}
|
|
290
|
+
const DOCUMENT_TESTS = [
|
|
291
|
+
{
|
|
292
|
+
path: '/path',
|
|
293
|
+
names: (named) => named === '/path',
|
|
294
|
+
kind: 'string',
|
|
295
|
+
operators: ['eq', 'in', 'prefix'],
|
|
296
|
+
read: (facts) => single({ kind: 'string', value: facts.path }),
|
|
297
|
+
},
|
|
298
|
+
envelope('/type', 'enum', (facts) => facts.type),
|
|
299
|
+
];
|
|
300
|
+
const ACTOR_TESTS = [
|
|
301
|
+
envelope('/user', 'enum', (actor) => actor.user),
|
|
302
|
+
envelope('/site', 'enum', (actor) => actor.site),
|
|
303
|
+
envelope('/app', 'enum', (actor) => actor.app),
|
|
304
|
+
envelope('/door', 'enum', (actor) => actor.door),
|
|
305
|
+
];
|
|
306
|
+
const ITEM_TESTS = [
|
|
307
|
+
envelope('/delivery', 'enum', (item) => item.delivery),
|
|
308
|
+
envelope('/source', 'enum', (item) => item.source),
|
|
309
|
+
envelope('/container', 'string', (item) => item.container),
|
|
310
|
+
envelope('/author', 'string', (item) => item.author),
|
|
311
|
+
{
|
|
312
|
+
path: '/headers/<lowercase name>',
|
|
313
|
+
names: (named) => HEADER.test(named),
|
|
314
|
+
kind: 'string',
|
|
315
|
+
operators: kindOperators('string'),
|
|
316
|
+
read: (item, path) => {
|
|
317
|
+
const name = path.slice('/headers/'.length);
|
|
318
|
+
return Object.hasOwn(item.headers, name)
|
|
319
|
+
? single({ kind: 'string', value: item.headers[name] })
|
|
320
|
+
: undefined;
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
path: '/json/<JSON Pointer>',
|
|
325
|
+
names: (named) => named.startsWith('/json/'),
|
|
326
|
+
kind: null,
|
|
327
|
+
operators: CONDITION_OPERATORS,
|
|
328
|
+
read: (item, path) => item.json === null ? UNREAD : jsonRead(pointed(item.json.value, path.slice('/json'.length))),
|
|
329
|
+
},
|
|
330
|
+
];
|
|
331
|
+
const MESSAGE_TESTS = [
|
|
332
|
+
envelope('/sender', 'enum', (message) => message.sender),
|
|
333
|
+
envelope('/routine', 'string', (message) => message.routine),
|
|
334
|
+
envelope('/path', 'string', (message) => message.path),
|
|
335
|
+
];
|
|
336
|
+
export const DOCUMENT_PATHS = DOCUMENT_TESTS.map(({ path }) => path);
|
|
337
|
+
export const ACTOR_PATHS = ACTOR_TESTS.map(({ path }) => path);
|
|
338
|
+
export const ITEM_PATHS = ITEM_TESTS.map(({ path }) => path);
|
|
339
|
+
export const MESSAGE_PATHS = MESSAGE_TESTS.map(({ path }) => path);
|
|
340
|
+
export function testOperators(definitions, path, memberType) {
|
|
341
|
+
const own = tested(DOCUMENT_TESTS, path);
|
|
342
|
+
if (own !== undefined)
|
|
343
|
+
return own.operators;
|
|
344
|
+
return [
|
|
345
|
+
...new Set(definitions.flatMap((definition) => typeOperators(definition, path, memberType))),
|
|
346
|
+
];
|
|
347
|
+
}
|
|
348
|
+
export function actorOperators(path) {
|
|
349
|
+
return tested(ACTOR_TESTS, path)?.operators ?? [];
|
|
350
|
+
}
|
|
351
|
+
export function itemOperators(path) {
|
|
352
|
+
return tested(ITEM_TESTS, path)?.operators ?? [];
|
|
353
|
+
}
|
|
354
|
+
export function messageOperators(path) {
|
|
355
|
+
return tested(MESSAGE_TESTS, path)?.operators ?? [];
|
|
356
|
+
}
|
|
357
|
+
export function itemKind(path) {
|
|
358
|
+
return tested(ITEM_TESTS, path)?.kind ?? null;
|
|
359
|
+
}
|
|
214
360
|
export function dated(value) {
|
|
215
361
|
return (typeof value === 'string' && DATE.test(value) && instant(`${value}T00:00:00Z`) !== undefined);
|
|
216
362
|
}
|
|
@@ -239,11 +385,8 @@ export function instant(value) {
|
|
|
239
385
|
return (BigInt(at.getTime()) - BigInt(offset) * 60000n) * 1000000n + BigInt(fraction);
|
|
240
386
|
}
|
|
241
387
|
export function pointed(value, pointer) {
|
|
242
|
-
if (pointer === '')
|
|
243
|
-
return value;
|
|
244
388
|
let reached = value;
|
|
245
|
-
for (const
|
|
246
|
-
const token = part.replaceAll('~1', '/').replaceAll('~0', '~');
|
|
389
|
+
for (const token of pointerSegments(pointer)) {
|
|
247
390
|
if (Array.isArray(reached)) {
|
|
248
391
|
if (!ARRAY_INDEX.test(token))
|
|
249
392
|
return undefined;
|
|
@@ -282,46 +425,15 @@ function jsonRead(value) {
|
|
|
282
425
|
return single({ kind: 'prose' });
|
|
283
426
|
return { present: true, values: [], items: value.filter(scalar).map(jsonHeld), loose: true };
|
|
284
427
|
}
|
|
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) {
|
|
428
|
+
function equal(held, value) {
|
|
316
429
|
if (!('value' in held))
|
|
317
430
|
return undefined;
|
|
318
|
-
|
|
319
|
-
if (typeof expected !== typeof held.value)
|
|
431
|
+
if (typeof value !== typeof held.value)
|
|
320
432
|
return undefined;
|
|
321
433
|
if (held.kind !== 'time')
|
|
322
|
-
return
|
|
434
|
+
return value === held.value;
|
|
323
435
|
const left = instant(held.value);
|
|
324
|
-
const right = instant(
|
|
436
|
+
const right = instant(value);
|
|
325
437
|
return left === undefined || right === undefined ? undefined : left === right;
|
|
326
438
|
}
|
|
327
439
|
function sign(left, right) {
|
|
@@ -358,11 +470,11 @@ function allOf(truths) {
|
|
|
358
470
|
return false;
|
|
359
471
|
return truths.some((truth) => truth === undefined) ? undefined : true;
|
|
360
472
|
}
|
|
361
|
-
function compared(test, held
|
|
473
|
+
function compared(test, held) {
|
|
362
474
|
if ('eq' in test)
|
|
363
|
-
return equal(held, test.eq
|
|
475
|
+
return equal(held, test.eq);
|
|
364
476
|
if ('in' in test)
|
|
365
|
-
return anyOf(test.in.map((value) => equal(held, value
|
|
477
|
+
return anyOf(test.in.map((value) => equal(held, value)));
|
|
366
478
|
if ('prefix' in test) {
|
|
367
479
|
if (!('value' in held) || typeof held.value !== 'string')
|
|
368
480
|
return undefined;
|
|
@@ -378,7 +490,7 @@ function compared(test, held, owner) {
|
|
|
378
490
|
return ordered(held, test.lt, (sign) => sign < 0);
|
|
379
491
|
return ordered(held, test.lte, (sign) => sign <= 0);
|
|
380
492
|
}
|
|
381
|
-
function leaf(test, read
|
|
493
|
+
function leaf(test, read) {
|
|
382
494
|
if ('exists' in test) {
|
|
383
495
|
const present = read === undefined ? false : read.present;
|
|
384
496
|
return present === undefined ? undefined : present === test.exists;
|
|
@@ -388,26 +500,37 @@ function leaf(test, read, owner) {
|
|
|
388
500
|
if ('contains' in test) {
|
|
389
501
|
if (read.items === null)
|
|
390
502
|
return undefined;
|
|
391
|
-
const truths = read.items.map((item) => item === undefined ? undefined : equal(item, test.contains
|
|
503
|
+
const truths = read.items.map((item) => item === undefined ? undefined : equal(item, test.contains));
|
|
392
504
|
return read.loose === true && !truths.includes(true) ? false : anyOf(truths);
|
|
393
505
|
}
|
|
394
506
|
if (read.values.length === 0)
|
|
395
507
|
return read === NO_ITEM ? false : undefined;
|
|
396
|
-
return anyOf(read.values.map((value) => (value === undefined ? undefined : compared(test, value
|
|
508
|
+
return anyOf(read.values.map((value) => (value === undefined ? undefined : compared(test, value))));
|
|
397
509
|
}
|
|
398
|
-
function evaluated(test, read
|
|
510
|
+
function evaluated(test, read) {
|
|
399
511
|
if ('all' in test)
|
|
400
|
-
return allOf(test.all.map((part) => evaluated(part, read
|
|
512
|
+
return allOf(test.all.map((part) => evaluated(part, read)));
|
|
401
513
|
if ('any' in test)
|
|
402
|
-
return anyOf(test.any.map((part) => evaluated(part, read
|
|
514
|
+
return anyOf(test.any.map((part) => evaluated(part, read)));
|
|
403
515
|
if ('not' in test) {
|
|
404
|
-
const truth = evaluated(test.not, read
|
|
516
|
+
const truth = evaluated(test.not, read);
|
|
405
517
|
return truth === undefined ? undefined : !truth;
|
|
406
518
|
}
|
|
407
|
-
return leaf(test, read(test.path)
|
|
519
|
+
return leaf(test, read(test.path));
|
|
408
520
|
}
|
|
409
|
-
export function
|
|
410
|
-
|
|
521
|
+
export function members(document, path) {
|
|
522
|
+
if (!path.startsWith('/members/'))
|
|
523
|
+
return [];
|
|
524
|
+
const read = readDocument(document, path);
|
|
525
|
+
const values = read === undefined ? [] : [...read.values, ...(read.items ?? [])];
|
|
526
|
+
return [
|
|
527
|
+
...new Set(values.flatMap((value) => value !== undefined && value.kind === 'member' && 'value' in value
|
|
528
|
+
? [String(value.value)]
|
|
529
|
+
: [])),
|
|
530
|
+
].sort();
|
|
531
|
+
}
|
|
532
|
+
export function holds(test, document) {
|
|
533
|
+
return evaluated(test, (path) => readDocument(document, path));
|
|
411
534
|
}
|
|
412
535
|
function inScope(scope, document) {
|
|
413
536
|
if (document === null)
|
|
@@ -418,10 +541,10 @@ function inScope(scope, document) {
|
|
|
418
541
|
return document.id === scope.document;
|
|
419
542
|
return scope.folder === '/' || document.path.startsWith(`${scope.folder}/`);
|
|
420
543
|
}
|
|
421
|
-
function matched(condition, test, document
|
|
544
|
+
function matched(condition, test, document) {
|
|
422
545
|
if (!inScope(condition.scope, document))
|
|
423
546
|
return false;
|
|
424
|
-
return test === undefined || holds(test, document
|
|
547
|
+
return test === undefined || holds(test, document) === true;
|
|
425
548
|
}
|
|
426
549
|
function reachedAt(document, field) {
|
|
427
550
|
if (document === null)
|
|
@@ -444,15 +567,20 @@ function valueOf(fact) {
|
|
|
444
567
|
.sort()
|
|
445
568
|
.map((key) => [key, valueOf(fact.fields[key])]),
|
|
446
569
|
};
|
|
570
|
+
if (fact.kind === 'time') {
|
|
571
|
+
const at = instant(fact.value);
|
|
572
|
+
if (at !== undefined)
|
|
573
|
+
return { kind: fact.kind, at: String(at) };
|
|
574
|
+
}
|
|
447
575
|
return 'value' in fact ? { kind: fact.kind, value: fact.value } : fact;
|
|
448
576
|
}
|
|
449
577
|
function signature(reached) {
|
|
450
578
|
return JSON.stringify(reached.map(({ fact }) => valueOf(fact)));
|
|
451
579
|
}
|
|
452
|
-
function among(values, document, field
|
|
453
|
-
return holds({ path: field, in: values }, document
|
|
580
|
+
function among(values, document, field) {
|
|
581
|
+
return holds({ path: field, in: values }, document) === true;
|
|
454
582
|
}
|
|
455
|
-
function fieldChanged(condition, event
|
|
583
|
+
function fieldChanged(condition, event) {
|
|
456
584
|
const { field, from, to } = condition;
|
|
457
585
|
const before = reachedAt(event.before, field);
|
|
458
586
|
const after = reachedAt(event.after, field);
|
|
@@ -466,32 +594,40 @@ function fieldChanged(condition, event, owner) {
|
|
|
466
594
|
return false;
|
|
467
595
|
if (from === 'new'
|
|
468
596
|
? event.before !== null
|
|
469
|
-
: from !== undefined && (event.before === null || !among(from, event.before, field
|
|
597
|
+
: from !== undefined && (event.before === null || !among(from, event.before, field)))
|
|
470
598
|
return false;
|
|
471
599
|
if (to === 'deleted'
|
|
472
600
|
? event.after !== null
|
|
473
|
-
: to !== undefined && (event.after === null || !among(to, event.after, field
|
|
601
|
+
: to !== undefined && (event.after === null || !among(to, event.after, field)))
|
|
474
602
|
return false;
|
|
475
603
|
return true;
|
|
476
604
|
}
|
|
477
|
-
export function fires(condition, event
|
|
478
|
-
if (condition.
|
|
479
|
-
|
|
605
|
+
export function fires(condition, event) {
|
|
606
|
+
if (condition.moved_between_rooms !== undefined &&
|
|
607
|
+
condition.moved_between_rooms !== event.moved_between_rooms)
|
|
608
|
+
return false;
|
|
609
|
+
if (condition.by !== undefined && evaluated(condition.by, reader(ACTOR_TESTS, event.by)) !== true)
|
|
480
610
|
return false;
|
|
481
611
|
if (condition.mode === 'starts_matching') {
|
|
482
612
|
if (event.before === null && !condition.new_documents)
|
|
483
613
|
return false;
|
|
484
|
-
return (matched(condition, condition.match, event.after
|
|
485
|
-
!matched(condition, condition.match, event.before
|
|
614
|
+
return (matched(condition, condition.match, event.after) &&
|
|
615
|
+
!matched(condition, condition.match, event.before));
|
|
486
616
|
}
|
|
487
617
|
const side = event.after ?? event.before;
|
|
488
|
-
return matched(condition, condition.match, side
|
|
618
|
+
return matched(condition, condition.match, side) && fieldChanged(condition, event);
|
|
489
619
|
}
|
|
490
|
-
export function itemFires(condition, item
|
|
620
|
+
export function itemFires(condition, item) {
|
|
491
621
|
if (condition.source !== undefined && item.source !== condition.source)
|
|
492
622
|
return false;
|
|
493
623
|
if (condition.address !== undefined && item.address !== condition.address)
|
|
494
624
|
return false;
|
|
625
|
+
return (condition.match === undefined || evaluated(condition.match, reader(ITEM_TESTS, item)) === true);
|
|
626
|
+
}
|
|
627
|
+
export function notificationFires(condition, notification) {
|
|
628
|
+
return condition.match === undefined || holds(condition.match, notification) === true;
|
|
629
|
+
}
|
|
630
|
+
export function messageFires(condition, message) {
|
|
495
631
|
return (condition.match === undefined ||
|
|
496
|
-
evaluated(condition.match, (
|
|
632
|
+
evaluated(condition.match, reader(MESSAGE_TESTS, message)) === true);
|
|
497
633
|
}
|
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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"}
|