@agentshouse/mdruntime 0.1.0-alpha.9 → 0.1.0-c0105dbd22806

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/AGENTS.md +299 -0
  2. package/README.md +54 -0
  3. package/dist/adapter.d.ts +246 -40
  4. package/dist/adapter.d.ts.map +1 -1
  5. package/dist/adapter.js +1 -10
  6. package/dist/attached-model.d.ts +11 -0
  7. package/dist/attached-model.d.ts.map +1 -0
  8. package/dist/attached-model.js +47 -0
  9. package/dist/attempt.d.ts +16 -0
  10. package/dist/attempt.d.ts.map +1 -0
  11. package/dist/attempt.js +70 -0
  12. package/dist/binary.d.ts +23 -0
  13. package/dist/binary.d.ts.map +1 -0
  14. package/dist/binary.js +8 -0
  15. package/dist/bootstrap.d.ts +17 -7
  16. package/dist/bootstrap.d.ts.map +1 -1
  17. package/dist/bootstrap.js +97 -41
  18. package/dist/change-set.d.ts +33 -0
  19. package/dist/change-set.d.ts.map +1 -0
  20. package/dist/change-set.js +90 -0
  21. package/dist/change.d.ts +24 -0
  22. package/dist/change.d.ts.map +1 -1
  23. package/dist/change.js +31 -5
  24. package/dist/chat/acts.d.ts +34 -0
  25. package/dist/chat/acts.d.ts.map +1 -0
  26. package/dist/chat/acts.js +36 -0
  27. package/dist/chat/context.d.ts +3 -0
  28. package/dist/chat/context.d.ts.map +1 -0
  29. package/dist/chat/context.js +10 -0
  30. package/dist/chat/input.d.ts +9 -0
  31. package/dist/chat/input.d.ts.map +1 -0
  32. package/dist/chat/input.js +99 -0
  33. package/dist/chat/kit.d.ts +60 -0
  34. package/dist/chat/kit.d.ts.map +1 -0
  35. package/dist/chat/kit.js +123 -0
  36. package/dist/chat/lasting.d.ts +6 -0
  37. package/dist/chat/lasting.d.ts.map +1 -0
  38. package/dist/chat/lasting.js +19 -0
  39. package/dist/chat/list.d.ts +26 -0
  40. package/dist/chat/list.d.ts.map +1 -0
  41. package/dist/chat/list.js +62 -0
  42. package/dist/chat/markdown.d.ts +20 -0
  43. package/dist/chat/markdown.d.ts.map +1 -0
  44. package/dist/chat/markdown.js +188 -0
  45. package/dist/chat/message.d.ts +6 -0
  46. package/dist/chat/message.d.ts.map +1 -0
  47. package/dist/chat/message.js +192 -0
  48. package/dist/chat/messages.d.ts +21 -0
  49. package/dist/chat/messages.d.ts.map +1 -0
  50. package/dist/chat/messages.js +151 -0
  51. package/dist/chat/name.d.ts +6 -0
  52. package/dist/chat/name.d.ts.map +1 -0
  53. package/dist/chat/name.js +37 -0
  54. package/dist/chat/opened.d.ts +11 -0
  55. package/dist/chat/opened.d.ts.map +1 -0
  56. package/dist/chat/opened.js +17 -0
  57. package/dist/chat/overlay.d.ts +31 -0
  58. package/dist/chat/overlay.d.ts.map +1 -0
  59. package/dist/chat/overlay.js +97 -0
  60. package/dist/chat/parts.d.ts +57 -0
  61. package/dist/chat/parts.d.ts.map +1 -0
  62. package/dist/chat/parts.js +119 -0
  63. package/dist/chat/process.d.ts +20 -0
  64. package/dist/chat/process.d.ts.map +1 -0
  65. package/dist/chat/process.js +32 -0
  66. package/dist/chat/provider.d.ts +63 -0
  67. package/dist/chat/provider.d.ts.map +1 -0
  68. package/dist/chat/provider.js +645 -0
  69. package/dist/chat/question.d.ts +9 -0
  70. package/dist/chat/question.d.ts.map +1 -0
  71. package/dist/chat/question.js +80 -0
  72. package/dist/chat/questions.d.ts +31 -0
  73. package/dist/chat/questions.d.ts.map +1 -0
  74. package/dist/chat/questions.js +111 -0
  75. package/dist/chat/read.d.ts +5 -0
  76. package/dist/chat/read.d.ts.map +1 -0
  77. package/dist/chat/read.js +13 -0
  78. package/dist/chat/ready.d.ts +33 -0
  79. package/dist/chat/ready.d.ts.map +1 -0
  80. package/dist/chat/ready.js +91 -0
  81. package/dist/chat/style.d.ts +4 -0
  82. package/dist/chat/style.d.ts.map +1 -0
  83. package/dist/chat/style.js +302 -0
  84. package/dist/chat.d.ts +14 -0
  85. package/dist/chat.d.ts.map +1 -0
  86. package/dist/chat.js +8 -0
  87. package/dist/client.d.ts +49 -33
  88. package/dist/client.d.ts.map +1 -1
  89. package/dist/client.js +164 -183
  90. package/dist/collection.d.ts +9 -17
  91. package/dist/collection.d.ts.map +1 -1
  92. package/dist/collection.js +83 -89
  93. package/dist/connection.d.ts +66 -48
  94. package/dist/connection.d.ts.map +1 -1
  95. package/dist/connection.js +1964 -1173
  96. package/dist/conversation.d.ts +65 -24
  97. package/dist/conversation.d.ts.map +1 -1
  98. package/dist/conversation.js +675 -334
  99. package/dist/durability.js +6 -6
  100. package/dist/entry.d.ts +17 -0
  101. package/dist/entry.d.ts.map +1 -0
  102. package/dist/entry.js +156 -0
  103. package/dist/expectation.d.ts +21 -0
  104. package/dist/expectation.d.ts.map +1 -0
  105. package/dist/expectation.js +70 -0
  106. package/dist/failure.d.ts +13 -0
  107. package/dist/failure.d.ts.map +1 -0
  108. package/dist/failure.js +19 -0
  109. package/dist/fence.d.ts +6 -0
  110. package/dist/fence.d.ts.map +1 -0
  111. package/dist/fence.js +10 -0
  112. package/dist/file.d.ts +2 -2
  113. package/dist/file.d.ts.map +1 -1
  114. package/dist/file.js +48 -71
  115. package/dist/host.d.ts +15 -3
  116. package/dist/host.d.ts.map +1 -1
  117. package/dist/host.js +109 -127
  118. package/dist/identity.d.ts +4 -0
  119. package/dist/identity.d.ts.map +1 -1
  120. package/dist/identity.js +22 -9
  121. package/dist/index.d.ts +17 -11
  122. package/dist/index.d.ts.map +1 -1
  123. package/dist/index.js +4 -3
  124. package/dist/log.js +5 -6
  125. package/dist/memory.d.ts +19 -8
  126. package/dist/memory.d.ts.map +1 -1
  127. package/dist/memory.js +304 -216
  128. package/dist/model.d.ts +16 -30
  129. package/dist/model.d.ts.map +1 -1
  130. package/dist/model.js +21 -21
  131. package/dist/observation.d.ts +27 -0
  132. package/dist/observation.d.ts.map +1 -0
  133. package/dist/observation.js +95 -0
  134. package/dist/open.d.ts +2 -0
  135. package/dist/open.d.ts.map +1 -0
  136. package/dist/open.js +1 -0
  137. package/dist/outcome.d.ts +37 -31
  138. package/dist/outcome.d.ts.map +1 -1
  139. package/dist/outcome.js +36 -18
  140. package/dist/overlay.d.ts +22 -4
  141. package/dist/overlay.d.ts.map +1 -1
  142. package/dist/overlay.js +236 -54
  143. package/dist/paths.d.ts +0 -2
  144. package/dist/paths.d.ts.map +1 -1
  145. package/dist/paths.js +6 -29
  146. package/dist/query.d.ts +219 -10
  147. package/dist/query.d.ts.map +1 -1
  148. package/dist/query.js +462 -15
  149. package/dist/reach.d.ts +42 -0
  150. package/dist/reach.d.ts.map +1 -0
  151. package/dist/reach.js +294 -0
  152. package/dist/react.d.ts +41 -0
  153. package/dist/react.d.ts.map +1 -0
  154. package/dist/react.js +64 -0
  155. package/dist/read-side.d.ts +18 -0
  156. package/dist/read-side.d.ts.map +1 -0
  157. package/dist/read-side.js +440 -0
  158. package/dist/refresh.d.ts +15 -5
  159. package/dist/refresh.d.ts.map +1 -1
  160. package/dist/refresh.js +64 -41
  161. package/dist/replica.d.ts +28 -5
  162. package/dist/replica.d.ts.map +1 -1
  163. package/dist/replica.js +249 -40
  164. package/dist/room-draft.d.ts +144 -0
  165. package/dist/room-draft.d.ts.map +1 -0
  166. package/dist/room-draft.js +438 -0
  167. package/dist/rows.d.ts +46 -0
  168. package/dist/rows.d.ts.map +1 -0
  169. package/dist/rows.js +145 -0
  170. package/dist/save.d.ts +33 -5
  171. package/dist/save.d.ts.map +1 -1
  172. package/dist/save.js +630 -366
  173. package/dist/search.d.ts +62 -0
  174. package/dist/search.d.ts.map +1 -0
  175. package/dist/search.js +125 -0
  176. package/dist/status.d.ts +6 -8
  177. package/dist/status.d.ts.map +1 -1
  178. package/dist/status.js +8 -20
  179. package/dist/store.d.ts +89 -34
  180. package/dist/store.d.ts.map +1 -1
  181. package/dist/store.js +513 -132
  182. package/dist/transfer.d.ts +5 -0
  183. package/dist/transfer.d.ts.map +1 -1
  184. package/dist/transfer.js +1 -5
  185. package/dist/wire.d.ts +59 -19
  186. package/dist/wire.d.ts.map +1 -1
  187. package/dist/wire.js +88 -105
  188. package/package.json +34 -16
  189. package/dist/adapter.js.map +0 -1
  190. package/dist/bootstrap.js.map +0 -1
  191. package/dist/change.js.map +0 -1
  192. package/dist/client.js.map +0 -1
  193. package/dist/collection.js.map +0 -1
  194. package/dist/connection.js.map +0 -1
  195. package/dist/conversation.js.map +0 -1
  196. package/dist/durability.js.map +0 -1
  197. package/dist/file.js.map +0 -1
  198. package/dist/host.js.map +0 -1
  199. package/dist/identity.js.map +0 -1
  200. package/dist/index.js.map +0 -1
  201. package/dist/log.js.map +0 -1
  202. package/dist/memory.js.map +0 -1
  203. package/dist/model.js.map +0 -1
  204. package/dist/outcome.js.map +0 -1
  205. package/dist/overlay.js.map +0 -1
  206. package/dist/paths.js.map +0 -1
  207. package/dist/query.js.map +0 -1
  208. package/dist/refresh.js.map +0 -1
  209. package/dist/replica.js.map +0 -1
  210. package/dist/save.js.map +0 -1
  211. package/dist/status.js.map +0 -1
  212. package/dist/store.js.map +0 -1
  213. package/dist/transfer.js.map +0 -1
  214. package/dist/wire.js.map +0 -1
