@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.
Files changed (129) hide show
  1. package/API.md +227 -182
  2. package/README.md +21 -22
  3. package/dist/blocks.d.ts.map +1 -1
  4. package/dist/blocks.js +35 -20
  5. package/dist/condition.d.ts +43 -14
  6. package/dist/condition.d.ts.map +1 -1
  7. package/dist/condition.js +225 -129
  8. package/dist/definition.d.ts +17 -1
  9. package/dist/definition.d.ts.map +1 -1
  10. package/dist/definition.js +238 -22
  11. package/dist/divide.d.ts.map +1 -1
  12. package/dist/divide.js +27 -17
  13. package/dist/document.d.ts +5 -5
  14. package/dist/document.d.ts.map +1 -1
  15. package/dist/document.js +304 -187
  16. package/dist/index.d.ts +21 -9
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +12 -6
  19. package/dist/kinds.d.ts +18 -0
  20. package/dist/kinds.d.ts.map +1 -0
  21. package/dist/kinds.js +141 -0
  22. package/dist/links.d.ts +2 -0
  23. package/dist/links.d.ts.map +1 -1
  24. package/dist/links.js +107 -50
  25. package/dist/paths.d.ts +9 -1
  26. package/dist/paths.d.ts.map +1 -1
  27. package/dist/paths.js +28 -2
  28. package/dist/pattern.d.ts +10 -0
  29. package/dist/pattern.d.ts.map +1 -0
  30. package/dist/pattern.js +355 -0
  31. package/dist/project.d.ts +1 -0
  32. package/dist/project.d.ts.map +1 -1
  33. package/dist/project.js +38 -15
  34. package/dist/query/language.d.ts +218 -0
  35. package/dist/query/language.d.ts.map +1 -0
  36. package/dist/query/language.js +526 -0
  37. package/dist/query/match.d.ts +12 -0
  38. package/dist/query/match.d.ts.map +1 -0
  39. package/dist/query/match.js +118 -0
  40. package/dist/query/rows.d.ts +32 -0
  41. package/dist/query/rows.d.ts.map +1 -0
  42. package/dist/query/rows.js +161 -0
  43. package/dist/query/sql.d.ts +39 -0
  44. package/dist/query/sql.d.ts.map +1 -0
  45. package/dist/query/sql.js +279 -0
  46. package/dist/references.d.ts.map +1 -1
  47. package/dist/references.js +6 -1
  48. package/dist/reserved.d.ts +5 -0
  49. package/dist/reserved.d.ts.map +1 -0
  50. package/dist/reserved.js +20 -0
  51. package/dist/schema.d.ts +1 -0
  52. package/dist/schema.d.ts.map +1 -1
  53. package/dist/schema.js +55 -4
  54. package/dist/types.d.ts +35 -4
  55. package/dist/types.d.ts.map +1 -1
  56. package/dist/validate.d.ts +28 -3
  57. package/dist/validate.d.ts.map +1 -1
  58. package/dist/validate.js +308 -77
  59. package/dist/yaml.d.ts.map +1 -1
  60. package/dist/yaml.js +36 -3
  61. package/fixtures/README.md +26 -6
  62. package/fixtures/cases/conditional-section/context.json +1 -0
  63. package/fixtures/cases/conditional-section/expected.json +6 -0
  64. package/fixtures/cases/conditional-section/library/questions/hosting.md +9 -0
  65. package/fixtures/cases/conditional-section/library/questions/payments.md +12 -0
  66. package/fixtures/cases/conditional-section/schema.yaml +14 -0
  67. package/fixtures/cases/cross-room-link/context.json +1 -0
  68. package/fixtures/cases/cross-room-link/expected.json +1 -0
  69. package/fixtures/cases/cross-room-link/library/clients/acme.md +6 -0
  70. package/fixtures/cases/cross-room-link/schema.yaml +3 -0
  71. package/fixtures/cases/cross-room-reference/context.json +1 -0
  72. package/fixtures/cases/cross-room-reference/expected.json +1 -0
  73. package/fixtures/cases/cross-room-reference/library/clients/acme.md +9 -0
  74. package/fixtures/cases/cross-room-reference/schema.yaml +9 -0
  75. package/fixtures/cases/link-into-a-reserved-name/context.json +1 -0
  76. package/fixtures/cases/link-into-a-reserved-name/expected.json +5 -0
  77. package/fixtures/cases/link-into-a-reserved-name/library/notes/a.md +6 -0
  78. package/fixtures/cases/link-into-a-reserved-name/schema.yaml +3 -0
  79. package/fixtures/cases/link-into-a-reserved-name-from-an-untyped-document/context.json +1 -0
  80. package/fixtures/cases/link-into-a-reserved-name-from-an-untyped-document/expected.json +5 -0
  81. package/fixtures/cases/link-into-a-reserved-name-from-an-untyped-document/library/notes/b.md +5 -0
  82. package/fixtures/cases/member-on-an-untyped-document/context.json +1 -0
  83. package/fixtures/cases/member-on-an-untyped-document/expected.json +6 -0
  84. package/fixtures/cases/member-on-an-untyped-document/library/note.md +4 -0
  85. package/fixtures/cases/member-on-another-type/context.json +1 -0
  86. package/fixtures/cases/member-on-another-type/expected.json +6 -0
  87. package/fixtures/cases/member-on-another-type/library/note.md +4 -0
  88. package/fixtures/cases/member-on-another-type/schema.yaml +7 -0
  89. package/fixtures/cases/reference-into-a-reserved-name/context.json +1 -0
  90. package/fixtures/cases/reference-into-a-reserved-name/expected.json +6 -0
  91. package/fixtures/cases/reference-into-a-reserved-name/library/notes/a.md +4 -0
  92. package/fixtures/cases/reference-into-a-reserved-name/library/settings/brief.md +1 -0
  93. package/fixtures/cases/reference-into-a-reserved-name/schema.yaml +3 -0
  94. package/fixtures/cases/room-md-declares-a-type/context.json +1 -0
  95. package/fixtures/cases/room-md-declares-a-type/expected.json +6 -0
  96. package/fixtures/cases/room-md-declares-a-type/library/ROOM.md +5 -0
  97. package/fixtures/cases/typed-path-names-another-type/context.json +11 -0
  98. package/fixtures/cases/typed-path-names-another-type/expected.json +6 -0
  99. package/fixtures/cases/typed-path-names-another-type/library/settings/prefs/one.md +3 -0
  100. package/fixtures/cases/typed-path-names-another-type/schema.yaml +6 -0
  101. package/fixtures/cases/typed-path-names-its-type/context.json +11 -0
  102. package/fixtures/cases/typed-path-names-its-type/expected.json +3 -0
  103. package/fixtures/cases/typed-path-names-its-type/library/settings/prefs/deeper/two.md +1 -0
  104. package/fixtures/cases/typed-path-names-its-type/library/settings/prefs/one.md +4 -0
  105. package/fixtures/cases/typed-path-names-its-type/schema.yaml +6 -0
  106. package/fixtures/cases/typed-path-names-no-type/context.json +11 -0
  107. package/fixtures/cases/typed-path-names-no-type/expected.json +6 -0
  108. package/fixtures/cases/typed-path-names-no-type/library/settings/prefs/one.md +1 -0
  109. package/fixtures/cases/typed-path-names-no-type/schema.yaml +6 -0
  110. package/fixtures/cases/unnamed-typed-path-checks-its-fields/context.json +11 -0
  111. package/fixtures/cases/unnamed-typed-path-checks-its-fields/expected.json +6 -0
  112. package/fixtures/cases/unnamed-typed-path-checks-its-fields/library/rooms/team/tasks/plan.md +4 -0
  113. package/fixtures/cases/unnamed-typed-path-checks-its-fields/schema.yaml +5 -0
  114. package/fixtures/cases/unnamed-typed-path-names-a-type/context.json +11 -0
  115. package/fixtures/cases/unnamed-typed-path-names-a-type/expected.json +6 -0
  116. package/fixtures/cases/unnamed-typed-path-names-a-type/library/rooms/team/tasks/plan.md +6 -0
  117. package/fixtures/cases/unnamed-typed-path-names-a-type/schema.yaml +5 -0
  118. package/fixtures/cases/unnamed-typed-path-reads-its-type/context.json +11 -0
  119. package/fixtures/cases/unnamed-typed-path-reads-its-type/expected.json +3 -0
  120. package/fixtures/cases/unnamed-typed-path-reads-its-type/library/rooms/team/plan.md +1 -0
  121. package/fixtures/cases/unnamed-typed-path-reads-its-type/library/rooms/team/tasks/plan.md +5 -0
  122. package/fixtures/cases/unnamed-typed-path-reads-its-type/schema.yaml +5 -0
  123. package/fixtures/cases/unnamed-typed-path-without-a-body/context.json +11 -0
  124. package/fixtures/cases/unnamed-typed-path-without-a-body/expected.json +5 -0
  125. package/fixtures/cases/unnamed-typed-path-without-a-body/library/rooms/team/tasks/plan.md +5 -0
  126. package/fixtures/cases/unnamed-typed-path-without-a-body/schema.yaml +5 -0
  127. package/fixtures/division.json +26 -26
  128. package/fixtures/queries.json +913 -0
  129. 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 { target } from './paths.js';
