@agentshouse/mdruntime 0.1.0-c97456d63baba → 0.1.0-c9b1e59e5baeb
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +221 -221
- package/README.md +8 -8
- package/dist/adapter.d.ts +35 -6
- package/dist/adapter.d.ts.map +1 -1
- package/dist/bootstrap.d.ts +2 -1
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +5 -1
- package/dist/change-set.d.ts +5 -2
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +8 -2
- package/dist/chat/earlier.d.ts +10 -0
- package/dist/chat/earlier.d.ts.map +1 -0
- package/dist/chat/earlier.js +54 -0
- package/dist/chat/kit.js +1 -1
- package/dist/chat/list.d.ts +2 -1
- package/dist/chat/list.d.ts.map +1 -1
- package/dist/chat/list.js +40 -4
- package/dist/chat/markdown.d.ts +1 -0
- package/dist/chat/markdown.d.ts.map +1 -1
- package/dist/chat/markdown.js +78 -20
- package/dist/chat/message.d.ts.map +1 -1
- package/dist/chat/message.js +9 -2
- package/dist/chat/messages.d.ts.map +1 -1
- package/dist/chat/messages.js +36 -16
- package/dist/chat/overlay.d.ts +1 -0
- package/dist/chat/overlay.d.ts.map +1 -1
- package/dist/chat/overlay.js +10 -0
- package/dist/chat/pieces.d.ts +62 -0
- package/dist/chat/pieces.d.ts.map +1 -0
- package/dist/chat/pieces.js +1110 -0
- package/dist/chat/provider.d.ts +1 -0
- package/dist/chat/provider.d.ts.map +1 -1
- package/dist/chat/provider.js +22 -14
- package/dist/chat/question.d.ts +1 -1
- package/dist/chat/question.d.ts.map +1 -1
- package/dist/chat/question.js +7 -18
- package/dist/chat/ready.d.ts +1 -1
- package/dist/chat/ready.d.ts.map +1 -1
- package/dist/chat/ready.js +1 -1
- package/dist/chat/steady.d.ts +3 -0
- package/dist/chat/steady.d.ts.map +1 -0
- package/dist/chat/steady.js +26 -0
- package/dist/chat/style.js +1 -1
- package/dist/chat.d.ts +2 -2
- package/dist/chat.d.ts.map +1 -1
- package/dist/chat.js +2 -2
- package/dist/client.d.ts +6 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +16 -5
- package/dist/collection.d.ts +4 -3
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +128 -63
- package/dist/connection.d.ts +13 -5
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +506 -228
- package/dist/conversation.d.ts +11 -0
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +195 -41
- package/dist/entry.d.ts.map +1 -1
- package/dist/entry.js +3 -2
- package/dist/host.d.ts +9 -7
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +58 -9
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/memory.d.ts +7 -3
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +24 -11
- package/dist/observation.d.ts +2 -0
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +9 -3
- package/dist/outcome.d.ts +8 -2
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +3 -0
- package/dist/overlay.d.ts +5 -4
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +197 -132
- package/dist/query.d.ts +27 -1
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +36 -7
- package/dist/reach.d.ts +1 -2
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +17 -4
- package/dist/react.d.ts +3 -3
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +7 -17
- package/dist/read-side.d.ts +3 -1
- package/dist/read-side.d.ts.map +1 -1
- package/dist/read-side.js +256 -69
- package/dist/reads.d.ts +11 -0
- package/dist/reads.d.ts.map +1 -0
- package/dist/reads.js +98 -0
- package/dist/refresh.d.ts +4 -4
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +39 -14
- package/dist/replica.d.ts +11 -5
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +79 -41
- package/dist/room-draft.d.ts +12 -0
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +11 -12
- package/dist/rows.d.ts +3 -1
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +8 -1
- package/dist/save.d.ts +4 -2
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +195 -111
- package/dist/search.d.ts +27 -6
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +89 -7
- package/dist/seed.d.ts +16 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +75 -0
- package/dist/shared.d.ts +4 -0
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +63 -33
- package/dist/store.d.ts +20 -4
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +404 -317
- package/dist/turn.d.ts +5 -3
- package/dist/turn.d.ts.map +1 -1
- package/dist/turn.js +26 -7
- package/dist/windows.d.ts +26 -0
- package/dist/windows.d.ts.map +1 -0
- package/dist/windows.js +93 -0
- package/dist/wire.d.ts +16 -0
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +4 -0
- package/package.json +2 -2
- package/dist/acquisition.d.ts +0 -14
- package/dist/acquisition.d.ts.map +0 -1
- package/dist/acquisition.js +0 -24
package/dist/read-side.js
CHANGED
|
@@ -2,6 +2,7 @@ import { and, BasicIndex, configureIndexDevMode, count, createCollection, create
|
|
|
2
2
|
import { ARRAY_INDEX, parse, pointerSegments } from '@agentshouse/mdmodel';
|
|
3
3
|
import { documentKey } from './rows.js';
|
|
4
4
|
import { after, inUnits, ROW_WEIGHT } from './turn.js';
|
|
5
|
+
import { beyond, cursorOf, MAXIMUM_WINDOW, windowed } from './windows.js';
|
|
5
6
|
function every(expressions) {
|
|
6
7
|
const [first, second, ...rest] = expressions;
|
|
7
8
|
return second === undefined ? first : and(first, second, ...rest);
|
|
@@ -59,10 +60,12 @@ function reached(reach, room, document) {
|
|
|
59
60
|
? []
|
|
60
61
|
: [or(inArray(room, [...reach.rooms]), inArray(document, [...reach.documents]))];
|
|
61
62
|
}
|
|
62
|
-
function scoped(scope, row, rooms, reach) {
|
|
63
|
+
function scoped(scope, row, rooms, reach, paths = null, folder = null) {
|
|
63
64
|
return every([
|
|
64
65
|
eq(row.kind, 'document'),
|
|
65
66
|
...(rooms === null ? [] : [inArray(row.room, [...rooms])]),
|
|
67
|
+
...(paths === null ? [] : [inArray(row.path, [...paths])]),
|
|
68
|
+
...(folder === null ? [] : [eq(row.folder, folder)]),
|
|
66
69
|
...reached(reach, row.room, row.key),
|
|
67
70
|
...(scope.types === null ? [] : [inArray(row.type, [...scope.types])]),
|
|
68
71
|
...(scope.pathPrefix === null ? [] : [inArray(scope.pathPrefix, row.directories)]),
|
|
@@ -90,7 +93,7 @@ function related(q, rows, scope, field, kept, reach) {
|
|
|
90
93
|
}
|
|
91
94
|
function filtered(q, rows, plan) {
|
|
92
95
|
const from = q.from({ d: rows });
|
|
93
|
-
let query = narrowed(from.where(({ d }) => scoped(plan.root, d, plan.rooms, plan.reach)), plan.root.where, 'd');
|
|
96
|
+
let query = narrowed(from.where(({ d }) => scoped(plan.root, d, plan.rooms, plan.reach, plan.paths, plan.folder)), plan.root.where, 'd');
|
|
94
97
|
if (plan.hop !== null) {
|
|
95
98
|
const hop = related(q, rows, plan.hop, plan.hop.field, 'source', plan.reach);
|
|
96
99
|
query = query.innerJoin({ h: hop }, ({ d, h }) => eq(d.key, h.key));
|
|
@@ -104,25 +107,56 @@ function filtered(q, rows, plan) {
|
|
|
104
107
|
function bodied(shape) {
|
|
105
108
|
return shape.sections !== null || shape.preamble || shape.markdown;
|
|
106
109
|
}
|
|
110
|
+
function orderingOf(options) {
|
|
111
|
+
const collated = options.stringSort === 'locale';
|
|
112
|
+
return {
|
|
113
|
+
direction: options.direction,
|
|
114
|
+
nulls: options.nulls ?? 'first',
|
|
115
|
+
stringSort: options.stringSort ?? 'locale',
|
|
116
|
+
locale: collated ? options.locale : undefined,
|
|
117
|
+
localeOptions: collated
|
|
118
|
+
? options.localeOptions
|
|
119
|
+
: undefined,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function storedValue(key, row) {
|
|
123
|
+
return key.of === 'field' ? row.values[key.field] : row[key.of];
|
|
124
|
+
}
|
|
125
|
+
function documentOrder(shape) {
|
|
126
|
+
return shape.orderBy.map(({ options }) => orderingOf(options));
|
|
127
|
+
}
|
|
128
|
+
function documentCursor(shape, row) {
|
|
129
|
+
return cursorOf([
|
|
130
|
+
...shape.orderBy.map((_, index) => row[`order${index}`]),
|
|
131
|
+
documentKey(row.room, row.path),
|
|
132
|
+
]);
|
|
133
|
+
}
|
|
107
134
|
function documents(q, rows, plan, shape) {
|
|
108
135
|
let query = filtered(q, rows, plan);
|
|
136
|
+
const cursor = plan.after?.values ?? null;
|
|
137
|
+
if (cursor !== null) {
|
|
138
|
+
const orderings = documentOrder(shape);
|
|
139
|
+
query = query.fn.where(({ d }) => beyond([...shape.orderBy.map(({ key }) => storedValue(key, d)), d.key], cursor, orderings));
|
|
140
|
+
}
|
|
109
141
|
for (const { key, options } of shape.orderBy) {
|
|
110
142
|
query = query.orderBy(({ d }) => keyed(key, d), options);
|
|
111
143
|
}
|
|
112
|
-
if (shape.orderBy.length
|
|
144
|
+
if (shape.orderBy.length > 0 || plan.limit !== null || plan.after !== null) {
|
|
113
145
|
query = query.orderBy(({ d }) => d.key, { stringSort: 'lexical' });
|
|
114
146
|
}
|
|
115
147
|
if (plan.limit !== null)
|
|
116
|
-
query = query.limit(plan.limit);
|
|
148
|
+
query = query.limit(plan.limit + 1);
|
|
117
149
|
return query.select(({ d }) => ({
|
|
118
150
|
room: d.room,
|
|
119
151
|
path: d.path,
|
|
120
152
|
type: d.type,
|
|
121
153
|
binary: d.binary,
|
|
154
|
+
...Object.fromEntries(shape.orderBy.map(({ key }, index) => [`order${index}`, keyed(key, d)])),
|
|
122
155
|
...(shape.fields === null ? {} : { fields: d.fields }),
|
|
123
156
|
...(bodied(shape) ? { text: d.text } : {}),
|
|
124
157
|
...(shape.backlinks ? { backlinks: toArray(backlinked(q, rows, d, plan.reach)) } : {}),
|
|
125
158
|
...(shape.change ? { change: d.change } : {}),
|
|
159
|
+
...(shape.fileId ? { fileId: d.fileId } : {}),
|
|
126
160
|
}));
|
|
127
161
|
}
|
|
128
162
|
function backlinked(q, rows, document, reach) {
|
|
@@ -133,15 +167,13 @@ function backlinked(q, rows, document, reach) {
|
|
|
133
167
|
.orderBy(({ r }) => r.field, { stringSort: 'lexical' })
|
|
134
168
|
.select(({ r }) => ({ path: r.path, type: r.type, field: r.field }));
|
|
135
169
|
}
|
|
136
|
-
function groups(q, stage, shape
|
|
170
|
+
function groups(q, stage, shape) {
|
|
137
171
|
const keys = shape.groupBy.map((_, index) => `key${index}`);
|
|
138
172
|
const from = q.from({ m: stage });
|
|
139
173
|
let query = from.groupBy(({ m }) => keys.map((key) => m[key]));
|
|
140
174
|
for (const { by, direction } of shape.orderBy) {
|
|
141
175
|
query = query.orderBy(({ m }) => (by === 'count' ? count(m.key) : m[keys[by]]), direction);
|
|
142
176
|
}
|
|
143
|
-
if (limit !== null && shape.orderBy.length > 0)
|
|
144
|
-
query = query.limit(limit);
|
|
145
177
|
return query.select(({ m }) => ({
|
|
146
178
|
...Object.fromEntries(keys.map((key) => [key, m[key]])),
|
|
147
179
|
count: count(m.key),
|
|
@@ -151,15 +183,27 @@ function built(rows, plan) {
|
|
|
151
183
|
const shape = plan.shape;
|
|
152
184
|
if (shape.kind === 'documents') {
|
|
153
185
|
const collection = live((q) => documents(q, rows, plan, shape));
|
|
154
|
-
|
|
186
|
+
const count = plan.total
|
|
187
|
+
? live((q) => filtered(q, rows, plan).select(({ d }) => ({ key: d.key })))
|
|
188
|
+
: null;
|
|
189
|
+
return {
|
|
190
|
+
live: collection,
|
|
191
|
+
count,
|
|
192
|
+
dispose: () => {
|
|
193
|
+
void collection.cleanup();
|
|
194
|
+
if (count !== null)
|
|
195
|
+
void count.cleanup();
|
|
196
|
+
},
|
|
197
|
+
};
|
|
155
198
|
}
|
|
156
199
|
const stage = live((q) => filtered(q, rows, plan).select(({ d }) => ({
|
|
157
200
|
key: d.key,
|
|
158
201
|
...Object.fromEntries(shape.groupBy.map((key, index) => [`key${index}`, keyed(key, d)])),
|
|
159
202
|
})));
|
|
160
|
-
const collection = live((q) => groups(q, stage, shape
|
|
203
|
+
const collection = live((q) => groups(q, stage, shape));
|
|
161
204
|
return {
|
|
162
205
|
live: collection,
|
|
206
|
+
count: null,
|
|
163
207
|
dispose: () => {
|
|
164
208
|
void collection.cleanup();
|
|
165
209
|
void stage.cleanup();
|
|
@@ -239,6 +283,7 @@ function documentOf(key, row, shape, bodies) {
|
|
|
239
283
|
room: row.room,
|
|
240
284
|
path: row.path,
|
|
241
285
|
...(binary === null ? {} : { binaryFile: binary }),
|
|
286
|
+
...(shape.fileId ? { fileId: row.fileId } : {}),
|
|
242
287
|
};
|
|
243
288
|
}
|
|
244
289
|
const body = bodied(shape) ? bodyOf(row, key, bodies) : null;
|
|
@@ -260,33 +305,75 @@ function documentOf(key, row, shape, bodies) {
|
|
|
260
305
|
...(shape.markdown && body !== null ? { markdown: body.content } : {}),
|
|
261
306
|
...(shape.backlinks
|
|
262
307
|
? {
|
|
263
|
-
backlinks: row.backlinks
|
|
308
|
+
backlinks: row.backlinks
|
|
309
|
+
.slice(0, MAXIMUM_WINDOW)
|
|
310
|
+
.map(({ path, type, field }) => ({ path, type, field })),
|
|
264
311
|
}
|
|
265
312
|
: {}),
|
|
266
313
|
...(shape.change ? { change: row.change } : {}),
|
|
314
|
+
...(shape.fileId ? { fileId: row.fileId } : {}),
|
|
267
315
|
};
|
|
268
316
|
}
|
|
269
317
|
function weight(row) {
|
|
270
318
|
return ROW_WEIGHT + (typeof row?.text === 'string' ? row.text.length : 0);
|
|
271
319
|
}
|
|
272
|
-
|
|
320
|
+
const HELD_PER_WEIGHT = 16;
|
|
321
|
+
function groupValues(shape, [key, row]) {
|
|
322
|
+
return [...shape.orderBy.map(({ by }) => (by === 'count' ? row.count : row[`key${by}`])), key];
|
|
323
|
+
}
|
|
324
|
+
function groupOrder(shape) {
|
|
325
|
+
return shape.orderBy.map(({ direction }) => ({
|
|
326
|
+
direction,
|
|
327
|
+
nulls: 'first',
|
|
328
|
+
stringSort: 'locale',
|
|
329
|
+
locale: undefined,
|
|
330
|
+
localeOptions: undefined,
|
|
331
|
+
}));
|
|
332
|
+
}
|
|
333
|
+
function windowOf(plan, entries, total) {
|
|
273
334
|
const shape = plan.shape;
|
|
335
|
+
if (shape.kind === 'documents') {
|
|
336
|
+
return {
|
|
337
|
+
...windowed(entries, plan.limit, plan.after?.text, ([, row]) => documentCursor(shape, row)),
|
|
338
|
+
total,
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
const cursor = plan.after?.values ?? null;
|
|
342
|
+
const orderings = groupOrder(shape);
|
|
343
|
+
const following = cursor === null
|
|
344
|
+
? entries
|
|
345
|
+
: entries.filter((entry) => beyond(groupValues(shape, entry), cursor, orderings));
|
|
346
|
+
return {
|
|
347
|
+
...windowed(following, plan.limit, plan.after?.text, (entry) => cursorOf(groupValues(shape, entry))),
|
|
348
|
+
total: plan.total ? entries.length : undefined,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
function framed(rows, { next, total }) {
|
|
352
|
+
return {
|
|
353
|
+
...rows,
|
|
354
|
+
...(next === undefined ? {} : { next }),
|
|
355
|
+
...(total === undefined ? {} : { total }),
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
function rowsOfPlan(plan, entries, total, bodies, each = (row) => row) {
|
|
359
|
+
const shape = plan.shape;
|
|
360
|
+
const { kept, ...window } = windowOf(plan, entries, total);
|
|
361
|
+
const keys = kept.map(([key]) => key);
|
|
274
362
|
if (shape.kind === 'documents') {
|
|
275
363
|
const documents = [];
|
|
276
|
-
return after(inUnits(
|
|
364
|
+
return after(inUnits(kept, ([key, row]) => {
|
|
277
365
|
documents.push(each(documentOf(key, row, shape, bodies)));
|
|
278
366
|
return weight(row);
|
|
279
|
-
}), () => ({ rows: { documents },
|
|
367
|
+
}), () => ({ rows: framed({ documents }, window), keys, ...window }));
|
|
280
368
|
}
|
|
281
|
-
const bounded = shape.orderBy.length === 0 && plan.limit !== null ? entries.slice(0, plan.limit) : entries;
|
|
282
369
|
const groups = [];
|
|
283
|
-
return after(inUnits(
|
|
370
|
+
return after(inUnits(kept, ([, row]) => {
|
|
284
371
|
groups.push(each({
|
|
285
372
|
key: shape.groupBy.map((_, index) => row[`key${index}`]),
|
|
286
373
|
count: row.count,
|
|
287
374
|
}));
|
|
288
375
|
return ROW_WEIGHT;
|
|
289
|
-
}), () => ({ rows: { groups },
|
|
376
|
+
}), () => ({ rows: framed({ groups }, window), keys, ...window }));
|
|
290
377
|
}
|
|
291
378
|
export function reconciled(previous, next) {
|
|
292
379
|
const before = previous.result;
|
|
@@ -311,13 +398,16 @@ export function reconciled(previous, next) {
|
|
|
311
398
|
const removed = previous.keys.filter((key) => !present.has(key));
|
|
312
399
|
const moved = reordered(previous.keys, next.keys, present);
|
|
313
400
|
const covered = !deepEquals(before.coverage, after.coverage);
|
|
314
|
-
|
|
401
|
+
const framing = reframed(before, after);
|
|
402
|
+
if (changed.length === 0 && removed.length === 0 && !moved && !covered && framing === null) {
|
|
315
403
|
return null;
|
|
404
|
+
}
|
|
405
|
+
const window = { next: after.next, total: after.total };
|
|
316
406
|
return {
|
|
317
407
|
keyed: {
|
|
318
408
|
result: 'groups' in after
|
|
319
|
-
? { groups: rows, coverage: after.coverage }
|
|
320
|
-
: { documents: rows, coverage: after.coverage },
|
|
409
|
+
? framed({ groups: rows, coverage: after.coverage }, window)
|
|
410
|
+
: framed({ documents: rows, coverage: after.coverage }, window),
|
|
321
411
|
keys: next.keys,
|
|
322
412
|
},
|
|
323
413
|
message: {
|
|
@@ -325,9 +415,17 @@ export function reconciled(previous, next) {
|
|
|
325
415
|
removed,
|
|
326
416
|
order: moved ? next.keys : null,
|
|
327
417
|
...(covered ? { coverage: after.coverage } : {}),
|
|
418
|
+
...framing,
|
|
328
419
|
},
|
|
329
420
|
};
|
|
330
421
|
}
|
|
422
|
+
function reframed(before, after) {
|
|
423
|
+
const next = before.next === after.next ? {} : { next: after.next ?? null };
|
|
424
|
+
const total = before.total === after.total || after.total === undefined ? {} : { total: after.total };
|
|
425
|
+
return Object.keys(next).length === 0 && Object.keys(total).length === 0
|
|
426
|
+
? null
|
|
427
|
+
: { ...next, ...total };
|
|
428
|
+
}
|
|
331
429
|
function reordered(previous, next, present) {
|
|
332
430
|
let at = 0;
|
|
333
431
|
for (const key of previous) {
|
|
@@ -357,6 +455,9 @@ export function createReadSide() {
|
|
|
357
455
|
},
|
|
358
456
|
});
|
|
359
457
|
const shared = new Map();
|
|
458
|
+
let writing = false;
|
|
459
|
+
let publishing = null;
|
|
460
|
+
let closed = false;
|
|
360
461
|
function searched(row) {
|
|
361
462
|
const read = row.text === null ? null : parse(row.text, row.path);
|
|
362
463
|
if (read === null || !read.ok)
|
|
@@ -376,8 +477,11 @@ export function createReadSide() {
|
|
|
376
477
|
return;
|
|
377
478
|
entry.rows.set(key, row);
|
|
378
479
|
}
|
|
480
|
+
function counted(entry) {
|
|
481
|
+
return entry.built.count === null ? undefined : entry.built.count.size;
|
|
482
|
+
}
|
|
379
483
|
function rebuilt(entry) {
|
|
380
|
-
return after(rowsOfPlan(entry.plan, [...entry.built.live.entries()], entry.bodies), ({ rows: found, keys }) => {
|
|
484
|
+
return after(rowsOfPlan(entry.plan, [...entry.built.live.entries()], counted(entry), entry.bodies), ({ rows: found, keys, next, total }) => {
|
|
381
485
|
const present = new Set(keys);
|
|
382
486
|
for (const key of [...entry.rows.keys()])
|
|
383
487
|
if (!present.has(key))
|
|
@@ -387,32 +491,34 @@ export function createReadSide() {
|
|
|
387
491
|
entry.bodies.delete(key);
|
|
388
492
|
}
|
|
389
493
|
keys.forEach((key, index) => kept(entry, key, rowAt(found, index)));
|
|
390
|
-
return keys;
|
|
494
|
+
return { keys, next, total };
|
|
391
495
|
});
|
|
392
496
|
}
|
|
393
497
|
function refreshed(entry, dirty) {
|
|
394
498
|
const shape = entry.plan.shape;
|
|
395
|
-
const
|
|
396
|
-
const
|
|
397
|
-
const
|
|
499
|
+
const { kept: inWindow, next, total, } = windowOf(entry.plan, [...entry.built.live.entries()], counted(entry));
|
|
500
|
+
const keys = inWindow.map(([key]) => key);
|
|
501
|
+
const present = new Set(keys);
|
|
502
|
+
for (const key of [...entry.rows.keys()]) {
|
|
503
|
+
if (present.has(key))
|
|
504
|
+
continue;
|
|
505
|
+
entry.rows.delete(key);
|
|
506
|
+
entry.bodies.delete(key);
|
|
507
|
+
}
|
|
508
|
+
const values = inWindow.filter(([key]) => dirty.has(key) || !entry.rows.has(key));
|
|
398
509
|
const done = inUnits(values, ([key, value]) => {
|
|
399
|
-
|
|
400
|
-
kept(entry, key, documentOf(key, value, shape, entry.bodies));
|
|
401
|
-
else {
|
|
402
|
-
entry.rows.delete(key);
|
|
403
|
-
entry.bodies.delete(key);
|
|
404
|
-
}
|
|
510
|
+
kept(entry, key, documentOf(key, value, shape, entry.bodies));
|
|
405
511
|
return weight(value);
|
|
406
512
|
});
|
|
407
|
-
return after(done, () => keys);
|
|
513
|
+
return after(done, () => ({ keys, next, total }));
|
|
408
514
|
}
|
|
409
|
-
function current(entry,
|
|
410
|
-
const
|
|
515
|
+
function current(entry, found, coverage) {
|
|
516
|
+
const rows = found.keys.map((key) => entry.rows.get(key));
|
|
411
517
|
return {
|
|
412
518
|
result: entry.plan.shape.kind === 'groups'
|
|
413
|
-
? { groups:
|
|
414
|
-
: { documents:
|
|
415
|
-
keys,
|
|
519
|
+
? framed({ groups: rows, coverage }, found)
|
|
520
|
+
: framed({ documents: rows, coverage }, found),
|
|
521
|
+
keys: found.keys,
|
|
416
522
|
};
|
|
417
523
|
}
|
|
418
524
|
function delivered(entry, next) {
|
|
@@ -448,25 +554,26 @@ export function createReadSide() {
|
|
|
448
554
|
const dirty = entry.dirty;
|
|
449
555
|
entry.dirty = new Set();
|
|
450
556
|
entry.whole = false;
|
|
451
|
-
const
|
|
452
|
-
if (
|
|
453
|
-
void
|
|
454
|
-
.then((
|
|
557
|
+
const found = whole ? rebuilt(entry) : refreshed(entry, dirty);
|
|
558
|
+
if (found instanceof Promise) {
|
|
559
|
+
void found
|
|
560
|
+
.then((window) => {
|
|
455
561
|
if (entry.listeners.size > 0)
|
|
456
|
-
delivered(entry, current(entry,
|
|
457
|
-
|
|
562
|
+
delivered(entry, current(entry, window, cover.coverage));
|
|
563
|
+
entry.running = false;
|
|
564
|
+
wake(entry);
|
|
458
565
|
})
|
|
459
566
|
.catch(() => {
|
|
460
567
|
entry.running = false;
|
|
461
568
|
});
|
|
462
569
|
return;
|
|
463
570
|
}
|
|
464
|
-
delivered(entry, current(entry,
|
|
571
|
+
delivered(entry, current(entry, found, cover.coverage));
|
|
465
572
|
}
|
|
466
573
|
entry.running = false;
|
|
467
574
|
}
|
|
468
575
|
function wake(entry) {
|
|
469
|
-
if (entry.subscription === null || entry.running)
|
|
576
|
+
if (entry.subscription === null || entry.running || writing || publishing !== null)
|
|
470
577
|
return;
|
|
471
578
|
entry.running = true;
|
|
472
579
|
try {
|
|
@@ -492,37 +599,92 @@ export function createReadSide() {
|
|
|
492
599
|
wake(entry);
|
|
493
600
|
}
|
|
494
601
|
}
|
|
602
|
+
function committed(next) {
|
|
603
|
+
if (closed || next.size === 0)
|
|
604
|
+
return;
|
|
605
|
+
sync.begin();
|
|
606
|
+
for (const [key, row] of next) {
|
|
607
|
+
if (row === null) {
|
|
608
|
+
if (rows.has(key))
|
|
609
|
+
sync.write({ type: 'delete', key });
|
|
610
|
+
continue;
|
|
611
|
+
}
|
|
612
|
+
sync.write({ type: rows.has(key) ? 'update' : 'insert', value: row });
|
|
613
|
+
}
|
|
614
|
+
sync.commit();
|
|
615
|
+
}
|
|
616
|
+
function published(set) {
|
|
617
|
+
let unit = new Map();
|
|
618
|
+
return inUnits(set.documents, (change) => {
|
|
619
|
+
if (closed)
|
|
620
|
+
return 0;
|
|
621
|
+
const shifted = rows.size / HELD_PER_WEIGHT;
|
|
622
|
+
let spent = 0;
|
|
623
|
+
for (const row of change.before) {
|
|
624
|
+
unit.set(row.key, null);
|
|
625
|
+
spent += ROW_WEIGHT + shifted;
|
|
626
|
+
}
|
|
627
|
+
for (const row of change.after) {
|
|
628
|
+
unit.set(row.key, row);
|
|
629
|
+
spent += weight(row) + shifted;
|
|
630
|
+
}
|
|
631
|
+
return spent;
|
|
632
|
+
}, () => {
|
|
633
|
+
committed(unit);
|
|
634
|
+
unit = new Map();
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
function released() {
|
|
638
|
+
recover();
|
|
639
|
+
for (const entry of shared.values())
|
|
640
|
+
wake(entry);
|
|
641
|
+
}
|
|
642
|
+
function publishedLater(applied) {
|
|
643
|
+
const fence = applied.then(() => { }, () => { });
|
|
644
|
+
publishing = fence;
|
|
645
|
+
void fence.then(() => {
|
|
646
|
+
if (publishing !== fence)
|
|
647
|
+
return;
|
|
648
|
+
publishing = null;
|
|
649
|
+
released();
|
|
650
|
+
});
|
|
651
|
+
return applied;
|
|
652
|
+
}
|
|
653
|
+
async function settled() {
|
|
654
|
+
while (publishing !== null)
|
|
655
|
+
await publishing;
|
|
656
|
+
}
|
|
495
657
|
return {
|
|
496
|
-
apply(set) {
|
|
497
|
-
const
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
next.set(row.key, null);
|
|
501
|
-
for (const row of change.after)
|
|
502
|
-
next.set(row.key, row);
|
|
658
|
+
apply(set, next = () => { }) {
|
|
659
|
+
const pending = publishing;
|
|
660
|
+
if (pending !== null) {
|
|
661
|
+
return publishedLater(pending.then(() => after(published(set), next)));
|
|
503
662
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
}
|
|
512
|
-
sync.write({ type: rows.has(key) ? 'update' : 'insert', value: row });
|
|
513
|
-
}
|
|
514
|
-
sync.commit();
|
|
663
|
+
writing = true;
|
|
664
|
+
let applied;
|
|
665
|
+
try {
|
|
666
|
+
applied = published(set);
|
|
667
|
+
}
|
|
668
|
+
finally {
|
|
669
|
+
writing = false;
|
|
515
670
|
}
|
|
516
|
-
|
|
671
|
+
if (applied instanceof Promise)
|
|
672
|
+
return publishedLater(applied.then(next));
|
|
673
|
+
released();
|
|
674
|
+
next();
|
|
517
675
|
},
|
|
518
676
|
recover,
|
|
677
|
+
settled,
|
|
519
678
|
async query(plan, at) {
|
|
520
|
-
const { live: collection, dispose } = built(rows, plan);
|
|
679
|
+
const { live: collection, count, dispose } = built(rows, plan);
|
|
521
680
|
try {
|
|
522
681
|
await collection.toArrayWhenReady();
|
|
682
|
+
if (count !== null)
|
|
683
|
+
await count.toArrayWhenReady();
|
|
684
|
+
await settled();
|
|
523
685
|
const entries = [...collection.entries()];
|
|
524
686
|
const held = at();
|
|
525
|
-
const found = await rowsOfPlan(plan, entries, null, structuredClone);
|
|
687
|
+
const found = await rowsOfPlan(plan, entries, count?.size, null, structuredClone);
|
|
526
688
|
return { rows: found.rows, at: held };
|
|
527
689
|
}
|
|
528
690
|
finally {
|
|
@@ -543,13 +705,16 @@ export function createReadSide() {
|
|
|
543
705
|
fresh: new Set(),
|
|
544
706
|
ready: new Set(),
|
|
545
707
|
subscription: null,
|
|
708
|
+
counting: null,
|
|
546
709
|
whole: true,
|
|
547
710
|
dirty: new Set(),
|
|
548
711
|
stale: false,
|
|
549
712
|
running: false,
|
|
550
713
|
};
|
|
551
714
|
created.built.live.on('status:change', ({ status }) => {
|
|
552
|
-
if (status
|
|
715
|
+
if (status !== 'cleaned-up' || created.listeners.size > 0)
|
|
716
|
+
return;
|
|
717
|
+
if (shared.get(identity) === created)
|
|
553
718
|
shared.delete(identity);
|
|
554
719
|
});
|
|
555
720
|
shared.set(identity, created);
|
|
@@ -557,7 +722,14 @@ export function createReadSide() {
|
|
|
557
722
|
}
|
|
558
723
|
const observed = entry;
|
|
559
724
|
observed.listeners.add(deliverTo);
|
|
560
|
-
observed.built.live.onFirstReady(() =>
|
|
725
|
+
const ready = (then) => observed.built.live.onFirstReady(() => observed.built.count === null ? then() : observed.built.count.onFirstReady(then));
|
|
726
|
+
const settled = () => {
|
|
727
|
+
if (observed.built.count === null)
|
|
728
|
+
wake(observed);
|
|
729
|
+
else
|
|
730
|
+
queueMicrotask(() => wake(observed));
|
|
731
|
+
};
|
|
732
|
+
ready(() => {
|
|
561
733
|
if (!observed.listeners.has(deliverTo))
|
|
562
734
|
return;
|
|
563
735
|
observed.fresh.add(deliverTo);
|
|
@@ -569,8 +741,13 @@ export function createReadSide() {
|
|
|
569
741
|
else
|
|
570
742
|
for (const { key } of changes)
|
|
571
743
|
observed.dirty.add(key);
|
|
572
|
-
|
|
744
|
+
settled();
|
|
573
745
|
}, { includeInitialState: false });
|
|
746
|
+
observed.counting =
|
|
747
|
+
observed.built.count?.subscribeChanges(() => {
|
|
748
|
+
observed.stale = true;
|
|
749
|
+
settled();
|
|
750
|
+
}, { includeInitialState: false }) ?? null;
|
|
574
751
|
}
|
|
575
752
|
wake(observed);
|
|
576
753
|
});
|
|
@@ -581,11 +758,16 @@ export function createReadSide() {
|
|
|
581
758
|
return;
|
|
582
759
|
observed.subscription?.unsubscribe();
|
|
583
760
|
observed.subscription = null;
|
|
761
|
+
observed.counting?.unsubscribe();
|
|
762
|
+
observed.counting = null;
|
|
584
763
|
observed.result = undefined;
|
|
585
764
|
observed.rows.clear();
|
|
586
765
|
observed.bodies.clear();
|
|
587
766
|
observed.dirty.clear();
|
|
588
767
|
observed.whole = true;
|
|
768
|
+
if (shared.get(identity) === observed)
|
|
769
|
+
shared.delete(identity);
|
|
770
|
+
observed.built.dispose();
|
|
589
771
|
};
|
|
590
772
|
},
|
|
591
773
|
room(room) {
|
|
@@ -596,11 +778,13 @@ export function createReadSide() {
|
|
|
596
778
|
return row === undefined || row.type === null ? null : searched(row);
|
|
597
779
|
},
|
|
598
780
|
close() {
|
|
781
|
+
closed = true;
|
|
599
782
|
for (const entry of shared.values()) {
|
|
600
783
|
entry.listeners.clear();
|
|
601
784
|
entry.fresh.clear();
|
|
602
785
|
entry.ready.clear();
|
|
603
786
|
entry.subscription?.unsubscribe();
|
|
787
|
+
entry.counting?.unsubscribe();
|
|
604
788
|
entry.built.dispose();
|
|
605
789
|
}
|
|
606
790
|
shared.clear();
|
|
@@ -625,13 +809,16 @@ function changedFrom(previous, next) {
|
|
|
625
809
|
const removed = previous.keys.filter((key) => !present.has(key));
|
|
626
810
|
const moved = reordered(previous.keys, next.keys, present);
|
|
627
811
|
const covered = !deepEquals(before.coverage, after.coverage);
|
|
628
|
-
|
|
812
|
+
const framing = reframed(before, after);
|
|
813
|
+
if (changed.length === 0 && removed.length === 0 && !moved && !covered && framing === null) {
|
|
629
814
|
return null;
|
|
815
|
+
}
|
|
630
816
|
return {
|
|
631
817
|
changed,
|
|
632
818
|
removed,
|
|
633
819
|
order: moved ? next.keys : null,
|
|
634
820
|
...(covered ? { coverage: after.coverage } : {}),
|
|
821
|
+
...framing,
|
|
635
822
|
};
|
|
636
823
|
}
|
|
637
824
|
function rowAt(rows, index) {
|
package/dist/reads.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Adapter } from './adapter.js';
|
|
2
|
+
import type { Reads } from './bootstrap.js';
|
|
3
|
+
export type DoorReads = Reads & {
|
|
4
|
+
carried(locator: string): number;
|
|
5
|
+
finished(locator: string, turn: number): void;
|
|
6
|
+
opened(): void;
|
|
7
|
+
applied(): void;
|
|
8
|
+
lost(): void;
|
|
9
|
+
};
|
|
10
|
+
export declare function doorReads(adapter: Adapter, declaration: (locator: string) => unknown, generation: () => number): DoorReads;
|
|
11
|
+
//# sourceMappingURL=reads.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reads.d.ts","sourceRoot":"","sources":["../src/reads.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EAOR,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG;IAC9B,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,MAAM,IAAI,IAAI,CAAC;IACf,OAAO,IAAI,IAAI,CAAC;IAChB,IAAI,IAAI,IAAI,CAAC;CACd,CAAC;AAiCF,wBAAgB,SAAS,CACvB,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,EACzC,UAAU,EAAE,MAAM,MAAM,GACvB,SAAS,CA0FX"}
|