package/dist/store.js CHANGED
@@ -1,191 +1,572 @@
1
+ import { sameBinary, sameChange } from './overlay.js';
1
2
  const DATABASE = 'mdruntime';
2
- const REPLICAS = 'replicas';
3
- const SYNCHRONIZATION = 'synchronization';
4
- const DISCOVERY = 'discovery';
5
- const QUEUES = 'queues';
6
- const DRAFTS = 'drafts';
3
+ const AUTHORED = 'mdruntime-authored';
4
+ const FENCES = 'fences';
5
+ const ROOMS = 'rooms';
6
+ const DOCUMENTS = 'documents';
7
+ const BINARY_FILES = 'binaryFiles';
8
+ const TRANSFERS = 'transfers';
9
+ const PENDING_CHANGES = 'pendingChanges';
10
+ const DECLARATIONS = 'declarations';
11
+ const ROOM_DRAFTS = 'roomDrafts';
7
12
  const PRESENTATION = 'presentation';
8
13
  const CONVERSATIONS = 'conversations';
9
- const INSTRUCTIONS = 'instructions';
10
- const LAST_COMPLETED = 'lastCompleted';
14
+ const MESSAGES = 'messages';
15
+ const CHAT_DRAFTS = 'chatDrafts';
16
+ const QUEUES = 'queues';
17
+ const FACTS = 'facts';
18
+ const CURRENT = 'current';
19
+ const MEMBER = 'member';
11
20
  const GENERATION = 'generation';
