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