@agentshouse/mdruntime 0.1.0-cde2b99d2fcbc → 0.1.0-ce131cb435f8b
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 +271 -290
- package/README.md +8 -8
- package/dist/adapter.d.ts +52 -10
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attempt.d.ts.map +1 -1
- package/dist/attempt.js +14 -1
- package/dist/bootstrap.d.ts +3 -2
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +33 -7
- package/dist/change-set.d.ts +2 -0
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +36 -10
- package/dist/chat/acts.d.ts +3 -4
- package/dist/chat/acts.d.ts.map +1 -1
- package/dist/chat/acts.js +10 -10
- 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.d.ts +2 -1
- package/dist/chat/kit.d.ts.map +1 -1
- package/dist/chat/kit.js +3 -3
- package/dist/chat/list.d.ts +8 -1
- package/dist/chat/list.d.ts.map +1 -1
- package/dist/chat/list.js +48 -8
- package/dist/chat/markdown.d.ts +2 -1
- package/dist/chat/markdown.d.ts.map +1 -1
- package/dist/chat/markdown.js +7 -6
- package/dist/chat/message.d.ts.map +1 -1
- package/dist/chat/message.js +2 -2
- package/dist/chat/messages.d.ts +1 -0
- package/dist/chat/messages.d.ts.map +1 -1
- package/dist/chat/messages.js +4 -0
- package/dist/chat/provider.d.ts +1 -1
- package/dist/chat/provider.d.ts.map +1 -1
- package/dist/chat/provider.js +62 -79
- 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 -0
- package/dist/chat/ready.d.ts.map +1 -1
- package/dist/chat/ready.js +4 -4
- package/dist/chat/style.js +5 -5
- package/dist/client.d.ts +17 -9
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +19 -6
- package/dist/collection.d.ts +20 -5
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +309 -33
- package/dist/connection.d.ts +31 -9
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +1620 -397
- package/dist/conversation.d.ts +20 -7
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +474 -163
- package/dist/durability.d.ts +7 -1
- package/dist/durability.d.ts.map +1 -1
- package/dist/entry.d.ts +17 -0
- package/dist/entry.d.ts.map +1 -0
- package/dist/entry.js +157 -0
- package/dist/fence.d.ts +6 -0
- package/dist/fence.d.ts.map +1 -0
- package/dist/fence.js +10 -0
- package/dist/host.d.ts +15 -3
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +94 -12
- package/dist/identity.d.ts +2 -0
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +6 -0
- package/dist/index.d.ts +10 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/memory.d.ts +8 -2
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +33 -6
- package/dist/model.d.ts +4 -2
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +10 -1
- package/dist/observation.d.ts +7 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +29 -12
- package/dist/outcome.d.ts +12 -2
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +4 -0
- package/dist/overlay.d.ts +3 -0
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +62 -55
- package/dist/query.d.ts +56 -4
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +36 -7
- package/dist/reach.d.ts +6 -3
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +30 -5
- package/dist/react.d.ts +8 -6
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +7 -17
- package/dist/read-side.d.ts +16 -7
- package/dist/read-side.d.ts.map +1 -1
- package/dist/read-side.js +484 -100
- package/dist/readiness.d.ts +53 -0
- package/dist/readiness.d.ts.map +1 -0
- package/dist/readiness.js +33 -0
- package/dist/reads.d.ts +11 -0
- package/dist/reads.d.ts.map +1 -0
- package/dist/reads.js +98 -0
- package/dist/recovery.d.ts +25 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/recovery.js +197 -0
- package/dist/refresh.d.ts +4 -4
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +18 -11
- package/dist/replica.d.ts +10 -5
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +96 -44
- package/dist/room-draft.d.ts +13 -1
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +2 -2
- package/dist/rows.d.ts +6 -13
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +10 -13
- package/dist/save.d.ts +9 -3
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +68 -22
- package/dist/search.d.ts +49 -6
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +192 -47
- 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 +14 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +394 -0
- package/dist/status.d.ts +4 -0
- package/dist/status.d.ts.map +1 -1
- package/dist/store.d.ts +64 -16
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +447 -178
- package/dist/turn.d.ts +9 -0
- package/dist/turn.d.ts.map +1 -0
- package/dist/turn.js +64 -0
- 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 +152 -32
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +52 -31
- package/package.json +12 -8
package/dist/store.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { sameBinary, sameChange } from './overlay.js';
|
|
2
|
+
import { differing } from './shared.js';
|
|
3
|
+
import { precedes } from './windows.js';
|
|
2
4
|
const DATABASE = 'mdruntime';
|
|
5
|
+
const AUTHORED = 'mdruntime-authored';
|
|
6
|
+
const FENCES = 'fences';
|
|
3
7
|
const ROOMS = 'rooms';
|
|
4
8
|
const DOCUMENTS = 'documents';
|
|
5
9
|
const BINARY_FILES = 'binaryFiles';
|
|
6
10
|
const TRANSFERS = 'transfers';
|
|
11
|
+
const RECEIVED = 'received';
|
|
12
|
+
const RECEIVED_PARTS = 'receivedParts';
|
|
7
13
|
const PENDING_CHANGES = 'pendingChanges';
|
|
8
14
|
const DECLARATIONS = 'declarations';
|
|
9
15
|
const ROOM_DRAFTS = 'roomDrafts';
|
|
@@ -11,12 +17,45 @@ const PRESENTATION = 'presentation';
|
|
|
11
17
|
const CONVERSATIONS = 'conversations';
|
|
12
18
|
const MESSAGES = 'messages';
|
|
13
19
|
const CHAT_DRAFTS = 'chatDrafts';
|
|
20
|
+
const CALLS = 'calls';
|
|
21
|
+
const QUEUES = 'queues';
|
|
22
|
+
const FACTS = 'facts';
|
|
14
23
|
const CURRENT = 'current';
|
|
15
24
|
const MEMBER = 'member';
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
const
|
|
25
|
+
const TARGETS = 'targets';
|
|
26
|
+
const GENERATION = 'generation';
|
|
27
|
+
const HOLDER = 'holder';
|
|
28
|
+
const BINDING = 'binding';
|
|
29
|
+
export const STORE_SCHEMA = 25;
|
|
30
|
+
const REPLICA_SHAPE = 23;
|
|
31
|
+
export const AUTHORED_SCHEMA = 3;
|
|
32
|
+
const AUTHORED_STORES = [
|
|
33
|
+
[QUEUES, { keyPath: 'locator' }],
|
|
34
|
+
[PENDING_CHANGES, { keyPath: ['locator', 'id'] }],
|
|
35
|
+
[ROOM_DRAFTS, { keyPath: ['locator', 'path'] }],
|
|
36
|
+
[CHAT_DRAFTS, { keyPath: 'conversation' }],
|
|
37
|
+
[CALLS, { keyPath: 'operation' }],
|
|
38
|
+
[FACTS, undefined],
|
|
39
|
+
[FENCES, { keyPath: 'locator' }],
|
|
40
|
+
];
|
|
41
|
+
const REPLICA_STORES = [
|
|
42
|
+
[ROOMS, { keyPath: 'locator' }],
|
|
43
|
+
[DOCUMENTS, { keyPath: ['locator', 'transfer', 'path'] }],
|
|
44
|
+
[BINARY_FILES, { keyPath: ['locator', 'transfer', 'path'] }],
|
|
45
|
+
[TRANSFERS, { keyPath: 'locator' }],
|
|
46
|
+
[RECEIVED, { keyPath: 'key' }],
|
|
47
|
+
[RECEIVED_PARTS, { keyPath: ['key', 'index'] }],
|
|
48
|
+
[DECLARATIONS, undefined],
|
|
49
|
+
[PRESENTATION, { keyPath: 'app' }],
|
|
50
|
+
[CONVERSATIONS, { keyPath: 'conversation' }],
|
|
51
|
+
[MESSAGES, { keyPath: ['conversation', 'identity'] }],
|
|
52
|
+
];
|
|
19
53
|
const READ_BATCH = 256;
|
|
54
|
+
const MESSAGE_INDEXES = [
|
|
55
|
+
['conversation', 'conversation'],
|
|
56
|
+
['position', ['conversation', 'position']],
|
|
57
|
+
['turn', ['conversation', 'turn']],
|
|
58
|
+
];
|
|
20
59
|
function settled(request) {
|
|
21
60
|
return new Promise((resolve, reject) => {
|
|
22
61
|
request.onsuccess = () => resolve(request.result);
|
|
@@ -32,7 +71,6 @@ function completed(transaction) {
|
|
|
32
71
|
}
|
|
33
72
|
const EMPTY_DECLARATIONS = {
|
|
34
73
|
lastCompleted: null,
|
|
35
|
-
generation: null,
|
|
36
74
|
providerLimits: [],
|
|
37
75
|
capabilities: [],
|
|
38
76
|
};
|
|
@@ -60,9 +98,15 @@ function amendPending(database, locator, id, amendment) {
|
|
|
60
98
|
};
|
|
61
99
|
return completed(transaction);
|
|
62
100
|
}
|
|
63
|
-
function
|
|
64
|
-
|
|
65
|
-
|
|
101
|
+
function accepted({ conversation: _held, ...message }) {
|
|
102
|
+
return message;
|
|
103
|
+
}
|
|
104
|
+
function roomRecord(record) {
|
|
105
|
+
const { documents, binaries, revisions, fileIds, changes, written, ...room } = record;
|
|
106
|
+
return room;
|
|
107
|
+
}
|
|
108
|
+
function chatDraftRecord(record) {
|
|
109
|
+
return { ...record, revision: record.revision ?? '' };
|
|
66
110
|
}
|
|
67
111
|
function underTransfer(locator, transfer, after) {
|
|
68
112
|
return after === undefined
|
|
@@ -84,13 +128,15 @@ async function readTransfer(store, locator, transfer, receive) {
|
|
|
84
128
|
}
|
|
85
129
|
}
|
|
86
130
|
function emptyLayer() {
|
|
87
|
-
return { documents: {}, binaries: {}, revisions: {}, changes: {}, written: {} };
|
|
131
|
+
return { documents: {}, binaries: {}, revisions: {}, fileIds: {}, changes: {}, written: {} };
|
|
88
132
|
}
|
|
89
133
|
async function readLayer(transaction, locator, transfer) {
|
|
90
134
|
const layer = emptyLayer();
|
|
91
135
|
const head = (held) => {
|
|
92
136
|
if (held.revision !== null)
|
|
93
137
|
layer.revisions[held.path] = held.revision;
|
|
138
|
+
if (held.fileId !== null)
|
|
139
|
+
layer.fileIds[held.path] = held.fileId;
|
|
94
140
|
if (held.change !== null)
|
|
95
141
|
layer.changes[held.path] = held.change;
|
|
96
142
|
};
|
|
@@ -113,6 +159,7 @@ function documentRecord(locator, transfer, layer, path) {
|
|
|
113
159
|
path,
|
|
114
160
|
content: layer.documents[path],
|
|
115
161
|
revision: layer.revisions[path] ?? null,
|
|
162
|
+
fileId: layer.fileIds[path] ?? null,
|
|
116
163
|
change: layer.changes[path] ?? null,
|
|
117
164
|
written: layer.written[path] ?? null,
|
|
118
165
|
};
|
|
@@ -123,35 +170,37 @@ function binaryFileRecord(locator, transfer, layer, path) {
|
|
|
123
170
|
transfer,
|
|
124
171
|
path,
|
|
125
172
|
revision: layer.revisions[path] ?? null,
|
|
173
|
+
fileId: layer.fileIds[path] ?? null,
|
|
126
174
|
change: layer.changes[path] ?? null,
|
|
127
175
|
binary: layer.binaries[path],
|
|
128
176
|
};
|
|
129
177
|
}
|
|
130
178
|
function writeLayer(transaction, locator, transfer, next, base) {
|
|
131
179
|
const documents = transaction.objectStore(DOCUMENTS);
|
|
132
|
-
for (const path of Object.keys(base?.documents ?? {})) {
|
|
133
|
-
if (next.documents[path] === undefined)
|
|
134
|
-
documents.delete([locator, transfer, path]);
|
|
135
|
-
}
|
|
136
|
-
for (const [path, content] of Object.entries(next.documents)) {
|
|
137
|
-
if (base?.documents[path] === content &&
|
|
138
|
-
base.revisions[path] === next.revisions[path] &&
|
|
139
|
-
base.written[path] === next.written[path] &&
|
|
140
|
-
sameChange(base.changes[path], next.changes[path]))
|
|
141
|
-
continue;
|
|
142
|
-
documents.put(documentRecord(locator, transfer, next, path));
|
|
143
|
-
}
|
|
144
180
|
const files = transaction.objectStore(BINARY_FILES);
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
base
|
|
152
|
-
|
|
181
|
+
const paths = base === null
|
|
182
|
+
? new Set([...Object.keys(next.documents), ...Object.keys(next.binaries)])
|
|
183
|
+
: new Set([
|
|
184
|
+
...differing(base.documents, next.documents),
|
|
185
|
+
...differing(base.revisions, next.revisions),
|
|
186
|
+
...differing(base.fileIds, next.fileIds),
|
|
187
|
+
...differing(base.written, next.written),
|
|
188
|
+
...differing(base.changes, next.changes, sameChange),
|
|
189
|
+
...differing(base.binaries, next.binaries, sameBinary),
|
|
190
|
+
]);
|
|
191
|
+
for (const path of paths) {
|
|
192
|
+
if (next.documents[path] !== undefined) {
|
|
193
|
+
documents.put(documentRecord(locator, transfer, next, path));
|
|
194
|
+
}
|
|
195
|
+
else if (base?.documents[path] !== undefined) {
|
|
196
|
+
documents.delete([locator, transfer, path]);
|
|
197
|
+
}
|
|
198
|
+
if (next.binaries[path] !== undefined) {
|
|
153
199
|
files.put(binaryFileRecord(locator, transfer, next, path));
|
|
154
200
|
}
|
|
201
|
+
else if (base?.binaries[path] !== undefined) {
|
|
202
|
+
files.delete([locator, transfer, path]);
|
|
203
|
+
}
|
|
155
204
|
}
|
|
156
205
|
}
|
|
157
206
|
function removeRoomEntries(store, locator) {
|
|
@@ -163,123 +212,157 @@ function removeRoomEntries(store, locator) {
|
|
|
163
212
|
}
|
|
164
213
|
};
|
|
165
214
|
}
|
|
166
|
-
|
|
215
|
+
function removeDatabase(name) {
|
|
167
216
|
return new Promise((resolve, reject) => {
|
|
168
|
-
const removal = indexedDB.deleteDatabase(
|
|
217
|
+
const removal = indexedDB.deleteDatabase(name);
|
|
169
218
|
removal.onsuccess = () => resolve();
|
|
170
219
|
removal.onerror = () => reject(removal.error);
|
|
171
220
|
});
|
|
172
221
|
}
|
|
173
|
-
function
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
222
|
+
export async function authoredHolder() {
|
|
223
|
+
const authored = await openAuthored();
|
|
224
|
+
try {
|
|
225
|
+
const transaction = authored.transaction(FACTS, 'readonly');
|
|
226
|
+
const held = transaction.objectStore(FACTS).get(HOLDER);
|
|
227
|
+
await completed(transaction);
|
|
228
|
+
return typeof held.result === 'string' ? held.result : null;
|
|
229
|
+
}
|
|
230
|
+
finally {
|
|
231
|
+
authored.close();
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
export async function authoredBy(holder) {
|
|
235
|
+
const authored = await openAuthored();
|
|
236
|
+
try {
|
|
237
|
+
const transaction = authored.transaction(FACTS, 'readwrite');
|
|
238
|
+
const facts = transaction.objectStore(FACTS);
|
|
239
|
+
const held = facts.get(HOLDER);
|
|
240
|
+
let owned = true;
|
|
241
|
+
held.onsuccess = () => {
|
|
242
|
+
if (held.result === undefined)
|
|
243
|
+
facts.put(holder, HOLDER);
|
|
244
|
+
else
|
|
245
|
+
owned = held.result === holder;
|
|
246
|
+
};
|
|
247
|
+
await completed(transaction);
|
|
248
|
+
return owned;
|
|
249
|
+
}
|
|
250
|
+
finally {
|
|
251
|
+
authored.close();
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
export async function authoredBinding() {
|
|
255
|
+
const authored = await openAuthored();
|
|
256
|
+
try {
|
|
257
|
+
const transaction = authored.transaction(FACTS, 'readonly');
|
|
258
|
+
const held = transaction.objectStore(FACTS).get(BINDING);
|
|
259
|
+
await completed(transaction);
|
|
260
|
+
return typeof held.result === 'string' ? held.result : null;
|
|
261
|
+
}
|
|
262
|
+
finally {
|
|
263
|
+
authored.close();
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
export async function bindAuthored(binding) {
|
|
267
|
+
const authored = await openAuthored();
|
|
268
|
+
try {
|
|
269
|
+
const transaction = authored.transaction(FACTS, 'readwrite');
|
|
270
|
+
transaction.objectStore(FACTS).put(binding, BINDING);
|
|
271
|
+
await completed(transaction);
|
|
272
|
+
}
|
|
273
|
+
finally {
|
|
274
|
+
authored.close();
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
export async function removeRuntimeStore(holder) {
|
|
278
|
+
await removeDatabase(DATABASE);
|
|
279
|
+
if (holder !== undefined && (await authoredBy(holder)))
|
|
280
|
+
return true;
|
|
281
|
+
await removeDatabase(AUTHORED);
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
export function openDatabase(name, version, upgrade) {
|
|
285
|
+
return new Promise((resolve, reject) => {
|
|
286
|
+
const opening = indexedDB.open(name, version);
|
|
287
|
+
opening.onupgradeneeded = (event) => upgrade(opening, event.oldVersion);
|
|
288
|
+
opening.onsuccess = () => resolve(opening.result);
|
|
289
|
+
opening.onerror = () => {
|
|
290
|
+
if (opening.error?.name !== 'VersionError') {
|
|
291
|
+
reject(opening.error);
|
|
208
292
|
return;
|
|
209
293
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
if (document === null)
|
|
214
|
-
return;
|
|
215
|
-
const record = document.value;
|
|
216
|
-
if (kept.get(record.locator) !== record.transfer)
|
|
217
|
-
document.delete();
|
|
218
|
-
document.continue();
|
|
219
|
-
};
|
|
294
|
+
removeDatabase(name)
|
|
295
|
+
.then(() => openDatabase(name, version, upgrade))
|
|
296
|
+
.then(resolve, reject);
|
|
220
297
|
};
|
|
221
|
-
};
|
|
298
|
+
});
|
|
222
299
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
opening.onupgradeneeded = (event) => {
|
|
300
|
+
function openReplica() {
|
|
301
|
+
return openDatabase(DATABASE, STORE_SCHEMA, (opening, oldVersion) => {
|
|
226
302
|
const database = opening.result;
|
|
227
|
-
if (
|
|
228
|
-
|
|
229
|
-
|
|
303
|
+
if (oldVersion < REPLICA_SHAPE) {
|
|
304
|
+
for (const name of [...database.objectStoreNames])
|
|
305
|
+
database.deleteObjectStore(name);
|
|
230
306
|
}
|
|
231
|
-
for (const name of
|
|
232
|
-
database.
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
307
|
+
for (const [name, parameters] of REPLICA_STORES) {
|
|
308
|
+
if (database.objectStoreNames.contains(name))
|
|
309
|
+
continue;
|
|
310
|
+
database.createObjectStore(name, parameters);
|
|
311
|
+
}
|
|
312
|
+
const messages = opening.transaction.objectStore(MESSAGES);
|
|
313
|
+
for (const [name, keyPath] of MESSAGE_INDEXES) {
|
|
314
|
+
if (!messages.indexNames.contains(name))
|
|
315
|
+
messages.createIndex(name, keyPath);
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
function openAuthored() {
|
|
320
|
+
return openDatabase(AUTHORED, AUTHORED_SCHEMA, (opening) => {
|
|
321
|
+
const database = opening.result;
|
|
322
|
+
for (const [name, parameters] of AUTHORED_STORES) {
|
|
323
|
+
if (!database.objectStoreNames.contains(name))
|
|
324
|
+
database.createObjectStore(name, parameters);
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
export async function openRuntimeStore(fenced) {
|
|
329
|
+
const authored = await openAuthored();
|
|
330
|
+
const database = await openReplica().catch((error) => {
|
|
331
|
+
authored.close();
|
|
332
|
+
throw error;
|
|
333
|
+
});
|
|
249
334
|
return {
|
|
250
335
|
async all() {
|
|
251
336
|
const transaction = database.transaction([ROOMS, DOCUMENTS, BINARY_FILES], 'readonly');
|
|
252
337
|
const rooms = await settled(transaction.objectStore(ROOMS).getAll());
|
|
253
338
|
const records = [];
|
|
254
|
-
for (const
|
|
339
|
+
for (const room of rooms.filter((held) => !fenced(held.locator))) {
|
|
255
340
|
records.push({ ...room, ...(await readLayer(transaction, room.locator, room.transfer)) });
|
|
256
341
|
}
|
|
257
342
|
return records;
|
|
258
343
|
},
|
|
259
|
-
async
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
if (moved)
|
|
269
|
-
transaction.objectStore(TRANSFERS).delete(next.locator);
|
|
270
|
-
writeLayer(transaction, next.locator, next.transfer, next, moved ? (stored ?? null) : previous);
|
|
271
|
-
if (previousQueue !== undefined) {
|
|
272
|
-
const pending = transaction.objectStore(PENDING_CHANGES);
|
|
273
|
-
const before = new Set(previousQueue.map((batch) => batch.id));
|
|
344
|
+
async keepAuthored({ locator, queue, founded, saved, roomDrafts, consumedRoomDrafts }) {
|
|
345
|
+
if (fenced(locator))
|
|
346
|
+
return;
|
|
347
|
+
const transaction = authored.transaction([QUEUES, PENDING_CHANGES, ROOM_DRAFTS], 'readwrite');
|
|
348
|
+
const order = transaction.objectStore(QUEUES);
|
|
349
|
+
const pending = transaction.objectStore(PENDING_CHANGES);
|
|
350
|
+
const held = order.get(locator);
|
|
351
|
+
held.onsuccess = () => {
|
|
352
|
+
const before = new Set(held.result?.order ?? []);
|
|
274
353
|
const after = new Set(queue.map((batch) => batch.id));
|
|
354
|
+
if (queue.length === 0)
|
|
355
|
+
order.delete(locator);
|
|
356
|
+
else
|
|
357
|
+
order.put({ locator, order: [...after] });
|
|
275
358
|
for (const id of before) {
|
|
276
359
|
if (!after.has(id))
|
|
277
|
-
pending.delete([
|
|
360
|
+
pending.delete([locator, id]);
|
|
278
361
|
}
|
|
279
362
|
for (const batch of queue) {
|
|
280
363
|
if (!before.has(batch.id)) {
|
|
281
364
|
pending.put({
|
|
282
|
-
locator
|
|
365
|
+
locator,
|
|
283
366
|
id: batch.id,
|
|
284
367
|
batch,
|
|
285
368
|
drafts: saved?.get(batch.id) ?? [],
|
|
@@ -288,20 +371,48 @@ export async function openRuntimeStore() {
|
|
|
288
371
|
});
|
|
289
372
|
}
|
|
290
373
|
}
|
|
291
|
-
|
|
374
|
+
for (const batch of founded ?? []) {
|
|
375
|
+
if (!before.has(batch.id))
|
|
376
|
+
continue;
|
|
377
|
+
const stored = pending.get([locator, batch.id]);
|
|
378
|
+
stored.onsuccess = () => {
|
|
379
|
+
const record = stored.result;
|
|
380
|
+
if (record !== undefined)
|
|
381
|
+
pending.put({ ...record, batch });
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
};
|
|
292
385
|
const draftStore = transaction.objectStore(ROOM_DRAFTS);
|
|
293
386
|
for (const path of consumedRoomDrafts ?? [])
|
|
294
|
-
draftStore.delete([
|
|
387
|
+
draftStore.delete([locator, path]);
|
|
295
388
|
for (const record of roomDrafts ?? [])
|
|
296
389
|
draftStore.put(record);
|
|
297
390
|
await completed(transaction);
|
|
298
391
|
},
|
|
392
|
+
async write({ next, previous, stored }) {
|
|
393
|
+
if (next === previous || fenced(next.locator))
|
|
394
|
+
return;
|
|
395
|
+
const transaction = database.transaction([ROOMS, DOCUMENTS, BINARY_FILES, TRANSFERS], 'readwrite');
|
|
396
|
+
transaction.objectStore(ROOMS).put(roomRecord(next));
|
|
397
|
+
const moved = previous?.transfer !== next.transfer;
|
|
398
|
+
if (moved && previous !== null) {
|
|
399
|
+
const range = underTransfer(previous.locator, previous.transfer);
|
|
400
|
+
transaction.objectStore(DOCUMENTS).delete(range);
|
|
401
|
+
transaction.objectStore(BINARY_FILES).delete(range);
|
|
402
|
+
}
|
|
403
|
+
if (moved)
|
|
404
|
+
transaction.objectStore(TRANSFERS).delete(next.locator);
|
|
405
|
+
writeLayer(transaction, next.locator, next.transfer, next, moved ? (stored ?? null) : previous);
|
|
406
|
+
await completed(transaction);
|
|
407
|
+
},
|
|
299
408
|
async revokeModels(records) {
|
|
300
409
|
const transaction = database.transaction(ROOMS, 'readwrite');
|
|
301
410
|
const rooms = transaction.objectStore(ROOMS);
|
|
302
411
|
const revoked = { status: 'unavailable', reason: 'revoked' };
|
|
303
|
-
for (const
|
|
304
|
-
|
|
412
|
+
for (const record of records) {
|
|
413
|
+
if (fenced(record.locator))
|
|
414
|
+
continue;
|
|
415
|
+
rooms.put(roomRecord({ ...record, model: revoked, selectionModel: revoked }));
|
|
305
416
|
}
|
|
306
417
|
await completed(transaction);
|
|
307
418
|
},
|
|
@@ -334,36 +445,52 @@ export async function openRuntimeStore() {
|
|
|
334
445
|
transaction.objectStore(DECLARATIONS).put(member, MEMBER);
|
|
335
446
|
await completed(transaction);
|
|
336
447
|
},
|
|
448
|
+
async targets() {
|
|
449
|
+
const transaction = database.transaction(DECLARATIONS, 'readonly');
|
|
450
|
+
const held = await settled(transaction.objectStore(DECLARATIONS).get(TARGETS));
|
|
451
|
+
return held ?? {};
|
|
452
|
+
},
|
|
453
|
+
async keepTargets(targets) {
|
|
454
|
+
const transaction = database.transaction(DECLARATIONS, 'readwrite');
|
|
455
|
+
transaction.objectStore(DECLARATIONS).put(targets, TARGETS);
|
|
456
|
+
await completed(transaction);
|
|
457
|
+
},
|
|
337
458
|
async queues() {
|
|
338
|
-
const transaction =
|
|
339
|
-
const [
|
|
340
|
-
settled(transaction.objectStore(
|
|
459
|
+
const transaction = authored.transaction([QUEUES, PENDING_CHANGES], 'readonly');
|
|
460
|
+
const [queues, pending] = await Promise.all([
|
|
461
|
+
settled(transaction.objectStore(QUEUES).getAll()),
|
|
341
462
|
settled(transaction.objectStore(PENDING_CHANGES).getAll()),
|
|
342
463
|
]);
|
|
343
464
|
const byId = new Map(pending.map((record) => [`${record.locator}\0${record.id}`, record]));
|
|
344
|
-
return
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
465
|
+
return queues
|
|
466
|
+
.filter((queue) => !fenced(queue.locator))
|
|
467
|
+
.map((queue) => ({
|
|
468
|
+
locator: queue.locator,
|
|
469
|
+
pending: queue.order.map((id) => {
|
|
470
|
+
const record = byId.get(`${queue.locator}\0${id}`);
|
|
348
471
|
if (record === undefined)
|
|
349
|
-
throw new Error(`Missing Pending Change ${
|
|
472
|
+
throw new Error(`Missing Pending Change ${queue.locator}/${id}`);
|
|
350
473
|
const { batch, drafts, submission, lost, upload, accepted } = record;
|
|
351
474
|
return { batch, state: { drafts, submission, lost, upload, accepted } };
|
|
352
475
|
}),
|
|
353
476
|
}));
|
|
354
477
|
},
|
|
355
|
-
submit(locator, id, submission, lost) {
|
|
356
|
-
|
|
478
|
+
async submit(locator, id, submission, lost) {
|
|
479
|
+
if (!fenced(locator))
|
|
480
|
+
await amendPending(authored, locator, id, { submission, lost });
|
|
357
481
|
},
|
|
358
|
-
accept(locator, id, roomVersion) {
|
|
359
|
-
|
|
482
|
+
async accept(locator, id, roomVersion) {
|
|
483
|
+
if (!fenced(locator))
|
|
484
|
+
await amendPending(authored, locator, id, { accepted: roomVersion });
|
|
360
485
|
},
|
|
361
|
-
keepUpload(locator, id, upload) {
|
|
362
|
-
|
|
486
|
+
async keepUpload(locator, id, upload) {
|
|
487
|
+
if (!fenced(locator))
|
|
488
|
+
await amendPending(authored, locator, id, { upload });
|
|
363
489
|
},
|
|
364
490
|
async roomDrafts() {
|
|
365
|
-
const transaction =
|
|
366
|
-
|
|
491
|
+
const transaction = authored.transaction(ROOM_DRAFTS, 'readonly');
|
|
492
|
+
const held = await settled(transaction.objectStore(ROOM_DRAFTS).getAll());
|
|
493
|
+
return held.filter((record) => !fenced(record.locator));
|
|
367
494
|
},
|
|
368
495
|
async presentation() {
|
|
369
496
|
const transaction = database.transaction(PRESENTATION, 'readonly');
|
|
@@ -376,42 +503,107 @@ export async function openRuntimeStore() {
|
|
|
376
503
|
},
|
|
377
504
|
async conversations() {
|
|
378
505
|
const transaction = database.transaction([CONVERSATIONS, MESSAGES], 'readonly');
|
|
379
|
-
const
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
506
|
+
const records = await settled(transaction.objectStore(CONVERSATIONS).getAll());
|
|
507
|
+
const held = new Map(records.map(({ conversation, read, partial }) => [
|
|
508
|
+
conversation,
|
|
509
|
+
{ conversation, read, partial: partial === true },
|
|
510
|
+
]));
|
|
511
|
+
const keys = transaction.objectStore(MESSAGES).index('conversation');
|
|
512
|
+
await new Promise((resolve, reject) => {
|
|
513
|
+
const cursor = keys.openKeyCursor(null, 'nextunique');
|
|
514
|
+
cursor.onerror = () => reject(cursor.error);
|
|
515
|
+
cursor.onsuccess = () => {
|
|
516
|
+
const at = cursor.result;
|
|
517
|
+
if (at === null) {
|
|
518
|
+
resolve();
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
const conversation = at.key;
|
|
522
|
+
if (!held.has(conversation)) {
|
|
523
|
+
held.set(conversation, { conversation, read: undefined, partial: true });
|
|
524
|
+
}
|
|
525
|
+
at.continue();
|
|
526
|
+
};
|
|
527
|
+
});
|
|
392
528
|
return [...held.values()];
|
|
393
529
|
},
|
|
394
|
-
async keepMessages({ conversation, messages, read
|
|
395
|
-
const transaction = database.transaction([CONVERSATIONS, MESSAGES
|
|
530
|
+
async keepMessages({ conversation, messages, read }) {
|
|
531
|
+
const transaction = database.transaction([CONVERSATIONS, MESSAGES], 'readwrite');
|
|
396
532
|
const stored = transaction.objectStore(MESSAGES);
|
|
397
533
|
for (const message of messages) {
|
|
398
534
|
stored.put({ ...message, conversation });
|
|
399
535
|
}
|
|
400
536
|
if (read !== undefined) {
|
|
401
|
-
transaction
|
|
402
|
-
|
|
403
|
-
.
|
|
537
|
+
transaction.objectStore(CONVERSATIONS).put({
|
|
538
|
+
conversation,
|
|
539
|
+
read: read.at,
|
|
540
|
+
...(read.partial ? { partial: true } : {}),
|
|
541
|
+
});
|
|
404
542
|
}
|
|
405
|
-
if (sealed === true)
|
|
406
|
-
transaction.objectStore(CHAT_DRAFTS).delete(conversation);
|
|
407
543
|
await completed(transaction);
|
|
408
544
|
},
|
|
545
|
+
async messageWindow(conversation, limit, before) {
|
|
546
|
+
const transaction = database.transaction(MESSAGES, 'readonly');
|
|
547
|
+
const index = transaction.objectStore(MESSAGES).index('position');
|
|
548
|
+
const range = IDBKeyRange.bound([conversation], [conversation, before?.[0] ?? []]);
|
|
549
|
+
const latest = [];
|
|
550
|
+
let more = false;
|
|
551
|
+
await new Promise((resolve, reject) => {
|
|
552
|
+
const cursor = index.openCursor(range, 'prev');
|
|
553
|
+
cursor.onerror = () => reject(cursor.error);
|
|
554
|
+
cursor.onsuccess = () => {
|
|
555
|
+
const at = cursor.result;
|
|
556
|
+
if (at === null) {
|
|
557
|
+
resolve();
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
const record = at.value;
|
|
561
|
+
if (!precedes(record, before)) {
|
|
562
|
+
at.continue();
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
if (latest.length === limit) {
|
|
566
|
+
more = true;
|
|
567
|
+
resolve();
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
570
|
+
latest.push(accepted(record));
|
|
571
|
+
at.continue();
|
|
572
|
+
};
|
|
573
|
+
});
|
|
574
|
+
return { messages: latest.reverse(), more };
|
|
575
|
+
},
|
|
576
|
+
async messageCount(conversation) {
|
|
577
|
+
const transaction = database.transaction(MESSAGES, 'readonly');
|
|
578
|
+
return settled(transaction.objectStore(MESSAGES).index('conversation').count(conversation));
|
|
579
|
+
},
|
|
580
|
+
async messagesAfter(conversation, identity) {
|
|
581
|
+
const transaction = database.transaction(MESSAGES, 'readonly');
|
|
582
|
+
const range = identity === null
|
|
583
|
+
? IDBKeyRange.bound([conversation], [conversation, []])
|
|
584
|
+
: IDBKeyRange.bound([conversation, identity], [conversation, []], true);
|
|
585
|
+
const held = await settled(transaction.objectStore(MESSAGES).getAll(range, READ_BATCH));
|
|
586
|
+
return held.map(accepted);
|
|
587
|
+
},
|
|
588
|
+
async messageIdentities(conversation) {
|
|
589
|
+
const transaction = database.transaction(MESSAGES, 'readonly');
|
|
590
|
+
const keys = await settled(transaction.objectStore(MESSAGES).index('conversation').getAllKeys(conversation));
|
|
591
|
+
return keys.map((key) => key[1]);
|
|
592
|
+
},
|
|
593
|
+
async turnArrived(conversation, turn) {
|
|
594
|
+
const transaction = database.transaction(MESSAGES, 'readonly');
|
|
595
|
+
const held = await settled(transaction.objectStore(MESSAGES).index('turn').count([conversation, turn]));
|
|
596
|
+
return held > 0;
|
|
597
|
+
},
|
|
409
598
|
async dropConversations(conversations) {
|
|
410
|
-
const
|
|
599
|
+
const drafts = authored.transaction(CHAT_DRAFTS, 'readwrite');
|
|
600
|
+
for (const conversation of conversations)
|
|
601
|
+
drafts.objectStore(CHAT_DRAFTS).delete(conversation);
|
|
602
|
+
await completed(drafts);
|
|
603
|
+
const transaction = database.transaction([CONVERSATIONS, MESSAGES], 'readwrite');
|
|
411
604
|
const messages = transaction.objectStore(MESSAGES);
|
|
412
605
|
for (const conversation of conversations) {
|
|
413
606
|
transaction.objectStore(CONVERSATIONS).delete(conversation);
|
|
414
|
-
transaction.objectStore(CHAT_DRAFTS).delete(conversation);
|
|
415
607
|
const keys = messages.index('conversation').getAllKeys(conversation);
|
|
416
608
|
keys.onsuccess = () => {
|
|
417
609
|
for (const key of keys.result)
|
|
@@ -421,57 +613,103 @@ export async function openRuntimeStore() {
|
|
|
421
613
|
await completed(transaction);
|
|
422
614
|
},
|
|
423
615
|
async chatDrafts() {
|
|
424
|
-
const transaction =
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
transaction.
|
|
616
|
+
const transaction = authored.transaction(CHAT_DRAFTS, 'readonly');
|
|
617
|
+
const held = await settled(transaction.objectStore(CHAT_DRAFTS).getAll());
|
|
618
|
+
return held.map(chatDraftRecord);
|
|
619
|
+
},
|
|
620
|
+
async keepChatDrafts(records) {
|
|
621
|
+
const transaction = authored.transaction(CHAT_DRAFTS, 'readwrite');
|
|
622
|
+
for (const record of records)
|
|
623
|
+
transaction.objectStore(CHAT_DRAFTS).put(record);
|
|
430
624
|
await completed(transaction);
|
|
431
625
|
},
|
|
432
626
|
async dropChatDraft(conversation) {
|
|
433
|
-
const transaction =
|
|
627
|
+
const transaction = authored.transaction(CHAT_DRAFTS, 'readwrite');
|
|
434
628
|
transaction.objectStore(CHAT_DRAFTS).delete(conversation);
|
|
435
629
|
await completed(transaction);
|
|
436
630
|
},
|
|
631
|
+
async calls() {
|
|
632
|
+
const transaction = authored.transaction(CALLS, 'readonly');
|
|
633
|
+
return settled(transaction.objectStore(CALLS).getAll());
|
|
634
|
+
},
|
|
635
|
+
async keepCall(record) {
|
|
636
|
+
const transaction = authored.transaction(CALLS, 'readwrite');
|
|
637
|
+
transaction.objectStore(CALLS).put(record);
|
|
638
|
+
await completed(transaction);
|
|
639
|
+
},
|
|
640
|
+
async dropCall(operation) {
|
|
641
|
+
const transaction = authored.transaction(CALLS, 'readwrite');
|
|
642
|
+
transaction.objectStore(CALLS).delete(operation);
|
|
643
|
+
await completed(transaction);
|
|
644
|
+
},
|
|
437
645
|
async keepRoomDraft(record) {
|
|
438
|
-
|
|
646
|
+
if (fenced(record.locator))
|
|
647
|
+
return;
|
|
648
|
+
const transaction = authored.transaction(ROOM_DRAFTS, 'readwrite');
|
|
439
649
|
transaction.objectStore(ROOM_DRAFTS).put(record);
|
|
440
650
|
await completed(transaction);
|
|
441
651
|
},
|
|
442
652
|
async discardRoomDraft(locator, path) {
|
|
443
|
-
|
|
653
|
+
if (fenced(locator))
|
|
654
|
+
return;
|
|
655
|
+
const transaction = authored.transaction(ROOM_DRAFTS, 'readwrite');
|
|
444
656
|
transaction.objectStore(ROOM_DRAFTS).delete([locator, path]);
|
|
445
657
|
await completed(transaction);
|
|
446
658
|
},
|
|
447
|
-
async
|
|
448
|
-
const transaction =
|
|
659
|
+
async fences() {
|
|
660
|
+
const transaction = authored.transaction(FENCES, 'readonly');
|
|
661
|
+
const held = await settled(transaction.objectStore(FENCES).getAll());
|
|
662
|
+
return held.map((fence) => fence.locator);
|
|
663
|
+
},
|
|
664
|
+
async erase(locators) {
|
|
665
|
+
const work = authored.transaction([FENCES, QUEUES, PENDING_CHANGES, ROOM_DRAFTS], 'readwrite');
|
|
666
|
+
for (const locator of locators) {
|
|
667
|
+
work.objectStore(FENCES).put({ locator });
|
|
668
|
+
work.objectStore(QUEUES).delete(locator);
|
|
669
|
+
for (const name of [PENDING_CHANGES, ROOM_DRAFTS]) {
|
|
670
|
+
removeRoomEntries(work.objectStore(name), locator);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
await completed(work);
|
|
674
|
+
const transaction = database.transaction([ROOMS, DOCUMENTS, BINARY_FILES, TRANSFERS], 'readwrite');
|
|
449
675
|
for (const locator of locators) {
|
|
450
676
|
transaction.objectStore(ROOMS).delete(locator);
|
|
451
677
|
transaction.objectStore(TRANSFERS).delete(locator);
|
|
452
678
|
transaction.objectStore(DOCUMENTS).delete(underRoom(locator));
|
|
453
679
|
transaction.objectStore(BINARY_FILES).delete(underRoom(locator));
|
|
454
|
-
for (const name of [PENDING_CHANGES, ROOM_DRAFTS]) {
|
|
455
|
-
removeRoomEntries(transaction.objectStore(name), locator);
|
|
456
|
-
}
|
|
457
680
|
}
|
|
458
681
|
await completed(transaction);
|
|
682
|
+
const fences = authored.transaction(FENCES, 'readwrite');
|
|
683
|
+
for (const locator of locators)
|
|
684
|
+
fences.objectStore(FENCES).delete(locator);
|
|
685
|
+
await completed(fences);
|
|
686
|
+
},
|
|
687
|
+
async discard(locator) {
|
|
688
|
+
const transaction = authored.transaction([QUEUES, PENDING_CHANGES], 'readwrite');
|
|
689
|
+
transaction.objectStore(QUEUES).delete(locator);
|
|
690
|
+
removeRoomEntries(transaction.objectStore(PENDING_CHANGES), locator);
|
|
691
|
+
await completed(transaction);
|
|
459
692
|
},
|
|
460
693
|
async transfers() {
|
|
461
694
|
const transaction = database.transaction(TRANSFERS, 'readonly');
|
|
462
|
-
|
|
695
|
+
const held = await settled(transaction.objectStore(TRANSFERS).getAll());
|
|
696
|
+
return held.filter((record) => !fenced(record.locator));
|
|
463
697
|
},
|
|
464
698
|
staged(record) {
|
|
465
699
|
const transaction = database.transaction([DOCUMENTS, BINARY_FILES], 'readonly');
|
|
466
700
|
return readLayer(transaction, record.locator, record.transfer);
|
|
467
701
|
},
|
|
468
702
|
async stage(record, page) {
|
|
703
|
+
if (fenced(record.locator))
|
|
704
|
+
return;
|
|
469
705
|
const transaction = database.transaction([TRANSFERS, DOCUMENTS, BINARY_FILES], 'readwrite');
|
|
470
706
|
writeLayer(transaction, record.locator, record.transfer, page, null);
|
|
471
707
|
transaction.objectStore(TRANSFERS).put(record);
|
|
472
708
|
await completed(transaction);
|
|
473
709
|
},
|
|
474
710
|
async abandon(locator) {
|
|
711
|
+
if (fenced(locator))
|
|
712
|
+
return;
|
|
475
713
|
const transaction = database.transaction([TRANSFERS, DOCUMENTS, BINARY_FILES], 'readwrite');
|
|
476
714
|
const transfers = transaction.objectStore(TRANSFERS);
|
|
477
715
|
const held = transfers.get(locator);
|
|
@@ -486,13 +724,44 @@ export async function openRuntimeStore() {
|
|
|
486
724
|
};
|
|
487
725
|
await completed(transaction);
|
|
488
726
|
},
|
|
727
|
+
async receivedHeads() {
|
|
728
|
+
const transaction = database.transaction(RECEIVED, 'readonly');
|
|
729
|
+
return settled(transaction.objectStore(RECEIVED).getAll());
|
|
730
|
+
},
|
|
731
|
+
async receivedParts(key, count) {
|
|
732
|
+
const transaction = database.transaction(RECEIVED_PARTS, 'readonly');
|
|
733
|
+
const kept = await settled(transaction
|
|
734
|
+
.objectStore(RECEIVED_PARTS)
|
|
735
|
+
.getAll(IDBKeyRange.bound([key, 0], [key, count], false, true)));
|
|
736
|
+
return kept.map((part) => part.value);
|
|
737
|
+
},
|
|
738
|
+
async keepReceived(key, head, part) {
|
|
739
|
+
const transaction = database.transaction([RECEIVED, RECEIVED_PARTS], 'readwrite');
|
|
740
|
+
transaction.objectStore(RECEIVED).put({ key, head });
|
|
741
|
+
if (part !== undefined)
|
|
742
|
+
transaction.objectStore(RECEIVED_PARTS).put({ key, ...part });
|
|
743
|
+
await completed(transaction);
|
|
744
|
+
},
|
|
745
|
+
async dropReceived(keys) {
|
|
746
|
+
const transaction = database.transaction([RECEIVED, RECEIVED_PARTS], 'readwrite');
|
|
747
|
+
for (const key of keys) {
|
|
748
|
+
transaction.objectStore(RECEIVED).delete(key);
|
|
749
|
+
transaction.objectStore(RECEIVED_PARTS).delete(IDBKeyRange.bound([key], [key, []]));
|
|
750
|
+
}
|
|
751
|
+
await completed(transaction);
|
|
752
|
+
},
|
|
489
753
|
async generation() {
|
|
490
|
-
|
|
754
|
+
const transaction = authored.transaction(FACTS, 'readonly');
|
|
755
|
+
const held = await settled(transaction.objectStore(FACTS).get(GENERATION));
|
|
756
|
+
return held ?? null;
|
|
491
757
|
},
|
|
492
|
-
rememberGeneration(value) {
|
|
493
|
-
|
|
758
|
+
async rememberGeneration(value) {
|
|
759
|
+
const transaction = authored.transaction(FACTS, 'readwrite');
|
|
760
|
+
transaction.objectStore(FACTS).put(value, GENERATION);
|
|
761
|
+
await completed(transaction);
|
|
494
762
|
},
|
|
495
763
|
close() {
|
|
764
|
+
authored.close();
|
|
496
765
|
database.close();
|
|
497
766
|
},
|
|
498
767
|
};
|