12
- const PROVIDER_LIMITS = 'providerLimits';
13
- const SCHEMA = 8;
21
+ const HOLDER = 'holder';
22
+ export const STORE_SCHEMA = 23;
23
+ export const AUTHORED_SCHEMA = 2;
24
+ const AUTHORED_STORES = [
25
+ [QUEUES, { keyPath: 'locator' }],
26
+ [PENDING_CHANGES, { keyPath: ['locator', 'id'] }],
27
+ [ROOM_DRAFTS, { keyPath: ['locator', 'path'] }],
28
+ [CHAT_DRAFTS, { keyPath: 'conversation' }],
29
+ [FACTS, undefined],
30
+ [FENCES, { keyPath: 'locator' }],
31
+ ];
32
+ const READ_BATCH = 256;
14
33
  function settled(request) {
15
- return new Promise((resolve, reject)=>{
16
- request.onsuccess = ()=>resolve(request.result);
17
- request.onerror = ()=>reject(request.error);
34
+ return new Promise((resolve, reject) => {
35
+ request.onsuccess = () => resolve(request.result);
36
+ request.onerror = () => reject(request.error);
18
37
  });
19
38
  }
20
39
  function completed(transaction) {
21
- return new Promise((resolve, reject)=>{
22
- transaction.oncomplete = ()=>resolve();
23
- transaction.onerror = ()=>reject(transaction.error);
24
- transaction.onabort = ()=>reject(transaction.error);
40
+ return new Promise((resolve, reject) => {
41
+ transaction.oncomplete = () => resolve();
42
+ transaction.onerror = () => reject(transaction.error);
43
+ transaction.onabort = () => reject(transaction.error);
25
44
  });
26
45
  }
27
- export function removeRuntimeStore() {
28
- return new Promise((resolve, reject)=>{
29
- const removal = indexedDB.deleteDatabase(DATABASE);
30
- removal.onsuccess = ()=>resolve();
31
- removal.onerror = ()=>reject(removal.error);
46
+ const EMPTY_DECLARATIONS = {
47
+ lastCompleted: null,
48
+ providerLimits: [],
49
+ capabilities: [],
50
+ };
51
+ function declaration(database) {
52
+ const transaction = database.transaction(DECLARATIONS, 'readonly');
53
+ return settled(transaction.objectStore(DECLARATIONS).get(CURRENT)).then((record) => record ?? EMPTY_DECLARATIONS);
54
+ }
55
+ function updateDeclaration(database, update) {
56
+ const transaction = database.transaction(DECLARATIONS, 'readwrite');
57
+ const store = transaction.objectStore(DECLARATIONS);
58
+ const prior = store.get(CURRENT);
59
+ prior.onsuccess = () => {
60
+ store.put(update(prior.result ?? EMPTY_DECLARATIONS), CURRENT);
61
+ };
62
+ return completed(transaction);
63
+ }
64
+ function amendPending(database, locator, id, amendment) {
65
+ const transaction = database.transaction(PENDING_CHANGES, 'readwrite');
66
+ const pending = transaction.objectStore(PENDING_CHANGES);
67
+ const request = pending.get([locator, id]);
68
+ request.onsuccess = () => {
69
+ const record = request.result;
70
+ if (record !== undefined)
71
+ pending.put({ ...record, ...amendment });
72
+ };
73
+ return completed(transaction);
74
+ }
75
+ function roomRecord(record) {
76
+ const { documents, binaries, revisions, changes, written, ...room } = record;
77
+ return room;
78
+ }
79
+ function chatDraftRecord(record) {
80
+ return { ...record, revision: record.revision ?? '' };
81
+ }
82
+ function underTransfer(locator, transfer, after) {
83
+ return after === undefined
84
+ ? IDBKeyRange.bound([locator, transfer], [locator, transfer, []])
85
+ : IDBKeyRange.bound([locator, transfer, after], [locator, transfer, []], true);
86
+ }
87
+ function underRoom(locator) {
88
+ return IDBKeyRange.bound([locator], [locator, []]);
89
+ }
90
+ async function readTransfer(store, locator, transfer, receive) {
91
+ let range = underTransfer(locator, transfer);
92
+ for (;;) {
93
+ const batch = await settled(store.getAll(range, READ_BATCH));
94
+ for (const record of batch)
95
+ receive(record);
96
+ if (batch.length < READ_BATCH)
97
+ return;
98
+ range = underTransfer(locator, transfer, batch[batch.length - 1].path);
99
+ }
100
+ }
101
+ function emptyLayer() {
102
+ return { documents: {}, binaries: {}, revisions: {}, changes: {}, written: {} };
103
+ }
104
+ async function readLayer(transaction, locator, transfer) {
105
+ const layer = emptyLayer();
106
+ const head = (held) => {
107
+ if (held.revision !== null)
108
+ layer.revisions[held.path] = held.revision;
109
+ if (held.change !== null)
110
+ layer.changes[held.path] = held.change;
111
+ };
112
+ await readTransfer(transaction.objectStore(DOCUMENTS), locator, transfer, (document) => {
113
+ layer.documents[document.path] = document.content;
114
+ if (document.written !== null)
115
+ layer.written[document.path] = document.written;
116
+ head(document);
32
117
  });
118
+ await readTransfer(transaction.objectStore(BINARY_FILES), locator, transfer, (file) => {
119
+ layer.binaries[file.path] = file.binary;
120
+ head(file);
121
+ });
122
+ return layer;
33
123
  }
34
- function discardEveryEarlierStore(database) {
35
- for (const name of [
36
- ...database.objectStoreNames
37
- ])database.deleteObjectStore(name);
124
+ function documentRecord(locator, transfer, layer, path) {
125
+ return {
126
+ locator,
127
+ transfer,
128
+ path,
129
+ content: layer.documents[path],
130
+ revision: layer.revisions[path] ?? null,
131
+ change: layer.changes[path] ?? null,
132
+ written: layer.written[path] ?? null,
133
+ };
134
+ }
135
+ function binaryFileRecord(locator, transfer, layer, path) {
136
+ return {
137
+ locator,
138
+ transfer,
139
+ path,
140
+ revision: layer.revisions[path] ?? null,
141
+ change: layer.changes[path] ?? null,
142
+ binary: layer.binaries[path],
143
+ };
38
144
  }
39
- export async function openRuntimeStore() {
40
- const opening = indexedDB.open(DATABASE, SCHEMA);
41
- opening.onupgradeneeded = ()=>{
145
+ function writeLayer(transaction, locator, transfer, next, base) {
146
+ const documents = transaction.objectStore(DOCUMENTS);
147
+ for (const path of Object.keys(base?.documents ?? {})) {
148
+ if (next.documents[path] === undefined)
149
+ documents.delete([locator, transfer, path]);
150
+ }
151
+ for (const [path, content] of Object.entries(next.documents)) {
152
+ if (base?.documents[path] === content &&
153
+ base.revisions[path] === next.revisions[path] &&
154
+ base.written[path] === next.written[path] &&
155
+ sameChange(base.changes[path], next.changes[path]))
156
+ continue;
157
+ documents.put(documentRecord(locator, transfer, next, path));
158
+ }
159
+ const files = transaction.objectStore(BINARY_FILES);
160
+ for (const path of Object.keys(base?.binaries ?? {})) {
161
+ if (next.binaries[path] === undefined)
162
+ files.delete([locator, transfer, path]);
163
+ }
164
+ for (const path of Object.keys(next.binaries)) {
165
+ if (!sameBinary(base?.binaries[path], next.binaries[path]) ||
166
+ base?.revisions[path] !== next.revisions[path] ||
167
+ !sameChange(base?.changes[path], next.changes[path])) {
168
+ files.put(binaryFileRecord(locator, transfer, next, path));
169
+ }
170
+ }
171
+ }
172
+ function removeRoomEntries(store, locator) {
173
+ const keys = store.getAllKeys();
174
+ keys.onsuccess = () => {
175
+ for (const key of keys.result) {
176
+ if (Array.isArray(key) && key[0] === locator)
177
+ store.delete(key);
178
+ }
179
+ };
180
+ }
181
+ function removeDatabase(name) {
182
+ return new Promise((resolve, reject) => {
183
+ const removal = indexedDB.deleteDatabase(name);
184
+ removal.onsuccess = () => resolve();
185
+ removal.onerror = () => reject(removal.error);
186
+ });
187
+ }
188
+ export async function authoredHolder() {
189
+ const authored = await openAuthored();
190
+ try {
191
+ const transaction = authored.transaction(FACTS, 'readonly');
192
+ const held = transaction.objectStore(FACTS).get(HOLDER);
193
+ await completed(transaction);
194
+ return typeof held.result === 'string' ? held.result : null;
195
+ }
196
+ finally {
197
+ authored.close();
198
+ }
199
+ }
200
+ export async function authoredBy(holder) {
201
+ const authored = await openAuthored();
202
+ try {
203
+ const transaction = authored.transaction(FACTS, 'readwrite');
204
+ const facts = transaction.objectStore(FACTS);
205
+ const held = facts.get(HOLDER);
206
+ let owned = true;
207
+ held.onsuccess = () => {
208
+ if (held.result === undefined)
209
+ facts.put(holder, HOLDER);
210
+ else
211
+ owned = held.result === holder;
212
+ };
213
+ await completed(transaction);
214
+ return owned;
215
+ }
216
+ finally {
217
+ authored.close();
218
+ }
219
+ }
220
+ export async function removeRuntimeStore(holder) {
221
+ await removeDatabase(DATABASE);
222
+ if (holder !== undefined && (await authoredBy(holder)))
223
+ return true;
224
+ await removeDatabase(AUTHORED);
225
+ return false;
226
+ }
227
+ function openReplica() {
228
+ const opening = indexedDB.open(DATABASE, STORE_SCHEMA);
229
+ opening.onupgradeneeded = () => {
42
230
  const database = opening.result;
43
- discardEveryEarlierStore(database);
44
- database.createObjectStore(REPLICAS, {
45
- keyPath: 'locator'
46
- });
47
- database.createObjectStore(SYNCHRONIZATION);
48
- database.createObjectStore(DISCOVERY);
49
- database.createObjectStore(QUEUES, {
50
- keyPath: 'locator'
51
- });
52
- database.createObjectStore(DRAFTS, {
53
- keyPath: [
54
- 'locator',
55
- 'path'
56
- ]
57
- });
58
- database.createObjectStore(PRESENTATION, {
59
- keyPath: 'app'
60
- });
61
- database.createObjectStore(CONVERSATIONS, {
62
- keyPath: 'conversation'
63
- });
64
- database.createObjectStore(INSTRUCTIONS, {
65
- keyPath: 'conversation'
231
+ for (const name of [...database.objectStoreNames])
232
+ database.deleteObjectStore(name);
233
+ database.createObjectStore(ROOMS, { keyPath: 'locator' });
234
+ database.createObjectStore(DOCUMENTS, { keyPath: ['locator', 'transfer', 'path'] });
235
+ database.createObjectStore(BINARY_FILES, { keyPath: ['locator', 'transfer', 'path'] });
236
+ database.createObjectStore(TRANSFERS, { keyPath: 'locator' });
237
+ database.createObjectStore(DECLARATIONS);
238
+ database.createObjectStore(PRESENTATION, { keyPath: 'app' });
239
+ database.createObjectStore(CONVERSATIONS, { keyPath: 'conversation' });
240
+ const messages = database.createObjectStore(MESSAGES, {
241
+ keyPath: ['conversation', 'identity'],
66
242
  });
243
+ messages.createIndex('conversation', 'conversation');
244
+ };
245
+ return settled(opening);
246
+ }
247
+ function openAuthored() {
248
+ const opening = indexedDB.open(AUTHORED, AUTHORED_SCHEMA);
249
+ opening.onupgradeneeded = () => {
250
+ const database = opening.result;
251
+ for (const [name, parameters] of AUTHORED_STORES) {
252
+ if (!database.objectStoreNames.contains(name))
253
+ database.createObjectStore(name, parameters);
254
+ }
67
255
  };
68
- const database = await settled(opening);
256
+ return settled(opening);
257
+ }
258
+ export async function openRuntimeStore(fenced) {
259
+ const authored = await openAuthored();
260
+ const database = await openReplica().catch((error) => {
261
+ authored.close();
262
+ throw error;
263
+ });
69
264
  return {
70
- async all () {
71
- const transaction = database.transaction(REPLICAS, 'readonly');
72
- return settled(transaction.objectStore(REPLICAS).getAll());
265
+ async all() {
266
+ const transaction = database.transaction([ROOMS, DOCUMENTS, BINARY_FILES], 'readonly');
267
+ const rooms = await settled(transaction.objectStore(ROOMS).getAll());
268
+ const records = [];
269
+ for (const room of rooms.filter((held) => !fenced(held.locator))) {
270
+ records.push({ ...room, ...(await readLayer(transaction, room.locator, room.transfer)) });
271
+ }
272
+ return records;
73
273
  },
74
- async publish (record) {
75
- const transaction = database.transaction(REPLICAS, 'readwrite');
76
- transaction.objectStore(REPLICAS).put(record);
274
+ async keepAuthored({ locator, queue, saved, roomDrafts, consumedRoomDrafts }) {
275
+ if (fenced(locator))
276
+ return;
277
+ const transaction = authored.transaction([QUEUES, PENDING_CHANGES, ROOM_DRAFTS], 'readwrite');
278
+ const order = transaction.objectStore(QUEUES);
279
+ const pending = transaction.objectStore(PENDING_CHANGES);
280
+ const held = order.get(locator);
281
+ held.onsuccess = () => {
282
+ const before = new Set(held.result?.order ?? []);
283
+ const after = new Set(queue.map((batch) => batch.id));
284
+ if (queue.length === 0)
285
+ order.delete(locator);
286
+ else
287
+ order.put({ locator, order: [...after] });
288
+ for (const id of before) {
289
+ if (!after.has(id))
290
+ pending.delete([locator, id]);
291
+ }
292
+ for (const batch of queue) {
293
+ if (!before.has(batch.id)) {
294
+ pending.put({
295
+ locator,
296
+ id: batch.id,
297
+ batch,
298
+ drafts: saved?.get(batch.id) ?? [],
299
+ submission: { state: 'waiting' },
300
+ lost: false,
301
+ });
302
+ }
303
+ }
304
+ };
305
+ const draftStore = transaction.objectStore(ROOM_DRAFTS);
306
+ for (const path of consumedRoomDrafts ?? [])
307
+ draftStore.delete([locator, path]);
308
+ for (const record of roomDrafts ?? [])
309
+ draftStore.put(record);
77
310
  await completed(transaction);
78
311
  },
79
- async lastCompleted () {
80
- const transaction = database.transaction(SYNCHRONIZATION, 'readonly');
81
- const value = await settled(transaction.objectStore(SYNCHRONIZATION).get(LAST_COMPLETED));
82
- return value ?? null;
312
+ async write({ next, previous, stored }) {
313
+ if (next === previous || fenced(next.locator))
314
+ return;
315
+ const transaction = database.transaction([ROOMS, DOCUMENTS, BINARY_FILES, TRANSFERS], 'readwrite');
316
+ transaction.objectStore(ROOMS).put(roomRecord(next));
317
+ const moved = previous?.transfer !== next.transfer;
318
+ if (moved && previous !== null) {
319
+ const range = underTransfer(previous.locator, previous.transfer);
320
+ transaction.objectStore(DOCUMENTS).delete(range);
321
+ transaction.objectStore(BINARY_FILES).delete(range);
322
+ }
323
+ if (moved)
324
+ transaction.objectStore(TRANSFERS).delete(next.locator);
325
+ writeLayer(transaction, next.locator, next.transfer, next, moved ? (stored ?? null) : previous);
326
+ await completed(transaction);
83
327
  },
84
- async complete (at) {
85
- const transaction = database.transaction(SYNCHRONIZATION, 'readwrite');
86
- transaction.objectStore(SYNCHRONIZATION).put(at, LAST_COMPLETED);
328
+ async revokeModels(records) {
329
+ const transaction = database.transaction(ROOMS, 'readwrite');
330
+ const rooms = transaction.objectStore(ROOMS);
331
+ const revoked = { status: 'unavailable', reason: 'revoked' };
332
+ for (const record of records) {
333
+ if (fenced(record.locator))
334
+ continue;
335
+ rooms.put(roomRecord({ ...record, model: revoked, selectionModel: revoked }));
336
+ }
87
337
  await completed(transaction);
88
338
  },
89
- async providerLimits () {
90
- const transaction = database.transaction(DISCOVERY, 'readonly');
91
- const value = await settled(transaction.objectStore(DISCOVERY).get(PROVIDER_LIMITS));
92
- return value ?? [];
339
+ async lastCompleted() {
340
+ return (await declaration(database)).lastCompleted;
341
+ },
342
+ complete(at) {
343
+ return updateDeclaration(database, (record) => ({ ...record, lastCompleted: at }));
344
+ },
345
+ async providerLimits() {
346
+ return (await declaration(database)).providerLimits;
347
+ },
348
+ async capabilities() {
349
+ return (await declaration(database)).capabilities;
350
+ },
351
+ declare(limits, capabilities) {
352
+ return updateDeclaration(database, (record) => ({
353
+ ...record,
354
+ providerLimits: limits,
355
+ capabilities,
356
+ }));
93
357
  },
94
- async declare (limits) {
95
- const transaction = database.transaction(DISCOVERY, 'readwrite');
96
- transaction.objectStore(DISCOVERY).put(limits, PROVIDER_LIMITS);
358
+ async member() {
359
+ const transaction = database.transaction(DECLARATIONS, 'readonly');
360
+ const held = await settled(transaction.objectStore(DECLARATIONS).get(MEMBER));
361
+ return held ?? null;
362
+ },
363
+ async keepMember(member) {
364
+ const transaction = database.transaction(DECLARATIONS, 'readwrite');
365
+ transaction.objectStore(DECLARATIONS).put(member, MEMBER);
97
366
  await completed(transaction);
98
367
  },
99
- async queues () {
100
- const transaction = database.transaction(QUEUES, 'readonly');
101
- return settled(transaction.objectStore(QUEUES).getAll());
368
+ async queues() {
369
+ const transaction = authored.transaction([QUEUES, PENDING_CHANGES], 'readonly');
370
+ const [queues, pending] = await Promise.all([
371
+ settled(transaction.objectStore(QUEUES).getAll()),
372
+ settled(transaction.objectStore(PENDING_CHANGES).getAll()),
373
+ ]);
374
+ const byId = new Map(pending.map((record) => [`${record.locator}\0${record.id}`, record]));
375
+ return queues
376
+ .filter((queue) => !fenced(queue.locator))
377
+ .map((queue) => ({
378
+ locator: queue.locator,
379
+ pending: queue.order.map((id) => {
380
+ const record = byId.get(`${queue.locator}\0${id}`);
381
+ if (record === undefined)
382
+ throw new Error(`Missing Pending Change ${queue.locator}/${id}`);
383
+ const { batch, drafts, submission, lost, upload, accepted } = record;
384
+ return { batch, state: { drafts, submission, lost, upload, accepted } };
385
+ }),
386
+ }));
387
+ },
388
+ async submit(locator, id, submission, lost) {
389
+ if (!fenced(locator))
390
+ await amendPending(authored, locator, id, { submission, lost });
391
+ },
392
+ async accept(locator, id, roomVersion) {
393
+ if (!fenced(locator))
394
+ await amendPending(authored, locator, id, { accepted: roomVersion });
102
395
  },
103
- async drafts () {
104
- const transaction = database.transaction(DRAFTS, 'readonly');
105
- return settled(transaction.objectStore(DRAFTS).getAll());
396
+ async keepUpload(locator, id, upload) {
397
+ if (!fenced(locator))
398
+ await amendPending(authored, locator, id, { upload });
106
399
  },
107
- async presentation () {
400
+ async roomDrafts() {
401
+ const transaction = authored.transaction(ROOM_DRAFTS, 'readonly');
402
+ const held = await settled(transaction.objectStore(ROOM_DRAFTS).getAll());
403
+ return held.filter((record) => !fenced(record.locator));
404
+ },
405
+ async presentation() {
108
406
  const transaction = database.transaction(PRESENTATION, 'readonly');
109
407
  return settled(transaction.objectStore(PRESENTATION).getAll());
110
408
  },
111
- async present (record) {
409
+ async present(record) {
112
410
  const transaction = database.transaction(PRESENTATION, 'readwrite');
113
411
  transaction.objectStore(PRESENTATION).put(record);
114
412
  await completed(transaction);
115
413
  },
116
- async conversations () {
117
- const transaction = database.transaction(CONVERSATIONS, 'readonly');
118
- return settled(transaction.objectStore(CONVERSATIONS).getAll());
414
+ async conversations() {
415
+ const transaction = database.transaction([CONVERSATIONS, MESSAGES], 'readonly');
416
+ const [reads, messages] = await Promise.all([
417
+ settled(transaction.objectStore(CONVERSATIONS).getAll()),
418
+ settled(transaction.objectStore(MESSAGES).getAll()),
419
+ ]);
420
+ const held = new Map();
421
+ for (const { conversation, read } of reads) {
422
+ held.set(conversation, { conversation, read, messages: [] });
423
+ }
424
+ for (const { conversation, ...message } of messages) {
425
+ const entry = held.get(conversation) ?? { conversation, read: undefined, messages: [] };
426
+ entry.messages.push(message);
427
+ held.set(conversation, entry);
428
+ }
429
+ return [...held.values()];
119
430
  },
120
- async keepConversation (record) {
121
- const transaction = database.transaction(CONVERSATIONS, 'readwrite');
122
- transaction.objectStore(CONVERSATIONS).put(record);
431
+ async keepMessages({ conversation, messages, read, sealed }) {
432
+ if (sealed === true) {
433
+ const sealing = authored.transaction(CHAT_DRAFTS, 'readwrite');
434
+ sealing.objectStore(CHAT_DRAFTS).delete(conversation);
435
+ await completed(sealing);
436
+ }
437
+ const transaction = database.transaction([CONVERSATIONS, MESSAGES], 'readwrite');
438
+ const stored = transaction.objectStore(MESSAGES);
439
+ for (const message of messages) {
440
+ stored.put({ ...message, conversation });
441
+ }
442
+ if (read !== undefined) {
443
+ transaction
444
+ .objectStore(CONVERSATIONS)
445
+ .put({ conversation, read });
446
+ }
123
447
  await completed(transaction);
124
448
  },
125
- async dropConversation (conversation) {
126
- const transaction = database.transaction(CONVERSATIONS, 'readwrite');
127
- transaction.objectStore(CONVERSATIONS).delete(conversation);
449
+ async dropConversations(conversations) {
450
+ const drafts = authored.transaction(CHAT_DRAFTS, 'readwrite');
451
+ for (const conversation of conversations)
452
+ drafts.objectStore(CHAT_DRAFTS).delete(conversation);
453
+ await completed(drafts);
454
+ const transaction = database.transaction([CONVERSATIONS, MESSAGES], 'readwrite');
455
+ const messages = transaction.objectStore(MESSAGES);
456
+ for (const conversation of conversations) {
457
+ transaction.objectStore(CONVERSATIONS).delete(conversation);
458
+ const keys = messages.index('conversation').getAllKeys(conversation);
459
+ keys.onsuccess = () => {
460
+ for (const key of keys.result)
461
+ messages.delete(key);
462
+ };
463
+ }
128
464
  await completed(transaction);
129
465
  },
130
- async instructions () {
131
- const transaction = database.transaction(INSTRUCTIONS, 'readonly');
132
- return settled(transaction.objectStore(INSTRUCTIONS).getAll());
466
+ async chatDrafts() {
467
+ const transaction = authored.transaction(CHAT_DRAFTS, 'readonly');
468
+ const held = await settled(transaction.objectStore(CHAT_DRAFTS).getAll());
469
+ return held.map(chatDraftRecord);
133
470
  },
134
- async keepInstruction (record) {
135
- const transaction = database.transaction(INSTRUCTIONS, 'readwrite');
136
- transaction.objectStore(INSTRUCTIONS).put(record);
471
+ async keepChatDraft(record) {
472
+ const transaction = authored.transaction(CHAT_DRAFTS, 'readwrite');
473
+ transaction.objectStore(CHAT_DRAFTS).put(record);
137
474
  await completed(transaction);
138
475
  },
139
- async dropInstruction (conversation) {
140
- const transaction = database.transaction(INSTRUCTIONS, 'readwrite');
141
- transaction.objectStore(INSTRUCTIONS).delete(conversation);
476
+ async dropChatDraft(conversation) {
477
+ const transaction = authored.transaction(CHAT_DRAFTS, 'readwrite');
478
+ transaction.objectStore(CHAT_DRAFTS).delete(conversation);
142
479
  await completed(transaction);
143
480
  },
144
- async keep (draft) {
145
- const transaction = database.transaction(DRAFTS, 'readwrite');
146
- transaction.objectStore(DRAFTS).put(draft);
481
+ async keepRoomDraft(record) {
482
+ if (fenced(record.locator))
483
+ return;
484
+ const transaction = authored.transaction(ROOM_DRAFTS, 'readwrite');
485
+ transaction.objectStore(ROOM_DRAFTS).put(record);
147
486
  await completed(transaction);
148
487
  },
149
- async discard (locator, path) {
150
- const transaction = database.transaction(DRAFTS, 'readwrite');
151
- transaction.objectStore(DRAFTS).delete([
152
- locator,
153
- path
154
- ]);
488
+ async discardRoomDraft(locator, path) {
489
+ if (fenced(locator))
490
+ return;
491
+ const transaction = authored.transaction(ROOM_DRAFTS, 'readwrite');
492
+ transaction.objectStore(ROOM_DRAFTS).delete([locator, path]);
155
493
  await completed(transaction);
156
494
  },
157
- async append (queue, consumed) {
158
- const transaction = database.transaction([
159
- QUEUES,
160
- DRAFTS
161
- ], 'readwrite');
162
- transaction.objectStore(QUEUES).put(queue);
163
- const drafts = transaction.objectStore(DRAFTS);
164
- for (const path of consumed)drafts.delete([
165
- queue.locator,
166
- path
167
- ]);
495
+ async fences() {
496
+ const transaction = authored.transaction(FENCES, 'readonly');
497
+ const held = await settled(transaction.objectStore(FENCES).getAll());
498
+ return held.map((fence) => fence.locator);
499
+ },
500
+ async erase(locators) {
501
+ const work = authored.transaction([FENCES, QUEUES, PENDING_CHANGES, ROOM_DRAFTS], 'readwrite');
502
+ for (const locator of locators) {
503
+ work.objectStore(FENCES).put({ locator });
504
+ work.objectStore(QUEUES).delete(locator);
505
+ for (const name of [PENDING_CHANGES, ROOM_DRAFTS]) {
506
+ removeRoomEntries(work.objectStore(name), locator);
507
+ }
508
+ }
509
+ await completed(work);
510
+ const transaction = database.transaction([ROOMS, DOCUMENTS, BINARY_FILES, TRANSFERS], 'readwrite');
511
+ for (const locator of locators) {
512
+ transaction.objectStore(ROOMS).delete(locator);
513
+ transaction.objectStore(TRANSFERS).delete(locator);
514
+ transaction.objectStore(DOCUMENTS).delete(underRoom(locator));
515
+ transaction.objectStore(BINARY_FILES).delete(underRoom(locator));
516
+ }
168
517
  await completed(transaction);
518
+ const fences = authored.transaction(FENCES, 'readwrite');
519
+ for (const locator of locators)
520
+ fences.objectStore(FENCES).delete(locator);
521
+ await completed(fences);
522
+ },
523
+ async transfers() {
524
+ const transaction = database.transaction(TRANSFERS, 'readonly');
525
+ const held = await settled(transaction.objectStore(TRANSFERS).getAll());
526
+ return held.filter((record) => !fenced(record.locator));
169
527
  },
170
- async writeQueue (queue) {
171
- const transaction = database.transaction(QUEUES, 'readwrite');
172
- transaction.objectStore(QUEUES).put(queue);
528
+ staged(record) {
529
+ const transaction = database.transaction([DOCUMENTS, BINARY_FILES], 'readonly');
530
+ return readLayer(transaction, record.locator, record.transfer);
531
+ },
532
+ async stage(record, page) {
533
+ if (fenced(record.locator))
534
+ return;
535
+ const transaction = database.transaction([TRANSFERS, DOCUMENTS, BINARY_FILES], 'readwrite');
536
+ writeLayer(transaction, record.locator, record.transfer, page, null);
537
+ transaction.objectStore(TRANSFERS).put(record);
173
538
  await completed(transaction);
174
539
  },
175
- async generation () {
176
- const transaction = database.transaction(SYNCHRONIZATION, 'readonly');
177
- const value = await settled(transaction.objectStore(SYNCHRONIZATION).get(GENERATION));
178
- return value ?? null;
540
+ async abandon(locator) {
541
+ if (fenced(locator))
542
+ return;
543
+ const transaction = database.transaction([TRANSFERS, DOCUMENTS, BINARY_FILES], 'readwrite');
544
+ const transfers = transaction.objectStore(TRANSFERS);
545
+ const held = transfers.get(locator);
546
+ held.onsuccess = () => {
547
+ const record = held.result;
548
+ if (record === undefined)
549
+ return;
550
+ transfers.delete(locator);
551
+ const range = underTransfer(locator, record.transfer);
552
+ transaction.objectStore(DOCUMENTS).delete(range);
553
+ transaction.objectStore(BINARY_FILES).delete(range);
554
+ };
555
+ await completed(transaction);
179
556
  },
180
- async rememberGeneration (value) {
181
- const transaction = database.transaction(SYNCHRONIZATION, 'readwrite');
182
- transaction.objectStore(SYNCHRONIZATION).put(value, GENERATION);
557
+ async generation() {
558
+ const transaction = authored.transaction(FACTS, 'readonly');
559
+ const held = await settled(transaction.objectStore(FACTS).get(GENERATION));
560
+ return held ?? null;
561
+ },
562
+ async rememberGeneration(value) {
563
+ const transaction = authored.transaction(FACTS, 'readwrite');
564
+ transaction.objectStore(FACTS).put(value, GENERATION);
183
565
  await completed(transaction);
184
566
  },
185
- close () {
567
+ close() {
568
+ authored.close();
186
569
  database.close();
187
- }
570
+ },
188
571
  };
189
572
  }
190
-
191
- //# sourceMappingURL=store.js.map