3
- import { isRecord, plain } from './yaml.js';
4
- export const WRITE_DOORS = ['browser', 'agent', 'client'];
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 DATE = /^\d{4}-\d{2}-\d{2}$/u;
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
- if (facts.reference !== undefined)
14
- return 'reference';
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 (facts.type === 'boolean')
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
- return 'string';
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
- if (path === '/path')
185
- return single({ kind: 'path', value: facts.path });
186
- if (path === '/type')
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 dated(value) {
215
- return (typeof value === 'string' && DATE.test(value) && instant(`${value}T00:00:00Z`) !== undefined);
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
- export function instant(value) {
218
- if (typeof value !== 'string')
219
- return undefined;
220
- const parts = DATE_TIME.exec(value);
221
- if (parts === null)
222
- return undefined;
223
- const [year, month, day, hour, minute, second, offsetHours, offsetMinutes] = [
224
- 1, 2, 3, 4, 5, 6, 9, 10,
225
- ].map((at) => Number(parts[at] ?? 0));
226
- const at = new Date(0);
227
- at.setUTCFullYear(year, month - 1, day);
228
- at.setUTCHours(hour, minute, second);
229
- if (at.getUTCFullYear() !== year ||
230
- at.getUTCMonth() !== month - 1 ||
231
- at.getUTCDate() !== day ||
232
- at.getUTCHours() !== hour ||
233
- at.getUTCMinutes() !== minute ||
234
- offsetHours > 23 ||
235
- offsetMinutes > 59)
236
- return undefined;
237
- const offset = (parts[8] === '-' ? -1 : 1) * (offsetHours * 60 + offsetMinutes);
238
- const fraction = (parts[7] ?? '').padEnd(9, '0').slice(0, 9);
239
- return (BigInt(at.getTime()) - BigInt(offset) * 60000n) * 1000000n + BigInt(fraction);
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 part of pointer.slice(1).split('/')) {
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 readItem(item, path) {
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
- const expected = wanted(value, owner);
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 expected === held.value;
399
+ return value === held.value;
323
400
  const left = instant(held.value);
324
- const right = instant(expected);
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, owner) {
438
+ function compared(test, held) {
362
439
  if ('eq' in test)
363
- return equal(held, test.eq, owner);
440
+ return equal(held, test.eq);
364
441
  if ('in' in test)
365
- return anyOf(test.in.map((value) => equal(held, value, owner)));
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, owner) {
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, owner));
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, owner))));
473
+ return anyOf(read.values.map((value) => (value === undefined ? undefined : compared(test, value))));
397
474
  }
