@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
@@ -0,0 +1,393 @@
1
+ import { and, BasicIndex, configureIndexDevMode, count, createCollection, createLiveQueryCollection, deepEquals, eq, gt, gte, inArray, isNull, isUndefined, lt, lte, not, or, toArray } from '@tanstack/db';
2
+ import { documentKey } from './rows.js';
3
+ function every(expressions) {
4
+ const [first, second, ...rest] = expressions;
5
+ return second === undefined ? first : and(first, second, ...rest);
6
+ }
7
+ function some(expressions) {
8
+ const [first, second, ...rest] = expressions;
9
+ return second === undefined ? first : or(first, second, ...rest);
10
+ }
11
+ function equal(field, value) {
12
+ return or(eq(field, value), inArray(value, field));
13
+ }
14
+ function tested(test, field, size, written) {
15
+ if (test.op === 'eq') return test.value === null ? isNull(field) : equal(field, test.value);
16
+ if (test.op === 'ne') {
17
+ return test.value === null ? not(isNull(field)) : or(isUndefined(field), isNull(field), not(equal(field, test.value)));
18
+ }
19
+ if (test.op === 'in' || test.op === 'nin') {
20
+ const matches = test.values.length === 0 ? inArray(field, []) : some(test.values.map((value)=>value === null ? isNull(field) : equal(field, value)));
21
+ if (test.op === 'in') return matches;
22
+ return some([
23
+ isUndefined(field),
24
+ ...test.values.includes(null) ? [] : [
25
+ isNull(field)
26
+ ],
27
+ not(matches)
28
+ ]);
29
+ }
30
+ if (test.op === 'range') {
31
+ const compare = {
32
+ gt,
33
+ gte,
34
+ lt,
35
+ lte
36
+ };
37
+ return every(test.bounds.map(([operator, bound])=>compare[operator](field, bound)));
38
+ }
39
+ if (test.op === 'all') {
40
+ return every([
41
+ not(isUndefined(size)),
42
+ ...test.values.map((value)=>inArray(value, field))
43
+ ]);
44
+ }
45
+ if (test.op === 'size') return eq(size, test.size);
46
+ return test.exists ? not(isUndefined(written)) : isUndefined(written);
47
+ }
48
+ function conditioned(condition, row) {
49
+ if ('every' in condition) return every(condition.every.map((item)=>conditioned(item, row)));
50
+ if ('some' in condition) return some(condition.some.map((item)=>conditioned(item, row)));
51
+ return tested(condition.test, row.values[condition.field], row.sizes[condition.field], row.fields[condition.field]);
52
+ }
53
+ function scoped(scope, row, rooms) {
54
+ return every([
55
+ eq(row.kind, 'document'),
56
+ ...rooms === null ? [] : [
57
+ inArray(row.room, [
58
+ ...rooms
59
+ ])
60
+ ],
61
+ ...scope.types === null ? [] : [
62
+ inArray(row.type, [
63
+ ...scope.types
64
+ ])
65
+ ],
66
+ ...scope.pathPrefix === null ? [] : [
67
+ inArray(scope.pathPrefix, row.directories)
68
+ ],
69
+ ...scope.where === null ? [] : [
70
+ conditioned(scope.where, row)
71
+ ]
72
+ ]);
73
+ }
74
+ function keyed(key, row) {
75
+ return key.of === 'field' ? row.values[key.field] : row[key.of];
76
+ }
77
+ function live(query) {
78
+ return createLiveQueryCollection({
79
+ query: query,
80
+ startSync: true
81
+ });
82
+ }
83
+ function related(q, rows, scope, field, kept) {
84
+ const matched = kept === 'source' ? 'target' : 'source';
85
+ const from = q.from({
86
+ r: rows
87
+ });
88
+ return from.where(({ r })=>every([
89
+ eq(r.kind, 'reference'),
90
+ ...field === null ? [] : [
91
+ eq(r.field, field)
92
+ ]
93
+ ])).innerJoin({
94
+ m: rows
95
+ }, ({ r, m })=>eq(r[matched], m.key)).where(({ m })=>scoped(scope, m, null)).groupBy(({ r })=>r[kept]).select(({ r })=>({
96
+ key: r[kept]
97
+ }));
98
+ }
99
+ function filtered(q, rows, plan) {
100
+ const from = q.from({
101
+ d: rows
102
+ });
103
+ let query = from.where(({ d })=>scoped(plan.root, d, plan.rooms));
104
+ if (plan.hop !== null) {
105
+ const hop = related(q, rows, plan.hop, plan.hop.field, 'source');
106
+ query = query.innerJoin({
107
+ h: hop
108
+ }, ({ d, h })=>eq(d.key, h.key));
109
+ }
110
+ if (plan.backlinks !== null) {
111
+ const backlinks = related(q, rows, plan.backlinks, plan.backlinks.field, 'target');
112
+ query = query.innerJoin({
113
+ k: backlinks
114
+ }, ({ d, k })=>eq(d.key, k.key));
115
+ }
116
+ return query;
117
+ }
118
+ function named(prefix, names, source) {
119
+ return Object.fromEntries(names.map((name, index)=>[
120
+ `${prefix}${index}`,
121
+ source[name]
122
+ ]));
123
+ }
124
+ function documents(q, rows, plan, shape) {
125
+ let query = filtered(q, rows, plan);
126
+ if (shape.sections !== null || shape.preamble || shape.markdown) {
127
+ query = query.innerJoin({
128
+ b: rows
129
+ }, ({ d, b })=>eq(d.body, b.key));
130
+ }
131
+ for (const { key, options } of shape.orderBy){
132
+ query = query.orderBy(({ d })=>keyed(key, d), options);
133
+ }
134
+ if (shape.orderBy.length === 0 && plan.limit !== null) {
135
+ query = query.orderBy(({ d })=>d.key, {
136
+ stringSort: 'lexical'
137
+ });
138
+ }
139
+ if (plan.limit !== null) query = query.limit(plan.limit);
140
+ return query.select(({ d, b })=>({
141
+ room: d.room,
142
+ path: d.path,
143
+ type: d.type,
144
+ ...shape.fields === 'all' ? {
145
+ fields: d.fields
146
+ } : {},
147
+ ...Array.isArray(shape.fields) ? named('field', shape.fields, d.fields) : {},
148
+ ...shape.sections === 'all' ? {
149
+ sections: b.sections
150
+ } : {},
151
+ ...Array.isArray(shape.sections) ? named('section', shape.sections, b.sections) : {},
152
+ ...shape.preamble ? {
153
+ preamble: b.preamble
154
+ } : {},
155
+ ...shape.markdown ? {
156
+ markdown: b.markdown
157
+ } : {},
158
+ ...shape.backlinks ? {
159
+ backlinks: toArray(backlinked(q, rows, d))
160
+ } : {}
161
+ }));
162
+ }
163
+ function backlinked(q, rows, document) {
164
+ const from = q.from({
165
+ r: rows
166
+ });
167
+ return from.where(({ r })=>eq(r.target, document.key)).orderBy(({ r })=>r.path, {
168
+ stringSort: 'lexical'
169
+ }).orderBy(({ r })=>r.field, {
170
+ stringSort: 'lexical'
171
+ }).select(({ r })=>({
172
+ path: r.path,
173
+ type: r.type,
174
+ field: r.field
175
+ }));
176
+ }
177
+ function groups(q, stage, shape, limit) {
178
+ const keys = shape.groupBy.map((_, index)=>`key${index}`);
179
+ const from = q.from({
180
+ m: stage
181
+ });
182
+ let query = from.groupBy(({ m })=>keys.map((key)=>m[key]));
183
+ for (const { by, direction } of shape.orderBy){
184
+ query = query.orderBy(({ m })=>by === 'count' ? count(m.key) : m[keys[by]], direction);
185
+ }
186
+ if (limit !== null && shape.orderBy.length > 0) query = query.limit(limit);
187
+ return query.select(({ m })=>({
188
+ ...Object.fromEntries(keys.map((key)=>[
189
+ key,
190
+ m[key]
191
+ ])),
192
+ count: count(m.key)
193
+ }));
194
+ }
195
+ function built(rows, plan) {
196
+ const shape = plan.shape;
197
+ if (shape.kind === 'documents') {
198
+ const collection = live((q)=>documents(q, rows, plan, shape));
199
+ return {
200
+ live: collection,
201
+ dispose: ()=>void collection.cleanup()
202
+ };
203
+ }
204
+ const stage = live((q)=>filtered(q, rows, plan).select(({ d })=>({
205
+ key: d.key,
206
+ ...Object.fromEntries(shape.groupBy.map((key, index)=>[
207
+ `key${index}`,
208
+ keyed(key, d)
209
+ ]))
210
+ })));
211
+ const collection = live((q)=>groups(q, stage, shape, plan.limit));
212
+ return {
213
+ live: collection,
214
+ dispose: ()=>{
215
+ void collection.cleanup();
216
+ void stage.cleanup();
217
+ }
218
+ };
219
+ }
220
+ function present(entries) {
221
+ return Object.fromEntries(entries.filter(([, value])=>value !== undefined));
222
+ }
223
+ function part(row, prefix, names, whole) {
224
+ if (names === 'all') return whole;
225
+ return present(names.map((name, index)=>[
226
+ name,
227
+ row[`${prefix}${index}`]
228
+ ]));
229
+ }
230
+ function documentOf(row, shape) {
231
+ return {
232
+ room: row.room,
233
+ path: row.path,
234
+ type: row.type,
235
+ ...shape.fields === null ? {} : {
236
+ fields: part(row, 'field', shape.fields, row.fields)
237
+ },
238
+ ...shape.sections === null ? {} : {
239
+ sections: part(row, 'section', shape.sections, row.sections)
240
+ },
241
+ ...shape.preamble ? {
242
+ preamble: row.preamble
243
+ } : {},
244
+ ...shape.markdown ? {
245
+ markdown: row.markdown
246
+ } : {},
247
+ ...shape.backlinks ? {
248
+ backlinks: row.backlinks.map(({ path, type, field })=>({
249
+ path,
250
+ type,
251
+ field
252
+ }))
253
+ } : {}
254
+ };
255
+ }
256
+ function resultOf(plan, rows) {
257
+ const shape = plan.shape;
258
+ if (shape.kind === 'documents') {
259
+ return structuredClone({
260
+ documents: rows.map((row)=>documentOf(row, shape))
261
+ });
262
+ }
263
+ const bounded = shape.orderBy.length === 0 && plan.limit !== null ? rows.slice(0, plan.limit) : rows;
264
+ return structuredClone({
265
+ groups: bounded.map((row)=>({
266
+ key: shape.groupBy.map((_, index)=>row[`key${index}`]),
267
+ count: row.count
268
+ }))
269
+ });
270
+ }
271
+ export function createReadSide() {
272
+ configureIndexDevMode({
273
+ enabled: false
274
+ });
275
+ let sync;
276
+ const rows = createCollection({
277
+ getKey: (row)=>row.key,
278
+ gcTime: 0,
279
+ startSync: true,
280
+ autoIndex: 'eager',
281
+ defaultIndexType: BasicIndex,
282
+ sync: {
283
+ rowUpdateMode: 'full',
284
+ sync: (params)=>{
285
+ sync = params;
286
+ params.markReady();
287
+ }
288
+ }
289
+ });
290
+ const shared = new Map();
291
+ function searched(row) {
292
+ const body = rows.get(row.body);
293
+ return {
294
+ room: row.room,
295
+ path: row.path,
296
+ type: row.type,
297
+ fields: row.fields,
298
+ preamble: body.preamble,
299
+ sections: body.sections
300
+ };
301
+ }
302
+ function publish(entry) {
303
+ const next = resultOf(entry.plan, entry.built.live.toArray);
304
+ if (deepEquals(entry.result, next)) return;
305
+ entry.result = next;
306
+ for (const listener of entry.listeners)listener(next);
307
+ }
308
+ return {
309
+ apply (set) {
310
+ const next = new Map();
311
+ for (const change of set.documents){
312
+ for (const row of change.before)next.set(row.key, null);
313
+ for (const row of change.after)next.set(row.key, row);
314
+ }
315
+ if (next.size === 0) return;
316
+ sync.begin();
317
+ for (const [key, row] of next){
318
+ if (row === null) {
319
+ if (rows.has(key)) sync.write({
320
+ type: 'delete',
321
+ key
322
+ });
323
+ continue;
324
+ }
325
+ sync.write({
326
+ type: rows.has(key) ? 'update' : 'insert',
327
+ value: row
328
+ });
329
+ }
330
+ sync.commit();
331
+ },
332
+ async query (plan) {
333
+ const { live: collection, dispose } = built(rows, plan);
334
+ try {
335
+ return resultOf(plan, await collection.toArrayWhenReady());
336
+ } finally{
337
+ dispose();
338
+ }
339
+ },
340
+ observe (plan, identity, listener) {
341
+ let entry = shared.get(identity);
342
+ if (entry === undefined) {
343
+ const created = {
344
+ plan,
345
+ built: built(rows, plan),
346
+ result: undefined,
347
+ listeners: new Set(),
348
+ subscription: null
349
+ };
350
+ created.built.live.on('status:change', ({ status })=>{
351
+ if (status === 'cleaned-up' && created.listeners.size === 0) shared.delete(identity);
352
+ });
353
+ shared.set(identity, created);
354
+ entry = created;
355
+ }
356
+ const observed = entry;
357
+ observed.listeners.add(listener);
358
+ observed.built.live.onFirstReady(()=>{
359
+ if (!observed.listeners.has(listener)) return;
360
+ if (observed.subscription === null) {
361
+ observed.result = resultOf(observed.plan, observed.built.live.toArray);
362
+ observed.subscription = observed.built.live.subscribeChanges(()=>{
363
+ publish(observed);
364
+ });
365
+ }
366
+ listener(observed.result);
367
+ });
368
+ return ()=>{
369
+ if (!observed.listeners.delete(listener) || observed.listeners.size > 0) return;
370
+ observed.subscription?.unsubscribe();
371
+ observed.subscription = null;
372
+ };
373
+ },
374
+ documents () {
375
+ return rows.toArray.filter((row)=>row.kind === 'document').map(searched);
376
+ },
377
+ document (room, path) {
378
+ const row = rows.get(documentKey(room, path));
379
+ return row === undefined ? null : searched(row);
380
+ },
381
+ close () {
382
+ for (const entry of shared.values()){
383
+ entry.listeners.clear();
384
+ entry.subscription?.unsubscribe();
385
+ entry.built.dispose();
386
+ }
387
+ shared.clear();
388
+ void rows.cleanup();
389
+ }
390
+ };
391
+ }
392
+
393
+ //# sourceMappingURL=read-side.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/workspace/packages/mdruntime/src/read-side.ts"],"sourcesContent":["import {\n and,\n BasicIndex,\n configureIndexDevMode,\n count,\n createCollection,\n createLiveQueryCollection,\n deepEquals,\n eq,\n gt,\n gte,\n inArray,\n isNull,\n isUndefined,\n lt,\n lte,\n not,\n or,\n toArray,\n type Collection,\n type Context,\n type InitialQueryBuilder,\n type QueryBuilder,\n type Ref,\n type SyncConfig,\n} from '@tanstack/db';\nimport type { ChangeSet } from './change-set.js';\nimport type {\n Condition,\n Direction,\n DocumentShape,\n GroupShape,\n KeyPlan,\n OrderOptions,\n Plan,\n QueryDocument,\n QueryResult,\n Scope,\n Test,\n Value,\n} from './query.js';\nimport { documentKey, type Row } from './rows.js';\nimport type { SearchedDocument } from './search.js';\n\ntype Stored = {\n key: string;\n kind: string;\n room: string;\n path: string;\n type: string;\n body: string;\n source: string;\n target: string;\n field: string;\n fields: Readonly<Record<string, unknown>>;\n values: Readonly<Record<string, unknown>>;\n sizes: Readonly<Record<string, number>>;\n directories: readonly string[];\n preamble: string;\n sections: Readonly<Record<string, string>>;\n markdown: string;\n} & Readonly<Record<string, unknown>>;\n\ntype Reference = Ref<Stored>;\n\ntype Field = Reference['values'][string];\n\ntype Size = Reference['sizes'][string];\n\ntype Refs = Readonly<Record<string, Reference>>;\n\ntype Expression = ReturnType<typeof eq>;\n\ntype Builder = {\n where(callback: (refs: Refs) => Expression): Builder;\n innerJoin(source: Readonly<Record<string, unknown>>, on: (refs: Refs) => Expression): Builder;\n groupBy(callback: (refs: Refs) => unknown): Builder;\n orderBy(callback: (refs: Refs) => unknown, options: Direction | OrderOptions): Builder;\n limit(count: number): Builder;\n select(callback: (refs: Refs) => object): object;\n};\n\ntype Live = Collection<Stored, string | number>;\n\ntype Built = { live: Live; dispose(): void };\n\ntype Shared = {\n plan: Plan;\n built: Built;\n result: QueryResult | undefined;\n listeners: Set<(result: QueryResult) => void>;\n subscription: { unsubscribe(): void } | null;\n};\n\nexport type ReadSide = {\n apply(set: ChangeSet): void;\n query(plan: Plan): Promise<QueryResult>;\n observe(plan: Plan, identity: string, listener: (result: QueryResult) => void): () => void;\n documents(): readonly SearchedDocument[];\n document(room: string, path: string): SearchedDocument | null;\n close(): void;\n};\n\nfunction every(expressions: readonly Expression[]): Expression {\n const [first, second, ...rest] = expressions;\n return second === undefined ? first : and(first, second, ...rest);\n}\n\nfunction some(expressions: readonly Expression[]): Expression {\n const [first, second, ...rest] = expressions;\n return second === undefined ? first : or(first, second, ...rest);\n}\n\nfunction equal(field: Field, value: Exclude<Value, null>): Expression {\n return or(eq(field, value), inArray(value, field));\n}\n\nfunction tested(test: Test, field: Field, size: Size, written: Field): Expression {\n if (test.op === 'eq') return test.value === null ? isNull(field) : equal(field, test.value);\n if (test.op === 'ne') {\n return test.value === null\n ? not(isNull(field))\n : or(isUndefined(field), isNull(field), not(equal(field, test.value)));\n }\n if (test.op === 'in' || test.op === 'nin') {\n const matches =\n test.values.length === 0\n ? inArray(field, [])\n : some(test.values.map((value) => (value === null ? isNull(field) : equal(field, value))));\n if (test.op === 'in') return matches;\n return some([\n isUndefined(field),\n ...(test.values.includes(null) ? [] : [isNull(field)]),\n not(matches),\n ]);\n }\n if (test.op === 'range') {\n const compare = { gt, gte, lt, lte };\n return every(test.bounds.map(([operator, bound]) => compare[operator](field, bound)));\n }\n if (test.op === 'all') {\n return every([not(isUndefined(size)), ...test.values.map((value) => inArray(value, field))]);\n }\n if (test.op === 'size') return eq(size, test.size);\n return test.exists ? not(isUndefined(written)) : isUndefined(written);\n}\n\nfunction conditioned(condition: Condition, row: Reference): Expression {\n if ('every' in condition) return every(condition.every.map((item) => conditioned(item, row)));\n if ('some' in condition) return some(condition.some.map((item) => conditioned(item, row)));\n return tested(\n condition.test,\n row.values[condition.field],\n row.sizes[condition.field],\n row.fields[condition.field],\n );\n}\n\nfunction scoped(scope: Scope, row: Reference, rooms: readonly string[] | null): Expression {\n return every([\n eq(row.kind, 'document'),\n ...(rooms === null ? [] : [inArray(row.room, [...rooms])]),\n ...(scope.types === null ? [] : [inArray(row.type, [...scope.types])]),\n ...(scope.pathPrefix === null ? [] : [inArray(scope.pathPrefix, row.directories)]),\n ...(scope.where === null ? [] : [conditioned(scope.where, row)]),\n ]);\n}\n\nfunction keyed(key: KeyPlan, row: Reference): Field | Reference['room'] {\n return key.of === 'field' ? row.values[key.field] : row[key.of];\n}\n\nfunction live(query: (q: InitialQueryBuilder) => object): Live {\n return createLiveQueryCollection({\n query: query as (q: InitialQueryBuilder) => QueryBuilder<Context>,\n startSync: true,\n }) as unknown as Live;\n}\n\nfunction related(\n q: InitialQueryBuilder,\n rows: Collection<Stored, string>,\n scope: Scope,\n field: string | null,\n kept: 'source' | 'target',\n): object {\n const matched = kept === 'source' ? 'target' : 'source';\n const from: Builder = q.from({ r: rows });\n return from\n .where(({ r }) =>\n every([eq(r.kind, 'reference'), ...(field === null ? [] : [eq(r.field, field)])]),\n )\n .innerJoin({ m: rows }, ({ r, m }) => eq(r[matched], m.key))\n .where(({ m }) => scoped(scope, m, null))\n .groupBy(({ r }) => r[kept])\n .select(({ r }) => ({ key: r[kept] }));\n}\n\nfunction filtered(q: InitialQueryBuilder, rows: Collection<Stored, string>, plan: Plan): Builder {\n const from: Builder = q.from({ d: rows });\n let query = from.where(({ d }) => scoped(plan.root, d, plan.rooms));\n if (plan.hop !== null) {\n const hop = related(q, rows, plan.hop, plan.hop.field, 'source');\n query = query.innerJoin({ h: hop }, ({ d, h }) => eq(d.key, h.key));\n }\n if (plan.backlinks !== null) {\n const backlinks = related(q, rows, plan.backlinks, plan.backlinks.field, 'target');\n query = query.innerJoin({ k: backlinks }, ({ d, k }) => eq(d.key, k.key));\n }\n return query;\n}\n\nfunction named<T>(prefix: string, names: readonly string[], source: Readonly<Record<string, T>>) {\n return Object.fromEntries(names.map((name, index) => [`${prefix}${index}`, source[name]]));\n}\n\nfunction documents(\n q: InitialQueryBuilder,\n rows: Collection<Stored, string>,\n plan: Plan,\n shape: DocumentShape,\n): object {\n let query = filtered(q, rows, plan);\n if (shape.sections !== null || shape.preamble || shape.markdown) {\n query = query.innerJoin({ b: rows }, ({ d, b }) => eq(d.body, b.key));\n }\n for (const { key, options } of shape.orderBy) {\n query = query.orderBy(({ d }) => keyed(key, d), options);\n }\n if (shape.orderBy.length === 0 && plan.limit !== null) {\n query = query.orderBy(({ d }) => d.key, { stringSort: 'lexical' });\n }\n if (plan.limit !== null) query = query.limit(plan.limit);\n return query.select(({ d, b }) => ({\n room: d.room,\n path: d.path,\n type: d.type,\n ...(shape.fields === 'all' ? { fields: d.fields } : {}),\n ...(Array.isArray(shape.fields) ? named('field', shape.fields, d.fields) : {}),\n ...(shape.sections === 'all' ? { sections: b.sections } : {}),\n ...(Array.isArray(shape.sections) ? named('section', shape.sections, b.sections) : {}),\n ...(shape.preamble ? { preamble: b.preamble } : {}),\n ...(shape.markdown ? { markdown: b.markdown } : {}),\n ...(shape.backlinks ? { backlinks: toArray(backlinked(q, rows, d)) } : {}),\n }));\n}\n\nfunction backlinked(q: InitialQueryBuilder, rows: Collection<Stored, string>, document: Reference) {\n const from: Builder = q.from({ r: rows });\n return from\n .where(({ r }) => eq(r.target, document.key))\n .orderBy(({ r }) => r.path, { stringSort: 'lexical' })\n .orderBy(({ r }) => r.field, { stringSort: 'lexical' })\n .select(({ r }) => ({ path: r.path, type: r.type, field: r.field })) as QueryBuilder<Context>;\n}\n\nfunction groups(q: InitialQueryBuilder, stage: Live, shape: GroupShape, limit: number | null) {\n const keys = shape.groupBy.map((_, index) => `key${index}`);\n const from: Builder = q.from({ m: stage });\n let query = from.groupBy(({ m }) => keys.map((key) => m[key]));\n for (const { by, direction } of shape.orderBy) {\n query = query.orderBy(({ m }) => (by === 'count' ? count(m.key) : m[keys[by]]), direction);\n }\n if (limit !== null && shape.orderBy.length > 0) query = query.limit(limit);\n return query.select(({ m }) => ({\n ...Object.fromEntries(keys.map((key) => [key, m[key]])),\n count: count(m.key),\n }));\n}\n\nfunction built(rows: Collection<Stored, string>, plan: Plan): Built {\n const shape = plan.shape;\n if (shape.kind === 'documents') {\n const collection = live((q) => documents(q, rows, plan, shape));\n return { live: collection, dispose: () => void collection.cleanup() };\n }\n const stage = live((q) =>\n filtered(q, rows, plan).select(({ d }) => ({\n key: d.key,\n ...Object.fromEntries(shape.groupBy.map((key, index) => [`key${index}`, keyed(key, d)])),\n })),\n );\n const collection = live((q) => groups(q, stage, shape, plan.limit));\n return {\n live: collection,\n dispose: () => {\n void collection.cleanup();\n void stage.cleanup();\n },\n };\n}\n\nfunction present(entries: readonly (readonly [string, unknown])[]) {\n return Object.fromEntries(entries.filter(([, value]) => value !== undefined));\n}\n\nfunction part(\n row: Readonly<Record<string, unknown>>,\n prefix: string,\n names: 'all' | readonly string[],\n whole: unknown,\n) {\n if (names === 'all') return whole;\n return present(names.map((name, index) => [name, row[`${prefix}${index}`]] as const));\n}\n\nfunction documentOf(row: Readonly<Record<string, unknown>>, shape: DocumentShape): QueryDocument {\n return {\n room: row.room as string,\n path: row.path as string,\n type: row.type as string,\n ...(shape.fields === null\n ? {}\n : { fields: part(row, 'field', shape.fields, row.fields) as QueryDocument['fields'] }),\n ...(shape.sections === null\n ? {}\n : {\n sections: part(row, 'section', shape.sections, row.sections) as QueryDocument['sections'],\n }),\n ...(shape.preamble ? { preamble: row.preamble as string } : {}),\n ...(shape.markdown ? { markdown: row.markdown as string } : {}),\n ...(shape.backlinks\n ? {\n backlinks: (row.backlinks as readonly Readonly<Record<string, string>>[]).map(\n ({ path, type, field }) => ({ path, type, field }),\n ),\n }\n : {}),\n };\n}\n\nfunction resultOf(plan: Plan, rows: readonly Readonly<Record<string, unknown>>[]): QueryResult {\n const shape = plan.shape;\n if (shape.kind === 'documents') {\n return structuredClone({ documents: rows.map((row) => documentOf(row, shape)) });\n }\n const bounded =\n shape.orderBy.length === 0 && plan.limit !== null ? rows.slice(0, plan.limit) : rows;\n return structuredClone({\n groups: bounded.map((row) => ({\n key: shape.groupBy.map((_, index) => row[`key${index}`]),\n count: row.count as number,\n })),\n });\n}\n\nexport function createReadSide(): ReadSide {\n configureIndexDevMode({ enabled: false });\n let sync!: Parameters<SyncConfig<Stored, string>['sync']>[0];\n const rows = createCollection<Stored, string>({\n getKey: (row) => row.key,\n gcTime: 0,\n startSync: true,\n autoIndex: 'eager',\n defaultIndexType: BasicIndex,\n sync: {\n rowUpdateMode: 'full',\n sync: (params) => {\n sync = params;\n params.markReady();\n },\n },\n });\n const shared = new Map<string, Shared>();\n\n function searched(row: Stored): SearchedDocument {\n const body = rows.get(row.body) as Stored;\n return {\n room: row.room,\n path: row.path,\n type: row.type,\n fields: row.fields,\n preamble: body.preamble,\n sections: body.sections,\n };\n }\n\n function publish(entry: Shared) {\n const next = resultOf(entry.plan, entry.built.live.toArray);\n if (deepEquals(entry.result, next)) return;\n entry.result = next;\n for (const listener of entry.listeners) listener(next);\n }\n\n return {\n apply(set) {\n const next = new Map<string, Row | null>();\n for (const change of set.documents) {\n for (const row of change.before) next.set(row.key, null);\n for (const row of change.after) next.set(row.key, row);\n }\n if (next.size === 0) return;\n sync.begin();\n for (const [key, row] of next) {\n if (row === null) {\n if (rows.has(key)) sync.write({ type: 'delete', key });\n continue;\n }\n sync.write({ type: rows.has(key) ? 'update' : 'insert', value: row as Stored });\n }\n sync.commit();\n },\n async query(plan) {\n const { live: collection, dispose } = built(rows, plan);\n try {\n return resultOf(plan, await collection.toArrayWhenReady());\n } finally {\n dispose();\n }\n },\n observe(plan, identity, listener) {\n let entry = shared.get(identity);\n if (entry === undefined) {\n const created: Shared = {\n plan,\n built: built(rows, plan),\n result: undefined,\n listeners: new Set(),\n subscription: null,\n };\n created.built.live.on('status:change', ({ status }) => {\n if (status === 'cleaned-up' && created.listeners.size === 0) shared.delete(identity);\n });\n shared.set(identity, created);\n entry = created;\n }\n const observed = entry;\n observed.listeners.add(listener);\n observed.built.live.onFirstReady(() => {\n if (!observed.listeners.has(listener)) return;\n if (observed.subscription === null) {\n observed.result = resultOf(observed.plan, observed.built.live.toArray);\n observed.subscription = observed.built.live.subscribeChanges(() => {\n publish(observed);\n });\n }\n listener(observed.result as QueryResult);\n });\n return () => {\n if (!observed.listeners.delete(listener) || observed.listeners.size > 0) return;\n observed.subscription?.unsubscribe();\n observed.subscription = null;\n };\n },\n documents() {\n return rows.toArray.filter((row) => row.kind === 'document').map(searched);\n },\n document(room, path) {\n const row = rows.get(documentKey(room, path));\n return row === undefined ? null : searched(row);\n },\n close() {\n for (const entry of shared.values()) {\n entry.listeners.clear();\n entry.subscription?.unsubscribe();\n entry.built.dispose();\n }\n shared.clear();\n void rows.cleanup();\n },\n };\n}\n"],"names":["and","BasicIndex","configureIndexDevMode","count","createCollection","createLiveQueryCollection","deepEquals","eq","gt","gte","inArray","isNull","isUndefined","lt","lte","not","or","toArray","documentKey","every","expressions","first","second","rest","undefined","some","equal","field","value","tested","test","size","written","op","matches","values","length","map","includes","compare","bounds","operator","bound","exists","conditioned","condition","row","item","sizes","fields","scoped","scope","rooms","kind","room","types","type","pathPrefix","directories","where","keyed","key","of","live","query","startSync","related","q","rows","kept","matched","from","r","innerJoin","m","groupBy","select","filtered","plan","d","root","hop","h","backlinks","k","named","prefix","names","source","Object","fromEntries","name","index","documents","shape","sections","preamble","markdown","b","body","options","orderBy","limit","stringSort","path","Array","isArray","backlinked","document","target","groups","stage","keys","_","by","direction","built","collection","dispose","cleanup","present","entries","filter","part","whole","documentOf","resultOf","structuredClone","bounded","slice","createReadSide","enabled","sync","getKey","gcTime","autoIndex","defaultIndexType","rowUpdateMode","params","markReady","shared","Map","searched","get","publish","entry","next","result","listener","listeners","apply","set","change","before","after","begin","has","write","commit","toArrayWhenReady","observe","identity","created","Set","subscription","on","status","delete","observed","add","onFirstReady","subscribeChanges","unsubscribe","close","clear"],"mappings":"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"}
package/dist/rows.d.ts ADDED
@@ -0,0 +1,39 @@
1
+ import type { Document } from '@agentshouse/mdmodel';
2
+ import { type Composition } from './collection.js';
3
+ type Fields = Readonly<Record<string, unknown>>;
4
+ export type DocumentRow = {
5
+ key: string;
6
+ kind: 'document';
7
+ room: string;
8
+ path: string;
9
+ type: string;
10
+ fields: Fields;
11
+ values: Fields;
12
+ sizes: Readonly<Record<string, number>>;
13
+ directories: readonly string[];
14
+ body: string;
15
+ };
16
+ export type BodyRow = {
17
+ key: string;
18
+ kind: 'body';
19
+ room: string;
20
+ path: string;
21
+ preamble: string;
22
+ sections: Readonly<Record<string, string>>;
23
+ markdown: string;
24
+ };
25
+ export type ReferenceRow = {
26
+ key: string;
27
+ kind: 'reference';
28
+ room: string;
29
+ source: string;
30
+ target: string;
31
+ field: string;
32
+ path: string;
33
+ type: string;
34
+ };
35
+ export type Row = DocumentRow | BodyRow | ReferenceRow;
36
+ export declare function documentKey(room: string, path: string): string;
37
+ export declare function rowsOf(room: string, path: string, document: Document, composition: Composition): readonly Row[];
38
+ export {};
39
+ //# sourceMappingURL=rows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rows.d.ts","sourceRoot":"","sources":["../src/rows.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAa,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAI9D,KAAK,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEhD,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACxC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,GAAG,GAAG,WAAW,GAAG,OAAO,GAAG,YAAY,CAAC;AAMvD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9D;AAqBD,wBAAgB,MAAM,CACpB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,WAAW,GACvB,SAAS,GAAG,EAAE,CAqDhB"}
package/dist/rows.js ADDED
@@ -0,0 +1,85 @@
1
+ import { governing } from './collection.js';
2
+ import { definitionOf } from './model.js';
3
+ import { target } from './paths.js';
4
+ function keyOf(...parts) {
5
+ return `${parts.join('\u0000')}\u0000`;
6
+ }
7
+ export function documentKey(room, path) {
8
+ return keyOf('d', room, path);
9
+ }
10
+ function referenceField(spec) {
11
+ return spec?.kind === 'reference' || spec?.kind === 'list' && spec.of.kind === 'reference';
12
+ }
13
+ function targetOf(path, value) {
14
+ return typeof value === 'string' ? target(path, value) : null;
15
+ }
16
+ function resolved(path, value) {
17
+ if (value === null) return null;
18
+ if (!Array.isArray(value)) return targetOf(path, value) ?? undefined;
19
+ return value.map((item)=>targetOf(path, item)).filter((item)=>item !== null);
20
+ }
21
+ function directoriesOf(path) {
22
+ const parts = path.split('/').slice(0, -1);
23
+ return [
24
+ '',
25
+ ...parts.map((_, index)=>parts.slice(0, index + 1).join('/'))
26
+ ];
27
+ }
28
+ export function rowsOf(room, path, document, composition) {
29
+ if (!path.endsWith('.md')) return [];
30
+ const type = document.type ?? 'any';
31
+ const definition = definitionOf(governing(composition, path), document.type);
32
+ const key = documentKey(room, path);
33
+ const values = {};
34
+ const sizes = {};
35
+ const references = [];
36
+ for (const [name, value] of Object.entries(document.fields)){
37
+ const reference = referenceField(definition?.fields[name]);
38
+ const compared = reference ? resolved(path, value) : value;
39
+ if (compared !== undefined) values[name] = compared;
40
+ if (Array.isArray(value)) sizes[name] = value.length;
41
+ if (!reference) continue;
42
+ const targets = [
43
+ compared
44
+ ].flat().filter((found)=>typeof found === 'string');
45
+ for (const found of new Set(targets)){
46
+ references.push({
47
+ key: keyOf('r', room, path, name, found),
48
+ kind: 'reference',
49
+ room,
50
+ source: key,
51
+ target: documentKey(room, found),
52
+ field: name,
53
+ path,
54
+ type
55
+ });
56
+ }
57
+ }
58
+ const body = keyOf('b', room, path);
59
+ return [
60
+ {
61
+ key,
62
+ kind: 'document',
63
+ room,
64
+ path,
65
+ type,
66
+ fields: document.fields,
67
+ values,
68
+ sizes,
69
+ directories: directoriesOf(path),
70
+ body
71
+ },
72
+ {
73
+ key: body,
74
+ kind: 'body',
75
+ room,
76
+ path,
77
+ preamble: document.preamble,
78
+ sections: document.sections,
79
+ markdown: document.content
80
+ },
81
+ ...references
82
+ ];
83
+ }
84
+
85
+ //# sourceMappingURL=rows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/workspace/packages/mdruntime/src/rows.ts"],"sourcesContent":["import type { Document, FieldSpec } from '@agentshouse/mdmodel';\nimport { governing, type Composition } from './collection.js';\nimport { definitionOf } from './model.js';\nimport { target } from './paths.js';\n\ntype Fields = Readonly<Record<string, unknown>>;\n\nexport type DocumentRow = {\n key: string;\n kind: 'document';\n room: string;\n path: string;\n type: string;\n fields: Fields;\n values: Fields;\n sizes: Readonly<Record<string, number>>;\n directories: readonly string[];\n body: string;\n};\n\nexport type BodyRow = {\n key: string;\n kind: 'body';\n room: string;\n path: string;\n preamble: string;\n sections: Readonly<Record<string, string>>;\n markdown: string;\n};\n\nexport type ReferenceRow = {\n key: string;\n kind: 'reference';\n room: string;\n source: string;\n target: string;\n field: string;\n path: string;\n type: string;\n};\n\nexport type Row = DocumentRow | BodyRow | ReferenceRow;\n\nfunction keyOf(...parts: readonly string[]): string {\n return `${parts.join('\\u0000')}\\u0000`;\n}\n\nexport function documentKey(room: string, path: string): string {\n return keyOf('d', room, path);\n}\n\nfunction referenceField(spec: FieldSpec | undefined): boolean {\n return spec?.kind === 'reference' || (spec?.kind === 'list' && spec.of.kind === 'reference');\n}\n\nfunction targetOf(path: string, value: unknown): string | null {\n return typeof value === 'string' ? target(path, value) : null;\n}\n\nfunction resolved(path: string, value: unknown): unknown {\n if (value === null) return null;\n if (!Array.isArray(value)) return targetOf(path, value) ?? undefined;\n return value.map((item) => targetOf(path, item)).filter((item) => item !== null);\n}\n\nfunction directoriesOf(path: string): readonly string[] {\n const parts = path.split('/').slice(0, -1);\n return ['', ...parts.map((_, index) => parts.slice(0, index + 1).join('/'))];\n}\n\nexport function rowsOf(\n room: string,\n path: string,\n document: Document,\n composition: Composition,\n): readonly Row[] {\n if (!path.endsWith('.md')) return [];\n const type = document.type ?? 'any';\n const definition = definitionOf(governing(composition, path), document.type);\n const key = documentKey(room, path);\n const values: Record<string, unknown> = {};\n const sizes: Record<string, number> = {};\n const references: ReferenceRow[] = [];\n for (const [name, value] of Object.entries(document.fields)) {\n const reference = referenceField(definition?.fields[name]);\n const compared = reference ? resolved(path, value) : value;\n if (compared !== undefined) values[name] = compared;\n if (Array.isArray(value)) sizes[name] = value.length;\n if (!reference) continue;\n const targets = [compared].flat().filter((found) => typeof found === 'string');\n for (const found of new Set(targets)) {\n references.push({\n key: keyOf('r', room, path, name, found),\n kind: 'reference',\n room,\n source: key,\n target: documentKey(room, found),\n field: name,\n path,\n type,\n });\n }\n }\n const body = keyOf('b', room, path);\n return [\n {\n key,\n kind: 'document',\n room,\n path,\n type,\n fields: document.fields,\n values,\n sizes,\n directories: directoriesOf(path),\n body,\n },\n {\n key: body,\n kind: 'body',\n room,\n path,\n preamble: document.preamble,\n sections: document.sections,\n markdown: document.content,\n },\n ...references,\n ];\n}\n"],"names":["governing","definitionOf","target","keyOf","parts","join","documentKey","room","path","referenceField","spec","kind","of","targetOf","value","resolved","Array","isArray","undefined","map","item","filter","directoriesOf","split","slice","_","index","rowsOf","document","composition","endsWith","type","definition","key","values","sizes","references","name","Object","entries","fields","reference","compared","length","targets","flat","found","Set","push","source","field","body","directories","preamble","sections","markdown","content"],"mappings":"AACA,SAASA,SAAS,QAA0B,kBAAkB;AAC9D,SAASC,YAAY,QAAQ,aAAa;AAC1C,SAASC,MAAM,QAAQ,aAAa;AAwCpC,SAASC,MAAM,GAAGC,KAAwB;IACxC,OAAO,GAAGA,MAAMC,IAAI,CAAC,UAAU,MAAM,CAAC;AACxC;AAEA,OAAO,SAASC,YAAYC,IAAY,EAAEC,IAAY;IACpD,OAAOL,MAAM,KAAKI,MAAMC;AAC1B;AAEA,SAASC,eAAeC,IAA2B;IACjD,OAAOA,MAAMC,SAAS,eAAgBD,MAAMC,SAAS,UAAUD,KAAKE,EAAE,CAACD,IAAI,KAAK;AAClF;AAEA,SAASE,SAASL,IAAY,EAAEM,KAAc;IAC5C,OAAO,OAAOA,UAAU,WAAWZ,OAAOM,MAAMM,SAAS;AAC3D;AAEA,SAASC,SAASP,IAAY,EAAEM,KAAc;IAC5C,IAAIA,UAAU,MAAM,OAAO;IAC3B,IAAI,CAACE,MAAMC,OAAO,CAACH,QAAQ,OAAOD,SAASL,MAAMM,UAAUI;IAC3D,OAAOJ,MAAMK,GAAG,CAAC,CAACC,OAASP,SAASL,MAAMY,OAAOC,MAAM,CAAC,CAACD,OAASA,SAAS;AAC7E;AAEA,SAASE,cAAcd,IAAY;IACjC,MAAMJ,QAAQI,KAAKe,KAAK,CAAC,KAAKC,KAAK,CAAC,GAAG,CAAC;IACxC,OAAO;QAAC;WAAOpB,MAAMe,GAAG,CAAC,CAACM,GAAGC,QAAUtB,MAAMoB,KAAK,CAAC,GAAGE,QAAQ,GAAGrB,IAAI,CAAC;KAAM;AAC9E;AAEA,OAAO,SAASsB,OACdpB,IAAY,EACZC,IAAY,EACZoB,QAAkB,EAClBC,WAAwB;IAExB,IAAI,CAACrB,KAAKsB,QAAQ,CAAC,QAAQ,OAAO,EAAE;IACpC,MAAMC,OAAOH,SAASG,IAAI,IAAI;IAC9B,MAAMC,aAAa/B,aAAaD,UAAU6B,aAAarB,OAAOoB,SAASG,IAAI;IAC3E,MAAME,MAAM3B,YAAYC,MAAMC;IAC9B,MAAM0B,SAAkC,CAAC;IACzC,MAAMC,QAAgC,CAAC;IACvC,MAAMC,aAA6B,EAAE;IACrC,KAAK,MAAM,CAACC,MAAMvB,MAAM,IAAIwB,OAAOC,OAAO,CAACX,SAASY,MAAM,EAAG;QAC3D,MAAMC,YAAYhC,eAAeuB,YAAYQ,MAAM,CAACH,KAAK;QACzD,MAAMK,WAAWD,YAAY1B,SAASP,MAAMM,SAASA;QACrD,IAAI4B,aAAaxB,WAAWgB,MAAM,CAACG,KAAK,GAAGK;QAC3C,IAAI1B,MAAMC,OAAO,CAACH,QAAQqB,KAAK,CAACE,KAAK,GAAGvB,MAAM6B,MAAM;QACpD,IAAI,CAACF,WAAW;QAChB,MAAMG,UAAU;YAACF;SAAS,CAACG,IAAI,GAAGxB,MAAM,CAAC,CAACyB,QAAU,OAAOA,UAAU;QACrE,KAAK,MAAMA,SAAS,IAAIC,IAAIH,SAAU;YACpCR,WAAWY,IAAI,CAAC;gBACdf,KAAK9B,MAAM,KAAKI,MAAMC,MAAM6B,MAAMS;gBAClCnC,MAAM;gBACNJ;gBACA0C,QAAQhB;gBACR/B,QAAQI,YAAYC,MAAMuC;gBAC1BI,OAAOb;gBACP7B;gBACAuB;YACF;QACF;IACF;IACA,MAAMoB,OAAOhD,MAAM,KAAKI,MAAMC;IAC9B,OAAO;QACL;YACEyB;YACAtB,MAAM;YACNJ;YACAC;YACAuB;YACAS,QAAQZ,SAASY,MAAM;YACvBN;YACAC;YACAiB,aAAa9B,cAAcd;YAC3B2C;QACF;QACA;YACElB,KAAKkB;YACLxC,MAAM;YACNJ;YACAC;YACA6C,UAAUzB,SAASyB,QAAQ;YAC3BC,UAAU1B,SAAS0B,QAAQ;YAC3BC,UAAU3B,SAAS4B,OAAO;QAC5B;WACGpB;KACJ;AACH"}
@@ -0,0 +1,61 @@
1
+ import type { ChangeSet } from './change-set.js';
2
+ import { type Filter } from './query.js';
3
+ export type DocumentPart = 'fields' | 'sections' | 'preamble' | 'path';
4
+ export type SearchRequest = {
5
+ text: string;
6
+ documents?: Filter;
7
+ conversations?: readonly string[];
8
+ limit?: number;
9
+ };
10
+ export type DocumentHit = {
11
+ room: string;
12
+ path: string;
13
+ type: string;
14
+ score: number;
15
+ matches: Readonly<Record<string, readonly DocumentPart[]>>;
16
+ };
17
+ export type MessageHit = {
18
+ conversation: string;
19
+ identity: string;
20
+ score: number;
21
+ matches: Readonly<Record<string, readonly 'text'[]>>;
22
+ };
23
+ export type SearchResult = {
24
+ documents: readonly DocumentHit[];
25
+ messages: readonly MessageHit[];
26
+ };
27
+ export type SearchedDocument = {
28
+ room: string;
29
+ path: string;
30
+ type: string;
31
+ fields: Readonly<Record<string, unknown>>;
32
+ preamble: string;
33
+ sections: Readonly<Record<string, string>>;
34
+ };
35
+ export type SearchedMessage = {
36
+ conversation: string;
37
+ identity: string;
38
+ text: string;
39
+ };
40
+ export type SearchSource = {
41
+ documents(): readonly SearchedDocument[];
42
+ document(room: string, path: string): SearchedDocument | null;
43
+ messages(): readonly SearchedMessage[];
44
+ message(conversation: string, identity: string): SearchedMessage | null;
45
+ };
46
+ export type SearchPlan = {
47
+ text: string;
48
+ documents: unknown;
49
+ conversations: readonly string[] | null;
50
+ limit: number | null;
51
+ };
52
+ export type SearchIndex = {
53
+ changed(set: ChangeSet): void;
54
+ search(plan: SearchPlan, documents: readonly {
55
+ room: string;
56
+ path: string;
57
+ }[] | null): SearchResult;
58
+ };
59
+ export declare function searchPlanOf(input: unknown): SearchPlan;
60
+ export declare function createSearchIndex(source: SearchSource): SearchIndex;
61
+ //# sourceMappingURL=search.d.ts.map