@agentshouse/mdruntime 0.1.0-alpha.24 → 0.1.0-alpha.26

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 (52) hide show
  1. package/AGENTS.md +61 -4
  2. package/dist/change-set.d.ts +4 -11
  3. package/dist/change-set.d.ts.map +1 -1
  4. package/dist/change-set.js +8 -16
  5. package/dist/change-set.js.map +1 -1
  6. package/dist/client.d.ts +9 -3
  7. package/dist/client.d.ts.map +1 -1
  8. package/dist/client.js +5 -2
  9. package/dist/client.js.map +1 -1
  10. package/dist/collection.d.ts +0 -2
  11. package/dist/collection.d.ts.map +1 -1
  12. package/dist/collection.js +0 -5
  13. package/dist/collection.js.map +1 -1
  14. package/dist/connection.d.ts +9 -5
  15. package/dist/connection.d.ts.map +1 -1
  16. package/dist/connection.js +67 -67
  17. package/dist/connection.js.map +1 -1
  18. package/dist/conversation.d.ts +7 -4
  19. package/dist/conversation.d.ts.map +1 -1
  20. package/dist/conversation.js +29 -6
  21. package/dist/conversation.js.map +1 -1
  22. package/dist/host.d.ts.map +1 -1
  23. package/dist/host.js +2 -0
  24. package/dist/host.js.map +1 -1
  25. package/dist/index.d.ts +2 -2
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js.map +1 -1
  28. package/dist/paths.d.ts +1 -0
  29. package/dist/paths.d.ts.map +1 -1
  30. package/dist/paths.js +8 -0
  31. package/dist/paths.js.map +1 -1
  32. package/dist/query.d.ts +206 -10
  33. package/dist/query.d.ts.map +1 -1
  34. package/dist/query.js +463 -14
  35. package/dist/query.js.map +1 -1
  36. package/dist/read-side.d.ts +13 -0
  37. package/dist/read-side.d.ts.map +1 -0
  38. package/dist/read-side.js +393 -0
  39. package/dist/read-side.js.map +1 -0
  40. package/dist/rows.d.ts +39 -0
  41. package/dist/rows.d.ts.map +1 -0
  42. package/dist/rows.js +85 -0
  43. package/dist/rows.js.map +1 -0
  44. package/dist/search.d.ts +61 -0
  45. package/dist/search.d.ts.map +1 -0
  46. package/dist/search.js +155 -0
  47. package/dist/search.js.map +1 -0
  48. package/dist/wire.d.ts +2 -2
  49. package/dist/wire.d.ts.map +1 -1
  50. package/dist/wire.js +2 -1
  51. package/dist/wire.js.map +1 -1
  52. package/package.json +3 -2