398
- function evaluated(test, read, owner) {
475
+ function evaluated(test, read) {
399
476
  if ('all' in test)
400
- return allOf(test.all.map((part) => evaluated(part, read, owner)));
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, owner)));
479
+ return anyOf(test.any.map((part) => evaluated(part, read)));
403
480
  if ('not' in test) {
404
- const truth = evaluated(test.not, read, owner);
481
+ const truth = evaluated(test.not, read);
405
482
  return truth === undefined ? undefined : !truth;
406
483
  }
407
- return leaf(test, read(test.path), owner);
484
+ return leaf(test, read(test.path));
408
485
  }
409
- export function holds(test, document, owner) {
410
- return evaluated(test, (path) => readDocument(document, path), owner);
411
- }
412
- function inScope(scope, document) {
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, owner) {
509
+ function matched(condition, test, document) {
422
510
  if (!inScope(condition.scope, document))
423
511
  return false;
424
- return test === undefined || holds(test, document, owner) === true;
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, owner) {
458
- return holds({ path: field, in: values }, document, owner) === true;
545
+ function among(values, document, field) {
546
+ return holds({ path: field, in: values }, document) === true;
459
547
  }
460
- function fieldChanged(condition, event, owner) {
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, owner)))
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, owner)))
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, owner) {
483
- if (condition.by !== undefined &&
484
- evaluated(condition.by, (path) => readActor(event.by, path), owner) !== true)
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, owner) &&
490
- !matched(condition, condition.match, event.before, owner));
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, owner) && fieldChanged(condition, event, owner);
583
+ return matched(condition, condition.match, side) && fieldChanged(condition, event);
494
584
  }
495
- export function itemFires(condition, item, owner) {
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, (path) => readItem(item, path), owner) === true);
597
+ evaluated(condition.match, reader(MESSAGE_TESTS, message)) === true);
502
598
  }
@@ -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
@@ -1 +1 @@
1
- {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../src/definition.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../src/definition.ts"],"names":[],"mappings":"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"}