package/dist/query.js CHANGED
@@ -1,18 +1,467 @@
1
- export function rawQuery(rooms) {
2
- return {
3
- roomVersions: Object.fromEntries(rooms.map((room)=>[
4
- room.room,
5
- room.roomVersion
6
- ])),
7
- groups: null,
8
- documents: rooms.flatMap((room)=>Object.entries(room.documents).filter(([path])=>path.endsWith('.md')).map(([path, document])=>({
9
- ...structuredClone(document),
10
- type: document.type ?? 'any',
11
- room: room.room,
12
- path,
13
- backlinks: []
14
- })))
1
+ import { normalize } from './paths.js';
2
+ export class QueryError extends Error {
3
+ constructor(code, at, problem){
4
+ super(`${code} at ${at}: ${problem}`);
5
+ }
6
+ }
7
+ const RANGE = [
8
+ '$gt',
9
+ '$gte',
10
+ '$lt',
11
+ '$lte'
12
+ ];
13
+ const SINGLE = [
14
+ '$eq',
15
+ '$ne',
16
+ '$in',
17
+ '$nin',
18
+ '$all',
19
+ '$size',
20
+ '$exists'
21
+ ];
22
+ const FILTER = [
23
+ 'rooms',
24
+ 'types',
25
+ 'where',
26
+ 'pathPrefix',
27
+ 'hop',
28
+ 'backlinks'
29
+ ];
30
+ const RELATED = [
31
+ 'types',
32
+ 'where',
33
+ 'pathPrefix',
34
+ 'field'
35
+ ];
36
+ const PARTS = [
37
+ 'fields',
38
+ 'sections',
39
+ 'preamble',
40
+ 'markdown',
41
+ 'backlinks'
42
+ ];
43
+ const ORDER = [
44
+ 'by',
45
+ 'direction',
46
+ 'nulls',
47
+ 'stringSort',
48
+ 'locale',
49
+ 'localeOptions'
50
+ ];
51
+ const CALENDAR_DATE = /^(\d{4})-(\d{2})-(\d{2})$/;
52
+ export function invalid(at, problem) {
53
+ throw new QueryError('invalid-query', at, problem);
54
+ }
55
+ function place(at, name) {
56
+ return at === '' ? name : `${at}.${name}`;
57
+ }
58
+ export function plain(value) {
59
+ return typeof value === 'object' && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
60
+ }
61
+ export function known(value, allowed, at) {
62
+ for (const name of Object.keys(value)){
63
+ if (!allowed.includes(name)) invalid(place(at, name), 'unknown part');
64
+ }
65
+ }
66
+ function list(input, at) {
67
+ if (!Array.isArray(input)) invalid(at, 'expects a list');
68
+ return input;
69
+ }
70
+ function value(input, at) {
71
+ if (Array.isArray(input)) invalid(at, 'a list is not a value');
72
+ if (input !== null && typeof input !== 'string' && typeof input !== 'boolean' && !(typeof input === 'number' && Number.isFinite(input))) {
73
+ invalid(at, 'not a value');
74
+ }
75
+ return input;
76
+ }
77
+ function values(input, at) {
78
+ return list(input, at).map((item, index)=>value(item, `${at}[${index}]`));
79
+ }
80
+ function names(input, at) {
81
+ const listed = list(input, at);
82
+ if (listed.some((item)=>typeof item !== 'string')) invalid(at, 'expects a list of names');
83
+ return [
84
+ ...new Set(listed)
85
+ ].sort();
86
+ }
87
+ function directory(input, at) {
88
+ if (typeof input !== 'string' || normalize(input) !== input) {
89
+ invalid(at, 'expects a normalized directory');
90
+ }
91
+ return input;
92
+ }
93
+ function calendarDate(value) {
94
+ const match = CALENDAR_DATE.exec(value);
95
+ if (match === null) return false;
96
+ const [year, month, day] = match.slice(1).map(Number);
97
+ const date = new Date(Date.UTC(year, month - 1, day));
98
+ return date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day;
99
+ }
100
+ function fits(spec, value) {
101
+ const item = spec.kind === 'list' ? spec.of : spec;
102
+ if (item.kind === 'number') return typeof value === 'number';
103
+ if (typeof value !== 'string') return false;
104
+ if (item.kind === 'enum') return item.values.includes(value);
105
+ if (item.kind === 'date') return calendarDate(value);
106
+ if (item.kind === 'reference') return value !== '' && normalize(value) === value;
107
+ return true;
108
+ }
109
+ function reference(spec) {
110
+ return spec.kind === 'reference' || spec.kind === 'list' && spec.of.kind === 'reference';
111
+ }
112
+ function typing(facts, rooms, types, at) {
113
+ const read = rooms === null ? facts.rooms : facts.rooms.filter((room)=>rooms.includes(room.locator));
114
+ const acquiring = !facts.listed && (rooms === null || rooms.some((locator)=>!facts.rooms.some((room)=>room.locator === locator)));
115
+ const available = !acquiring && read.every((room)=>room.available);
116
+ const declared = read.flatMap((room)=>room.types);
117
+ for (const name of types ?? []){
118
+ if (name === 'any' || !available || declared.some((type)=>type.name === name)) continue;
119
+ throw new QueryError('unknown-type', place(at, 'types'), `no model it reads declares ${name}`);
120
+ }
121
+ return {
122
+ untyped: types === null || types.includes('any') || !available,
123
+ types: types === null ? declared : declared.filter((type)=>types.includes(type.name))
15
124
  };
16
125
  }
126
+ function specs(typed, field, at) {
127
+ const declared = typed.types.flatMap((type)=>Object.hasOwn(type.fields, field) ? [
128
+ type.fields[field]
129
+ ] : []);
130
+ if (declared.length === 0 && !typed.untyped) {
131
+ throw new QueryError('unknown-field', at, `no MD Type it reads declares ${field}`);
132
+ }
133
+ return declared;
134
+ }
135
+ function kind(declared, checked, at) {
136
+ if (checked === null || declared.length === 0 || declared.some((spec)=>fits(spec, checked))) {
137
+ return;
138
+ }
139
+ throw new QueryError('wrong-kind', at, `${JSON.stringify(checked)} is not of its field's kind`);
140
+ }
141
+ function listed(declared, list) {
142
+ return declared.length > 0 && declared.every((spec)=>spec.kind === 'list' === list);
143
+ }
144
+ function test(declared, input, at) {
145
+ if (!plain(input)) {
146
+ const equal = value(input, at);
147
+ kind(declared, equal, at);
148
+ return {
149
+ op: 'eq',
150
+ value: equal
151
+ };
152
+ }
153
+ const operators = Object.keys(input);
154
+ if (operators.length === 0) invalid(at, 'names no operator');
155
+ if (operators.some((operator)=>RANGE.includes(operator))) {
156
+ const stray = operators.find((operator)=>!RANGE.includes(operator));
157
+ if (stray !== undefined) invalid(place(at, stray), 'cannot join a range');
158
+ if (listed(declared, true)) invalid(at, 'a range on a list');
159
+ return {
160
+ op: 'range',
161
+ bounds: RANGE.filter((operator)=>operators.includes(operator)).map((operator)=>{
162
+ const bound = value(input[operator], place(at, operator));
163
+ if (bound === null) invalid(place(at, operator), 'a range bound is never null');
164
+ kind(declared, bound, place(at, operator));
165
+ return [
166
+ operator.slice(1),
167
+ bound
168
+ ];
169
+ })
170
+ };
171
+ }
172
+ if (operators.length > 1) invalid(place(at, operators[1]), 'names a second operator');
173
+ const [operator] = operators;
174
+ const where = place(at, operator);
175
+ if (!SINGLE.includes(operator)) invalid(where, 'unknown operator');
176
+ const operand = input[operator];
177
+ if (operator === '$eq' || operator === '$ne') {
178
+ const compared = value(operand, where);
179
+ kind(declared, compared, where);
180
+ return operator === '$eq' ? {
181
+ op: 'eq',
182
+ value: compared
183
+ } : {
184
+ op: 'ne',
185
+ value: compared
186
+ };
187
+ }
188
+ if (operator === '$in' || operator === '$nin' || operator === '$all') {
189
+ const compared = values(operand, where);
190
+ compared.forEach((item, index)=>kind(declared, item, `${where}[${index}]`));
191
+ if (operator === '$in') return {
192
+ op: 'in',
193
+ values: compared
194
+ };
195
+ if (operator === '$nin') return {
196
+ op: 'nin',
197
+ values: compared
198
+ };
199
+ if (compared.includes(null)) invalid(where, 'a list holds no null');
200
+ if (listed(declared, false)) invalid(where, 'the field is not a list');
201
+ return {
202
+ op: 'all',
203
+ values: compared
204
+ };
205
+ }
206
+ if (operator === '$size') {
207
+ if (!Number.isSafeInteger(operand) || operand < 0) {
208
+ invalid(where, 'expects a nonnegative integer');
209
+ }
210
+ if (listed(declared, false)) invalid(where, 'the field is not a list');
211
+ return {
212
+ op: 'size',
213
+ size: operand
214
+ };
215
+ }
216
+ if (typeof operand !== 'boolean') invalid(where, 'expects true or false');
217
+ return {
218
+ op: 'exists',
219
+ exists: operand
220
+ };
221
+ }
222
+ function condition(typed, input, at) {
223
+ if (!plain(input)) invalid(at, 'expects an object of field predicates');
224
+ const conditions = [];
225
+ for (const name of Object.keys(input).sort()){
226
+ const where = place(at, name);
227
+ const entry = input[name];
228
+ if (name === '$and' || name === '$or') {
229
+ const nested = list(entry, where).map((item, index)=>condition(typed, item, `${where}[${index}]`));
230
+ if (nested.length === 0) invalid(where, 'expects a nonempty list');
231
+ conditions.push(name === '$and' ? {
232
+ every: nested
233
+ } : {
234
+ some: nested
235
+ });
236
+ continue;
237
+ }
238
+ if (name.startsWith('$')) invalid(where, 'unknown operator');
239
+ conditions.push({
240
+ field: name,
241
+ test: test(specs(typed, name, where), entry, where)
242
+ });
243
+ }
244
+ if (conditions.length === 0) invalid(at, 'names no field');
245
+ return conditions.length === 1 ? conditions[0] : {
246
+ every: conditions
247
+ };
248
+ }
249
+ function scope(facts, rooms, input, at) {
250
+ const types = input.types === undefined ? null : names(input.types, place(at, 'types'));
251
+ const typed = typing(facts, rooms, types, at);
252
+ return {
253
+ typed,
254
+ types,
255
+ where: input.where === undefined || plain(input.where) && Object.keys(input.where).length === 0 ? null : condition(typed, input.where, place(at, 'where')),
256
+ pathPrefix: input.pathPrefix === undefined ? null : directory(input.pathPrefix, place(at, 'pathPrefix'))
257
+ };
258
+ }
259
+ function referenceField(typed, field, at) {
260
+ if (typeof field !== 'string') invalid(at, 'expects a field name');
261
+ const declared = specs(typed, field, at);
262
+ if (declared.length > 0 && !declared.some(reference)) invalid(at, 'not a reference field');
263
+ return field;
264
+ }
265
+ function hopOf(facts, rooms, root, input) {
266
+ if (!plain(input)) invalid('hop', 'expects an object');
267
+ known(input, RELATED, 'hop');
268
+ const field = referenceField(root, input.field, 'hop.field');
269
+ const { types, where, pathPrefix } = scope(facts, rooms, input, 'hop');
270
+ return {
271
+ types,
272
+ where,
273
+ pathPrefix,
274
+ field
275
+ };
276
+ }
277
+ function backlinksOf(facts, rooms, input) {
278
+ if (!plain(input)) invalid('backlinks', 'expects an object');
279
+ known(input, RELATED, 'backlinks');
280
+ const { typed, types, where, pathPrefix } = scope(facts, rooms, input, 'backlinks');
281
+ const field = input.field === undefined ? null : referenceField(typed, input.field, 'backlinks.field');
282
+ return {
283
+ types,
284
+ where,
285
+ pathPrefix,
286
+ field
287
+ };
288
+ }
289
+ function keyPlan(typed, input, at, path) {
290
+ if (input === 'room' || input === 'type' || path && input === 'path') return {
291
+ of: input
292
+ };
293
+ if (plain(input) && typeof input.field === 'string' && Object.keys(input).length === 1) {
294
+ specs(typed, input.field, place(at, 'field'));
295
+ return {
296
+ of: 'field',
297
+ field: input.field
298
+ };
299
+ }
300
+ return invalid(at, path ? 'expects room, path, type or a field' : 'expects room, type or a field');
301
+ }
302
+ function direction(input, at) {
303
+ if (input === undefined) return 'asc';
304
+ if (input !== 'asc' && input !== 'desc') invalid(at, 'expects asc or desc');
305
+ return input;
306
+ }
307
+ function orderOptions(input, at) {
308
+ const options = {
309
+ direction: direction(input.direction, place(at, 'direction'))
310
+ };
311
+ if (input.nulls !== undefined) {
312
+ if (input.nulls !== 'first' && input.nulls !== 'last') {
313
+ invalid(place(at, 'nulls'), 'expects first or last');
314
+ }
315
+ options.nulls = input.nulls;
316
+ }
317
+ if (input.stringSort !== undefined) {
318
+ if (input.stringSort !== 'lexical' && input.stringSort !== 'locale') {
319
+ invalid(place(at, 'stringSort'), 'expects lexical or locale');
320
+ }
321
+ options.stringSort = input.stringSort;
322
+ }
323
+ if (input.locale !== undefined) {
324
+ if (typeof input.locale !== 'string' || !collates(input.locale, undefined)) {
325
+ invalid(place(at, 'locale'), 'expects a locale name');
326
+ }
327
+ options.locale = input.locale;
328
+ }
329
+ if (input.localeOptions !== undefined) {
330
+ if (!plain(input.localeOptions) || !collates(options.locale, input.localeOptions)) {
331
+ invalid(place(at, 'localeOptions'), 'expects collation options');
332
+ }
333
+ options.localeOptions = input.localeOptions;
334
+ }
335
+ return options;
336
+ }
337
+ function collates(locale, options) {
338
+ try {
339
+ ''.localeCompare('', locale, options);
340
+ return true;
341
+ } catch {
342
+ return false;
343
+ }
344
+ }
345
+ function parts(typed, input, at, fields) {
346
+ if (input === undefined) return null;
347
+ if (input === 'all') return 'all';
348
+ const named = list(input, at);
349
+ named.forEach((name, index)=>{
350
+ if (typeof name !== 'string') invalid(`${at}[${index}]`, 'expects a name');
351
+ if (fields) specs(typed, name, `${at}[${index}]`);
352
+ });
353
+ return named;
354
+ }
355
+ function flag(input, at) {
356
+ if (input === undefined) return false;
357
+ if (input !== true) invalid(at, 'expects true');
358
+ return true;
359
+ }
360
+ function documentShape(typed, input) {
361
+ const orderBy = (input.orderBy === undefined ? [] : list(input.orderBy, 'orderBy')).map((clause, index)=>{
362
+ const at = `orderBy[${index}]`;
363
+ if (!plain(clause)) invalid(at, 'expects an order clause');
364
+ known(clause, ORDER, at);
365
+ return {
366
+ key: keyPlan(typed, clause.by, place(at, 'by'), true),
367
+ options: orderOptions(clause, at)
368
+ };
369
+ });
370
+ const select = input.select;
371
+ if (select === 'all') {
372
+ return {
373
+ kind: 'documents',
374
+ fields: 'all',
375
+ sections: 'all',
376
+ preamble: true,
377
+ markdown: true,
378
+ backlinks: true,
379
+ orderBy
380
+ };
381
+ }
382
+ if (!plain(select)) invalid('select', "expects 'all' or the parts to return");
383
+ known(select, PARTS, 'select');
384
+ return {
385
+ kind: 'documents',
386
+ fields: parts(typed, select.fields, 'select.fields', true),
387
+ sections: parts(typed, select.sections, 'select.sections', false),
388
+ preamble: flag(select.preamble, 'select.preamble'),
389
+ markdown: flag(select.markdown, 'select.markdown'),
390
+ backlinks: flag(select.backlinks, 'select.backlinks'),
391
+ orderBy
392
+ };
393
+ }
394
+ function groupShape(typed, input) {
395
+ const groupBy = list(input.groupBy, 'groupBy').map((key, index)=>keyPlan(typed, key, `groupBy[${index}]`, false));
396
+ if (groupBy.length === 0) invalid('groupBy', 'names no key');
397
+ const grouped = groupBy.map((key)=>JSON.stringify(key));
398
+ const orderBy = (input.orderBy === undefined ? [] : list(input.orderBy, 'orderBy')).map((clause, index)=>{
399
+ const at = `orderBy[${index}]`;
400
+ if (!plain(clause)) invalid(at, 'expects an order clause');
401
+ known(clause, [
402
+ 'by',
403
+ 'direction'
404
+ ], at);
405
+ const by = clause.by === 'count' ? 'count' : grouped.indexOf(JSON.stringify(keyPlan(typed, clause.by, place(at, 'by'), false)));
406
+ if (by === -1) invalid(place(at, 'by'), 'orders by a key the query does not group by');
407
+ return {
408
+ by,
409
+ direction: direction(clause.direction, place(at, 'direction'))
410
+ };
411
+ });
412
+ return {
413
+ kind: 'groups',
414
+ groupBy,
415
+ orderBy
416
+ };
417
+ }
418
+ export function planOf(input, facts) {
419
+ if (!plain(input)) invalid('query', 'expects a query object');
420
+ const grouped = input.groupBy !== undefined;
421
+ if (grouped && input.select !== undefined) invalid('select', 'a grouped query selects nothing');
422
+ if (!grouped && input.select === undefined) invalid('select', 'a Document query must select');
423
+ known(input, [
424
+ ...FILTER,
425
+ 'orderBy',
426
+ 'limit',
427
+ grouped ? 'groupBy' : 'select'
428
+ ], '');
429
+ const limit = limitOf(input.limit);
430
+ const rooms = input.rooms === undefined ? null : names(input.rooms, 'rooms');
431
+ const { typed, ...root } = scope(facts, rooms, input, '');
432
+ return {
433
+ rooms,
434
+ root,
435
+ hop: input.hop === undefined ? null : hopOf(facts, rooms, typed, input.hop),
436
+ backlinks: input.backlinks === undefined ? null : backlinksOf(facts, rooms, input.backlinks),
437
+ shape: grouped ? groupShape(typed, input) : documentShape(typed, input),
438
+ limit
439
+ };
440
+ }
441
+ export function limitOf(input) {
442
+ if (input === undefined) return null;
443
+ if (!Number.isSafeInteger(input) || input < 0) {
444
+ invalid('limit', 'expects a nonnegative integer');
445
+ }
446
+ return input;
447
+ }
448
+ export function filterOf(input, facts) {
449
+ if (!plain(input)) invalid('documents', 'expects a filter object');
450
+ known(input, FILTER, '');
451
+ return planOf({
452
+ ...input,
453
+ select: {}
454
+ }, facts);
455
+ }
456
+ function canonical(value) {
457
+ if (Array.isArray(value)) return `[${value.map(canonical).join(',')}]`;
458
+ if (typeof value === 'object' && value !== null) {
459
+ return `{${Object.keys(value).sort().map((name)=>`${JSON.stringify(name)}:${canonical(value[name])}`).join(',')}}`;
460
+ }
461
+ return JSON.stringify(value);
462
+ }
463
+ export function identityOf(plan) {
464
+ return canonical(plan);
465
+ }
17
466
 
18
467
  //# sourceMappingURL=query.js.map
package/dist/query.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["/workspace/packages/mdruntime/src/query.ts"],"sourcesContent":["import type { QueryOptions, QueryResult } from '@agentshouse/query';\nimport type { Document } from '@agentshouse/mdmodel';\nimport type { TypesResult } from './model.js';\n\nexport type QueryInput = {\n room: string;\n roomVersion: string;\n documents: Readonly<Record<string, Document>>;\n model: TypesResult;\n typedSelection: TypesResult | null;\n};\nexport type QueryBinding = (rooms: readonly QueryInput[], options: QueryOptions) => QueryResult;\nexport function rawQuery(rooms: readonly QueryInput[]): QueryResult {\n return {\n roomVersions: Object.fromEntries(rooms.map((room) => [room.room, room.roomVersion])),\n groups: null,\n documents: rooms.flatMap((room) =>\n Object.entries(room.documents)\n .filter(([path]) => path.endsWith('.md'))\n .map(([path, document]) => ({\n ...structuredClone(document),\n type: document.type ?? 'any',\n room: room.room,\n path,\n backlinks: [],\n })),\n ),\n };\n}\n"],"names":["rawQuery","rooms","roomVersions","Object","fromEntries","map","room","roomVersion","groups","documents","flatMap","entries","filter","path","endsWith","document","structuredClone","type","backlinks"],"mappings":"AAYA,OAAO,SAASA,SAASC,KAA4B;IACnD,OAAO;QACLC,cAAcC,OAAOC,WAAW,CAACH,MAAMI,GAAG,CAAC,CAACC,OAAS;gBAACA,KAAKA,IAAI;gBAAEA,KAAKC,WAAW;aAAC;QAClFC,QAAQ;QACRC,WAAWR,MAAMS,OAAO,CAAC,CAACJ,OACxBH,OAAOQ,OAAO,CAACL,KAAKG,SAAS,EAC1BG,MAAM,CAAC,CAAC,CAACC,KAAK,GAAKA,KAAKC,QAAQ,CAAC,QACjCT,GAAG,CAAC,CAAC,CAACQ,MAAME,SAAS,GAAM,CAAA;oBAC1B,GAAGC,gBAAgBD,SAAS;oBAC5BE,MAAMF,SAASE,IAAI,IAAI;oBACvBX,MAAMA,KAAKA,IAAI;oBACfO;oBACAK,WAAW,EAAE;gBACf,CAAA;IAEN;AACF"}
1
+ {"version":3,"sources":["/workspace/packages/mdruntime/src/query.ts"],"sourcesContent":["import type { Definition, FieldSpec } from '@agentshouse/mdmodel';\nimport { normalize } from './paths.js';\n\nexport type Value = string | number | boolean | null;\n\nexport type Predicate =\n | Value\n | { $eq: Value }\n | { $ne: Value }\n | { $in: readonly Value[] }\n | { $nin: readonly Value[] }\n | { $gt?: Value; $gte?: Value; $lt?: Value; $lte?: Value }\n | { $all: readonly Value[] }\n | { $size: number }\n | { $exists: boolean };\n\nexport type Where = {\n $and?: readonly Where[];\n $or?: readonly Where[];\n [field: string]: Predicate | readonly Where[] | undefined;\n};\n\nexport type Related = { types?: readonly string[]; where?: Where; pathPrefix?: string };\n\nexport type Filter = {\n rooms?: readonly string[];\n types?: readonly string[];\n where?: Where;\n pathPrefix?: string;\n hop?: Related & { field: string };\n backlinks?: Related & { field?: string };\n};\n\nexport type Key = 'room' | 'path' | 'type' | { field: string };\n\nexport type Select =\n | 'all'\n | {\n fields?: 'all' | readonly string[];\n sections?: 'all' | readonly string[];\n preamble?: true;\n markdown?: true;\n backlinks?: true;\n };\n\nexport type OrderOptions = {\n nulls?: 'first' | 'last';\n stringSort?: 'lexical' | 'locale';\n locale?: string;\n localeOptions?: Readonly<Record<string, unknown>>;\n};\n\nexport type Direction = 'asc' | 'desc';\n\nexport type DocumentQuery = Filter & {\n select: Select;\n orderBy?: readonly ({ by: Key; direction?: Direction } & OrderOptions)[];\n limit?: number;\n};\n\nexport type GroupQuery = Filter & {\n groupBy: readonly Exclude<Key, 'path'>[];\n orderBy?: readonly { by: 'count' | Exclude<Key, 'path'>; direction?: Direction }[];\n limit?: number;\n};\n\nexport type LocalQuery = DocumentQuery | GroupQuery;\n\nexport type Backlink = { path: string; type: string; field: string };\n\nexport type QueryDocument = {\n room: string;\n path: string;\n type: string;\n fields?: Readonly<Record<string, unknown>>;\n sections?: Readonly<Record<string, string>>;\n preamble?: string;\n markdown?: string;\n backlinks?: readonly Backlink[];\n};\n\nexport type QueryGroup = { key: readonly unknown[]; count: number };\n\nexport type DocumentResult = { documents: readonly QueryDocument[] };\n\nexport type GroupResult = { groups: readonly QueryGroup[] };\n\nexport type QueryResult = DocumentResult | GroupResult;\n\nexport type QueryErrorCode = 'invalid-query' | 'unknown-type' | 'unknown-field' | 'wrong-kind';\n\nexport type RoomFacts = {\n locator: string;\n available: boolean;\n types: readonly Definition[];\n};\n\nexport type HeldRooms = {\n listed: boolean;\n rooms: readonly RoomFacts[];\n};\n\nexport type Test =\n | { op: 'eq'; value: Value }\n | { op: 'ne'; value: Value }\n | { op: 'in'; values: readonly Value[] }\n | { op: 'nin'; values: readonly Value[] }\n | { op: 'range'; bounds: readonly (readonly ['gt' | 'gte' | 'lt' | 'lte', Value])[] }\n | { op: 'all'; values: readonly Value[] }\n | { op: 'size'; size: number }\n | { op: 'exists'; exists: boolean };\n\nexport type Condition =\n | { every: readonly Condition[] }\n | { some: readonly Condition[] }\n | { field: string; test: Test };\n\nexport type Scope = {\n types: readonly string[] | null;\n where: Condition | null;\n pathPrefix: string | null;\n};\n\nexport type KeyPlan =\n | { of: 'room' }\n | { of: 'path' }\n | { of: 'type' }\n | { of: 'field'; field: string };\n\nexport type DocumentShape = {\n kind: 'documents';\n fields: 'all' | readonly string[] | null;\n sections: 'all' | readonly string[] | null;\n preamble: boolean;\n markdown: boolean;\n backlinks: boolean;\n orderBy: readonly { key: KeyPlan; options: OrderOptions & { direction: Direction } }[];\n};\n\nexport type GroupShape = {\n kind: 'groups';\n groupBy: readonly KeyPlan[];\n orderBy: readonly { by: 'count' | number; direction: Direction }[];\n};\n\nexport type Plan = {\n rooms: readonly string[] | null;\n root: Scope;\n hop: (Scope & { field: string }) | null;\n backlinks: (Scope & { field: string | null }) | null;\n shape: DocumentShape | GroupShape;\n limit: number | null;\n};\n\nexport class QueryError extends Error {\n constructor(code: QueryErrorCode, at: string, problem: string) {\n super(`${code} at ${at}: ${problem}`);\n }\n}\n\ntype Entries = Readonly<Record<string, unknown>>;\n\ntype Typing = { untyped: boolean; types: readonly Definition[] };\n\nconst RANGE = ['$gt', '$gte', '$lt', '$lte'] as const;\nconst SINGLE = ['$eq', '$ne', '$in', '$nin', '$all', '$size', '$exists'] as const;\nconst FILTER = ['rooms', 'types', 'where', 'pathPrefix', 'hop', 'backlinks'];\nconst RELATED = ['types', 'where', 'pathPrefix', 'field'];\nconst PARTS = ['fields', 'sections', 'preamble', 'markdown', 'backlinks'];\nconst ORDER = ['by', 'direction', 'nulls', 'stringSort', 'locale', 'localeOptions'];\nconst CALENDAR_DATE = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\nexport function invalid(at: string, problem: string): never {\n throw new QueryError('invalid-query', at, problem);\n}\n\nfunction place(at: string, name: string): string {\n return at === '' ? name : `${at}.${name}`;\n}\n\nexport function plain(value: unknown): value is Entries {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)\n );\n}\n\nexport function known(value: Entries, allowed: readonly string[], at: string) {\n for (const name of Object.keys(value)) {\n if (!allowed.includes(name)) invalid(place(at, name), 'unknown part');\n }\n}\n\nfunction list(input: unknown, at: string): readonly unknown[] {\n if (!Array.isArray(input)) invalid(at, 'expects a list');\n return input;\n}\n\nfunction value(input: unknown, at: string): Value {\n if (Array.isArray(input)) invalid(at, 'a list is not a value');\n if (\n input !== null &&\n typeof input !== 'string' &&\n typeof input !== 'boolean' &&\n !(typeof input === 'number' && Number.isFinite(input))\n ) {\n invalid(at, 'not a value');\n }\n return input;\n}\n\nfunction values(input: unknown, at: string): readonly Value[] {\n return list(input, at).map((item, index) => value(item, `${at}[${index}]`));\n}\n\nfunction names(input: unknown, at: string): readonly string[] {\n const listed = list(input, at);\n if (listed.some((item) => typeof item !== 'string')) invalid(at, 'expects a list of names');\n return [...new Set(listed as readonly string[])].sort();\n}\n\nfunction directory(input: unknown, at: string): string {\n if (typeof input !== 'string' || normalize(input) !== input) {\n invalid(at, 'expects a normalized directory');\n }\n return input;\n}\n\nfunction calendarDate(value: string): boolean {\n const match = CALENDAR_DATE.exec(value);\n if (match === null) return false;\n const [year, month, day] = match.slice(1).map(Number);\n const date = new Date(Date.UTC(year, month - 1, day));\n return (\n date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day\n );\n}\n\nfunction fits(spec: FieldSpec, value: Value): boolean {\n const item = spec.kind === 'list' ? spec.of : spec;\n if (item.kind === 'number') return typeof value === 'number';\n if (typeof value !== 'string') return false;\n if (item.kind === 'enum') return item.values.includes(value);\n if (item.kind === 'date') return calendarDate(value);\n if (item.kind === 'reference') return value !== '' && normalize(value) === value;\n return true;\n}\n\nfunction reference(spec: FieldSpec): boolean {\n return spec.kind === 'reference' || (spec.kind === 'list' && spec.of.kind === 'reference');\n}\n\nfunction typing(\n facts: HeldRooms,\n rooms: readonly string[] | null,\n types: readonly string[] | null,\n at: string,\n): Typing {\n const read =\n rooms === null ? facts.rooms : facts.rooms.filter((room) => rooms.includes(room.locator));\n const acquiring =\n !facts.listed &&\n (rooms === null ||\n rooms.some((locator) => !facts.rooms.some((room) => room.locator === locator)));\n const available = !acquiring && read.every((room) => room.available);\n const declared = read.flatMap((room) => room.types);\n for (const name of types ?? []) {\n if (name === 'any' || !available || declared.some((type) => type.name === name)) continue;\n throw new QueryError('unknown-type', place(at, 'types'), `no model it reads declares ${name}`);\n }\n return {\n untyped: types === null || types.includes('any') || !available,\n types: types === null ? declared : declared.filter((type) => types.includes(type.name)),\n };\n}\n\nfunction specs(typed: Typing, field: string, at: string): readonly FieldSpec[] {\n const declared = typed.types.flatMap((type) =>\n Object.hasOwn(type.fields, field) ? [type.fields[field]] : [],\n );\n if (declared.length === 0 && !typed.untyped) {\n throw new QueryError('unknown-field', at, `no MD Type it reads declares ${field}`);\n }\n return declared;\n}\n\nfunction kind(declared: readonly FieldSpec[], checked: Value, at: string) {\n if (checked === null || declared.length === 0 || declared.some((spec) => fits(spec, checked))) {\n return;\n }\n throw new QueryError('wrong-kind', at, `${JSON.stringify(checked)} is not of its field's kind`);\n}\n\nfunction listed(declared: readonly FieldSpec[], list: boolean): boolean {\n return declared.length > 0 && declared.every((spec) => (spec.kind === 'list') === list);\n}\n\nfunction test(declared: readonly FieldSpec[], input: unknown, at: string): Test {\n if (!plain(input)) {\n const equal = value(input, at);\n kind(declared, equal, at);\n return { op: 'eq', value: equal };\n }\n const operators = Object.keys(input);\n if (operators.length === 0) invalid(at, 'names no operator');\n if (operators.some((operator) => (RANGE as readonly string[]).includes(operator))) {\n const stray = operators.find((operator) => !(RANGE as readonly string[]).includes(operator));\n if (stray !== undefined) invalid(place(at, stray), 'cannot join a range');\n if (listed(declared, true)) invalid(at, 'a range on a list');\n return {\n op: 'range',\n bounds: RANGE.filter((operator) => operators.includes(operator)).map((operator) => {\n const bound = value(input[operator], place(at, operator));\n if (bound === null) invalid(place(at, operator), 'a range bound is never null');\n kind(declared, bound, place(at, operator));\n return [operator.slice(1) as 'gt' | 'gte' | 'lt' | 'lte', bound] as const;\n }),\n };\n }\n if (operators.length > 1) invalid(place(at, operators[1]), 'names a second operator');\n const [operator] = operators;\n const where = place(at, operator);\n if (!(SINGLE as readonly string[]).includes(operator)) invalid(where, 'unknown operator');\n const operand = input[operator];\n if (operator === '$eq' || operator === '$ne') {\n const compared = value(operand, where);\n kind(declared, compared, where);\n return operator === '$eq' ? { op: 'eq', value: compared } : { op: 'ne', value: compared };\n }\n if (operator === '$in' || operator === '$nin' || operator === '$all') {\n const compared = values(operand, where);\n compared.forEach((item, index) => kind(declared, item, `${where}[${index}]`));\n if (operator === '$in') return { op: 'in', values: compared };\n if (operator === '$nin') return { op: 'nin', values: compared };\n if (compared.includes(null)) invalid(where, 'a list holds no null');\n if (listed(declared, false)) invalid(where, 'the field is not a list');\n return { op: 'all', values: compared };\n }\n if (operator === '$size') {\n if (!Number.isSafeInteger(operand) || (operand as number) < 0) {\n invalid(where, 'expects a nonnegative integer');\n }\n if (listed(declared, false)) invalid(where, 'the field is not a list');\n return { op: 'size', size: operand as number };\n }\n if (typeof operand !== 'boolean') invalid(where, 'expects true or false');\n return { op: 'exists', exists: operand };\n}\n\nfunction condition(typed: Typing, input: unknown, at: string): Condition {\n if (!plain(input)) invalid(at, 'expects an object of field predicates');\n const conditions: Condition[] = [];\n for (const name of Object.keys(input).sort()) {\n const where = place(at, name);\n const entry = input[name];\n if (name === '$and' || name === '$or') {\n const nested = list(entry, where).map((item, index) =>\n condition(typed, item, `${where}[${index}]`),\n );\n if (nested.length === 0) invalid(where, 'expects a nonempty list');\n conditions.push(name === '$and' ? { every: nested } : { some: nested });\n continue;\n }\n if (name.startsWith('$')) invalid(where, 'unknown operator');\n conditions.push({ field: name, test: test(specs(typed, name, where), entry, where) });\n }\n if (conditions.length === 0) invalid(at, 'names no field');\n return conditions.length === 1 ? conditions[0] : { every: conditions };\n}\n\nfunction scope(\n facts: HeldRooms,\n rooms: readonly string[] | null,\n input: Entries,\n at: string,\n): Scope & { typed: Typing } {\n const types = input.types === undefined ? null : names(input.types, place(at, 'types'));\n const typed = typing(facts, rooms, types, at);\n return {\n typed,\n types,\n where:\n input.where === undefined || (plain(input.where) && Object.keys(input.where).length === 0)\n ? null\n : condition(typed, input.where, place(at, 'where')),\n pathPrefix:\n input.pathPrefix === undefined ? null : directory(input.pathPrefix, place(at, 'pathPrefix')),\n };\n}\n\nfunction referenceField(typed: Typing, field: unknown, at: string): string {\n if (typeof field !== 'string') invalid(at, 'expects a field name');\n const declared = specs(typed, field, at);\n if (declared.length > 0 && !declared.some(reference)) invalid(at, 'not a reference field');\n return field;\n}\n\nfunction hopOf(\n facts: HeldRooms,\n rooms: readonly string[] | null,\n root: Typing,\n input: unknown,\n): Plan['hop'] {\n if (!plain(input)) invalid('hop', 'expects an object');\n known(input, RELATED, 'hop');\n const field = referenceField(root, input.field, 'hop.field');\n const { types, where, pathPrefix } = scope(facts, rooms, input, 'hop');\n return { types, where, pathPrefix, field };\n}\n\nfunction backlinksOf(\n facts: HeldRooms,\n rooms: readonly string[] | null,\n input: unknown,\n): Plan['backlinks'] {\n if (!plain(input)) invalid('backlinks', 'expects an object');\n known(input, RELATED, 'backlinks');\n const { typed, types, where, pathPrefix } = scope(facts, rooms, input, 'backlinks');\n const field =\n input.field === undefined ? null : referenceField(typed, input.field, 'backlinks.field');\n return { types, where, pathPrefix, field };\n}\n\nfunction keyPlan(typed: Typing, input: unknown, at: string, path: boolean): KeyPlan {\n if (input === 'room' || input === 'type' || (path && input === 'path')) return { of: input };\n if (plain(input) && typeof input.field === 'string' && Object.keys(input).length === 1) {\n specs(typed, input.field, place(at, 'field'));\n return { of: 'field', field: input.field };\n }\n return invalid(\n at,\n path ? 'expects room, path, type or a field' : 'expects room, type or a field',\n );\n}\n\nfunction direction(input: unknown, at: string): Direction {\n if (input === undefined) return 'asc';\n if (input !== 'asc' && input !== 'desc') invalid(at, 'expects asc or desc');\n return input;\n}\n\nfunction orderOptions(input: Entries, at: string): OrderOptions & { direction: Direction } {\n const options: OrderOptions & { direction: Direction } = {\n direction: direction(input.direction, place(at, 'direction')),\n };\n if (input.nulls !== undefined) {\n if (input.nulls !== 'first' && input.nulls !== 'last') {\n invalid(place(at, 'nulls'), 'expects first or last');\n }\n options.nulls = input.nulls;\n }\n if (input.stringSort !== undefined) {\n if (input.stringSort !== 'lexical' && input.stringSort !== 'locale') {\n invalid(place(at, 'stringSort'), 'expects lexical or locale');\n }\n options.stringSort = input.stringSort;\n }\n if (input.locale !== undefined) {\n if (typeof input.locale !== 'string' || !collates(input.locale, undefined)) {\n invalid(place(at, 'locale'), 'expects a locale name');\n }\n options.locale = input.locale;\n }\n if (input.localeOptions !== undefined) {\n if (!plain(input.localeOptions) || !collates(options.locale, input.localeOptions)) {\n invalid(place(at, 'localeOptions'), 'expects collation options');\n }\n options.localeOptions = input.localeOptions;\n }\n return options;\n}\n\nfunction collates(locale: string | undefined, options: Entries | undefined): boolean {\n try {\n ''.localeCompare('', locale, options);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction parts(typed: Typing, input: unknown, at: string, fields: boolean) {\n if (input === undefined) return null;\n if (input === 'all') return 'all';\n const named = list(input, at);\n named.forEach((name, index) => {\n if (typeof name !== 'string') invalid(`${at}[${index}]`, 'expects a name');\n if (fields) specs(typed, name, `${at}[${index}]`);\n });\n return named as readonly string[];\n}\n\nfunction flag(input: unknown, at: string): boolean {\n if (input === undefined) return false;\n if (input !== true) invalid(at, 'expects true');\n return true;\n}\n\nfunction documentShape(typed: Typing, input: Entries): DocumentShape {\n const orderBy = (input.orderBy === undefined ? [] : list(input.orderBy, 'orderBy')).map(\n (clause, index) => {\n const at = `orderBy[${index}]`;\n if (!plain(clause)) invalid(at, 'expects an order clause');\n known(clause, ORDER, at);\n return {\n key: keyPlan(typed, clause.by, place(at, 'by'), true),\n options: orderOptions(clause, at),\n };\n },\n );\n const select = input.select;\n if (select === 'all') {\n return {\n kind: 'documents',\n fields: 'all',\n sections: 'all',\n preamble: true,\n markdown: true,\n backlinks: true,\n orderBy,\n };\n }\n if (!plain(select)) invalid('select', \"expects 'all' or the parts to return\");\n known(select, PARTS, 'select');\n return {\n kind: 'documents',\n fields: parts(typed, select.fields, 'select.fields', true),\n sections: parts(typed, select.sections, 'select.sections', false),\n preamble: flag(select.preamble, 'select.preamble'),\n markdown: flag(select.markdown, 'select.markdown'),\n backlinks: flag(select.backlinks, 'select.backlinks'),\n orderBy,\n };\n}\n\nfunction groupShape(typed: Typing, input: Entries): GroupShape {\n const groupBy = list(input.groupBy, 'groupBy').map((key, index) =>\n keyPlan(typed, key, `groupBy[${index}]`, false),\n );\n if (groupBy.length === 0) invalid('groupBy', 'names no key');\n const grouped = groupBy.map((key) => JSON.stringify(key));\n const orderBy = (input.orderBy === undefined ? [] : list(input.orderBy, 'orderBy')).map(\n (clause, index) => {\n const at = `orderBy[${index}]`;\n if (!plain(clause)) invalid(at, 'expects an order clause');\n known(clause, ['by', 'direction'], at);\n const by =\n clause.by === 'count'\n ? ('count' as const)\n : grouped.indexOf(JSON.stringify(keyPlan(typed, clause.by, place(at, 'by'), false)));\n if (by === -1) invalid(place(at, 'by'), 'orders by a key the query does not group by');\n return { by, direction: direction(clause.direction, place(at, 'direction')) };\n },\n );\n return { kind: 'groups', groupBy, orderBy };\n}\n\nexport function planOf(input: unknown, facts: HeldRooms): Plan {\n if (!plain(input)) invalid('query', 'expects a query object');\n const grouped = input.groupBy !== undefined;\n if (grouped && input.select !== undefined) invalid('select', 'a grouped query selects nothing');\n if (!grouped && input.select === undefined) invalid('select', 'a Document query must select');\n known(input, [...FILTER, 'orderBy', 'limit', grouped ? 'groupBy' : 'select'], '');\n const limit = limitOf(input.limit);\n const rooms = input.rooms === undefined ? null : names(input.rooms, 'rooms');\n const { typed, ...root } = scope(facts, rooms, input, '');\n return {\n rooms,\n root,\n hop: input.hop === undefined ? null : hopOf(facts, rooms, typed, input.hop),\n backlinks: input.backlinks === undefined ? null : backlinksOf(facts, rooms, input.backlinks),\n shape: grouped ? groupShape(typed, input) : documentShape(typed, input),\n limit,\n };\n}\n\nexport function limitOf(input: unknown): number | null {\n if (input === undefined) return null;\n if (!Number.isSafeInteger(input) || (input as number) < 0) {\n invalid('limit', 'expects a nonnegative integer');\n }\n return input as number;\n}\n\nexport function filterOf(input: unknown, facts: HeldRooms): Plan {\n if (!plain(input)) invalid('documents', 'expects a filter object');\n known(input, FILTER, '');\n return planOf({ ...input, select: {} }, facts);\n}\n\nfunction canonical(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(canonical).join(',')}]`;\n if (typeof value === 'object' && value !== null) {\n return `{${Object.keys(value)\n .sort()\n .map((name) => `${JSON.stringify(name)}:${canonical((value as Entries)[name])}`)\n .join(',')}}`;\n }\n return JSON.stringify(value);\n}\n\nexport function identityOf(plan: Plan): string {\n return canonical(plan);\n}\n"],"names":["normalize","QueryError","Error","code","at","problem","RANGE","SINGLE","FILTER","RELATED","PARTS","ORDER","CALENDAR_DATE","invalid","place","name","plain","value","Array","isArray","Object","getPrototypeOf","prototype","known","allowed","keys","includes","list","input","Number","isFinite","values","map","item","index","names","listed","some","Set","sort","directory","calendarDate","match","exec","year","month","day","slice","date","Date","UTC","getUTCFullYear","getUTCMonth","getUTCDate","fits","spec","kind","of","reference","typing","facts","rooms","types","read","filter","room","locator","acquiring","available","every","declared","flatMap","type","untyped","specs","typed","field","hasOwn","fields","length","checked","JSON","stringify","test","equal","op","operators","operator","stray","find","undefined","bounds","bound","where","operand","compared","forEach","isSafeInteger","size","exists","condition","conditions","entry","nested","push","startsWith","scope","pathPrefix","referenceField","hopOf","root","backlinksOf","keyPlan","path","direction","orderOptions","options","nulls","stringSort","locale","collates","localeOptions","localeCompare","parts","named","flag","documentShape","orderBy","clause","key","by","select","sections","preamble","markdown","backlinks","groupShape","groupBy","grouped","indexOf","planOf","limit","limitOf","hop","shape","filterOf","canonical","join","identityOf","plan"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ChangeSet } from './change-set.js';
2
+ import type { Plan, QueryResult } from './query.js';
3
+ import type { SearchedDocument } from './search.js';
4
+ export type ReadSide = {
5
+ apply(set: ChangeSet): void;
6
+ query(plan: Plan): Promise<QueryResult>;
7
+ observe(plan: Plan, identity: string, listener: (result: QueryResult) => void): () => void;
8
+ documents(): readonly SearchedDocument[];
9
+ document(room: string, path: string): SearchedDocument | null;
10
+ close(): void;
11
+ };
12
+ export declare function createReadSide(): ReadSide;
13
+ //# sourceMappingURL=read-side.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-side.d.ts","sourceRoot":"","sources":["../src/read-side.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAOV,IAAI,EAEJ,WAAW,EAIZ,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAoDpD,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACxC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC3F,SAAS,IAAI,SAAS,gBAAgB,EAAE,CAAC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAAC;IAC9D,KAAK,IAAI,IAAI,CAAC;CACf,CAAC;AAqPF,wBAAgB,cAAc,IAAI,QAAQ,CAmHzC"}