@dabble/patches 0.4.5 → 0.4.6

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 (181) hide show
  1. package/dist/algorithms/client/applyCommittedChanges.d.ts +8 -2
  2. package/dist/algorithms/client/applyCommittedChanges.js +30 -38
  3. package/dist/algorithms/client/batching.d.ts +8 -2
  4. package/dist/algorithms/client/batching.js +38 -37
  5. package/dist/algorithms/client/breakChange.d.ts +8 -2
  6. package/dist/algorithms/client/breakChange.js +191 -240
  7. package/dist/algorithms/client/createStateFromSnapshot.d.ts +8 -2
  8. package/dist/algorithms/client/createStateFromSnapshot.js +7 -8
  9. package/dist/algorithms/client/getJSONByteSize.d.ts +3 -1
  10. package/dist/algorithms/client/getJSONByteSize.js +12 -11
  11. package/dist/algorithms/client/makeChange.d.ts +8 -2
  12. package/dist/algorithms/client/makeChange.js +28 -36
  13. package/dist/algorithms/server/commitChanges.d.ts +9 -3
  14. package/dist/algorithms/server/commitChanges.js +69 -78
  15. package/dist/algorithms/server/createVersion.d.ts +9 -3
  16. package/dist/algorithms/server/createVersion.js +21 -27
  17. package/dist/algorithms/server/getSnapshotAtRevision.d.ts +9 -3
  18. package/dist/algorithms/server/getSnapshotAtRevision.js +27 -28
  19. package/dist/algorithms/server/getStateAtRevision.d.ts +9 -3
  20. package/dist/algorithms/server/getStateAtRevision.js +13 -17
  21. package/dist/algorithms/server/handleOfflineSessionsAndBatches.d.ts +9 -3
  22. package/dist/algorithms/server/handleOfflineSessionsAndBatches.js +60 -77
  23. package/dist/algorithms/server/transformIncomingChanges.d.ts +8 -2
  24. package/dist/algorithms/server/transformIncomingChanges.js +27 -39
  25. package/dist/algorithms/shared/applyChanges.d.ts +8 -2
  26. package/dist/algorithms/shared/applyChanges.js +11 -16
  27. package/dist/algorithms/shared/rebaseChanges.d.ts +8 -2
  28. package/dist/algorithms/shared/rebaseChanges.js +30 -49
  29. package/dist/chunk-IZ2YBCUP.js +56 -0
  30. package/dist/client/InMemoryStore.d.ts +9 -3
  31. package/dist/client/InMemoryStore.js +92 -101
  32. package/dist/client/IndexedDBStore.d.ts +9 -3
  33. package/dist/client/IndexedDBStore.js +378 -491
  34. package/dist/client/Patches.d.ts +18 -13
  35. package/dist/client/Patches.js +152 -207
  36. package/dist/client/PatchesDoc.d.ts +14 -8
  37. package/dist/client/PatchesDoc.js +147 -154
  38. package/dist/client/PatchesHistoryClient.d.ts +12 -5
  39. package/dist/client/PatchesHistoryClient.js +110 -117
  40. package/dist/client/PatchesStore.d.ts +9 -3
  41. package/dist/client/PatchesStore.js +0 -1
  42. package/dist/client/index.d.ts +12 -6
  43. package/dist/client/index.js +5 -5
  44. package/dist/data/change.d.ts +9 -3
  45. package/dist/data/change.js +23 -15
  46. package/dist/data/version.d.ts +9 -3
  47. package/dist/data/version.js +11 -15
  48. package/dist/event-signal.d.ts +7 -6
  49. package/dist/event-signal.js +24 -39
  50. package/dist/index-CvQws3AB.d.ts +36 -0
  51. package/dist/index.d.ts +27 -5
  52. package/dist/index.js +10 -4
  53. package/dist/json-patch/JSONPatch.d.ts +9 -5
  54. package/dist/json-patch/JSONPatch.js +175 -183
  55. package/dist/json-patch/applyPatch.d.ts +5 -2
  56. package/dist/json-patch/applyPatch.js +27 -35
  57. package/dist/json-patch/composePatch.d.ts +5 -2
  58. package/dist/json-patch/composePatch.js +34 -34
  59. package/dist/json-patch/createJSONPatch.d.ts +7 -2
  60. package/dist/json-patch/createJSONPatch.js +11 -38
  61. package/dist/json-patch/index.d.ts +14 -6
  62. package/dist/json-patch/index.js +20 -9
  63. package/dist/json-patch/invertPatch.d.ts +5 -2
  64. package/dist/json-patch/invertPatch.js +31 -30
  65. package/dist/json-patch/ops/add.d.ts +5 -2
  66. package/dist/json-patch/ops/add.js +53 -51
  67. package/dist/json-patch/ops/bitmask.d.ts +8 -5
  68. package/dist/json-patch/ops/bitmask.js +41 -44
  69. package/dist/json-patch/ops/copy.d.ts +5 -2
  70. package/dist/json-patch/ops/copy.js +32 -33
  71. package/dist/json-patch/ops/increment.d.ts +5 -2
  72. package/dist/json-patch/ops/increment.js +21 -20
  73. package/dist/json-patch/ops/index.d.ts +10 -21
  74. package/dist/json-patch/ops/index.js +34 -24
  75. package/dist/json-patch/ops/move.d.ts +5 -2
  76. package/dist/json-patch/ops/move.js +132 -198
  77. package/dist/json-patch/ops/remove.d.ts +5 -2
  78. package/dist/json-patch/ops/remove.js +33 -30
  79. package/dist/json-patch/ops/replace.d.ts +5 -2
  80. package/dist/json-patch/ops/replace.js +45 -43
  81. package/dist/json-patch/ops/test.d.ts +5 -2
  82. package/dist/json-patch/ops/test.js +25 -21
  83. package/dist/json-patch/ops/text.d.ts +5 -2
  84. package/dist/json-patch/ops/text.js +54 -54
  85. package/dist/json-patch/pathProxy.d.ts +9 -3
  86. package/dist/json-patch/pathProxy.js +27 -48
  87. package/dist/json-patch/state.d.ts +5 -2
  88. package/dist/json-patch/state.js +11 -7
  89. package/dist/json-patch/transformPatch.d.ts +6 -2
  90. package/dist/json-patch/transformPatch.js +21 -24
  91. package/dist/json-patch/types.d.ts +9 -7
  92. package/dist/json-patch/types.js +0 -1
  93. package/dist/json-patch/utils/deepEqual.d.ts +3 -1
  94. package/dist/json-patch/utils/deepEqual.js +32 -28
  95. package/dist/json-patch/utils/exit.d.ts +5 -2
  96. package/dist/json-patch/utils/exit.js +7 -3
  97. package/dist/json-patch/utils/get.d.ts +5 -2
  98. package/dist/json-patch/utils/get.js +8 -4
  99. package/dist/json-patch/utils/getOpData.d.ts +5 -2
  100. package/dist/json-patch/utils/getOpData.js +12 -9
  101. package/dist/json-patch/utils/getType.d.ts +6 -3
  102. package/dist/json-patch/utils/getType.js +9 -4
  103. package/dist/json-patch/utils/index.d.ts +15 -14
  104. package/dist/json-patch/utils/index.js +14 -14
  105. package/dist/json-patch/utils/log.d.ts +4 -2
  106. package/dist/json-patch/utils/log.js +8 -3
  107. package/dist/json-patch/utils/ops.d.ts +8 -5
  108. package/dist/json-patch/utils/ops.js +83 -100
  109. package/dist/json-patch/utils/paths.d.ts +12 -9
  110. package/dist/json-patch/utils/paths.js +54 -51
  111. package/dist/json-patch/utils/pluck.d.ts +8 -5
  112. package/dist/json-patch/utils/pluck.js +32 -26
  113. package/dist/json-patch/utils/shallowCopy.d.ts +3 -1
  114. package/dist/json-patch/utils/shallowCopy.js +22 -18
  115. package/dist/json-patch/utils/softWrites.d.ts +6 -3
  116. package/dist/json-patch/utils/softWrites.js +17 -16
  117. package/dist/json-patch/utils/toArrayIndex.d.ts +3 -1
  118. package/dist/json-patch/utils/toArrayIndex.js +14 -10
  119. package/dist/json-patch/utils/toKeys.d.ts +3 -1
  120. package/dist/json-patch/utils/toKeys.js +15 -11
  121. package/dist/json-patch/utils/updateArrayIndexes.d.ts +5 -2
  122. package/dist/json-patch/utils/updateArrayIndexes.js +33 -37
  123. package/dist/json-patch/utils/updateArrayPath.d.ts +5 -2
  124. package/dist/json-patch/utils/updateArrayPath.js +29 -42
  125. package/dist/net/PatchesClient.d.ts +128 -0
  126. package/dist/net/PatchesClient.js +161 -0
  127. package/dist/net/PatchesSync.d.ts +19 -9
  128. package/dist/net/PatchesSync.js +291 -386
  129. package/dist/net/error.d.ts +3 -1
  130. package/dist/net/error.js +9 -6
  131. package/dist/net/http/FetchTransport.d.ts +21 -0
  132. package/dist/net/http/FetchTransport.js +34 -0
  133. package/dist/net/index.d.ts +26 -12
  134. package/dist/net/index.js +12 -10
  135. package/dist/net/protocol/JSONRPCClient.d.ts +11 -4
  136. package/dist/net/protocol/JSONRPCClient.js +95 -103
  137. package/dist/net/protocol/JSONRPCServer.d.ts +15 -8
  138. package/dist/net/protocol/JSONRPCServer.js +101 -123
  139. package/dist/net/protocol/types.d.ts +21 -15
  140. package/dist/net/protocol/types.js +0 -1
  141. package/dist/net/protocol/utils.d.ts +12 -0
  142. package/dist/net/protocol/utils.js +15 -0
  143. package/dist/net/types.d.ts +4 -2
  144. package/dist/net/types.js +0 -1
  145. package/dist/net/webrtc/WebRTCAwareness.d.ts +14 -4
  146. package/dist/net/webrtc/WebRTCAwareness.js +111 -120
  147. package/dist/net/webrtc/WebRTCTransport.d.ts +16 -8
  148. package/dist/net/webrtc/WebRTCTransport.js +149 -157
  149. package/dist/net/webrtc/index.d.ts +10 -2
  150. package/dist/net/webrtc/index.js +2 -2
  151. package/dist/net/websocket/AuthorizationProvider.d.ts +7 -5
  152. package/dist/net/websocket/AuthorizationProvider.js +12 -17
  153. package/dist/net/websocket/PatchesWebSocket.d.ts +14 -109
  154. package/dist/net/websocket/PatchesWebSocket.js +37 -184
  155. package/dist/net/websocket/RPCServer.d.ts +19 -10
  156. package/dist/net/websocket/RPCServer.js +190 -192
  157. package/dist/net/websocket/SignalingService.d.ts +12 -32
  158. package/dist/net/websocket/SignalingService.js +126 -133
  159. package/dist/net/websocket/WebSocketServer.d.ts +17 -4
  160. package/dist/net/websocket/WebSocketServer.js +64 -72
  161. package/dist/net/websocket/WebSocketTransport.d.ts +13 -5
  162. package/dist/net/websocket/WebSocketTransport.js +178 -207
  163. package/dist/net/websocket/onlineState.d.ts +6 -3
  164. package/dist/net/websocket/onlineState.js +25 -21
  165. package/dist/server/PatchesBranchManager.d.ts +12 -5
  166. package/dist/server/PatchesBranchManager.js +132 -142
  167. package/dist/server/PatchesHistoryManager.d.ts +11 -3
  168. package/dist/server/PatchesHistoryManager.js +81 -84
  169. package/dist/server/PatchesServer.d.ts +16 -10
  170. package/dist/server/PatchesServer.js +131 -137
  171. package/dist/server/index.d.ts +7 -2
  172. package/dist/server/index.js +9 -3
  173. package/dist/server/types.d.ts +9 -3
  174. package/dist/server/types.js +0 -1
  175. package/dist/types.d.ts +38 -19
  176. package/dist/types.js +1 -1
  177. package/dist/utils/concurrency.d.ts +7 -5
  178. package/dist/utils/concurrency.js +43 -53
  179. package/dist/utils/deferred.d.ts +4 -2
  180. package/dist/utils/deferred.js +25 -21
  181. package/package.json +5 -7
@@ -1,504 +1,391 @@
1
- var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
2
- var useValue = arguments.length > 2;
3
- for (var i = 0; i < initializers.length; i++) {
4
- value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
5
- }
6
- return useValue ? value : void 0;
7
- };
8
- var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
9
- function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
10
- var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
11
- var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
12
- var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
13
- var _, done = false;
14
- for (var i = decorators.length - 1; i >= 0; i--) {
15
- var context = {};
16
- for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
17
- for (var p in contextIn.access) context.access[p] = contextIn.access[p];
18
- context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
19
- var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
20
- if (kind === "accessor") {
21
- if (result === void 0) continue;
22
- if (result === null || typeof result !== "object") throw new TypeError("Object expected");
23
- if (_ = accept(result.get)) descriptor.get = _;
24
- if (_ = accept(result.set)) descriptor.set = _;
25
- if (_ = accept(result.init)) initializers.unshift(_);
26
- }
27
- else if (_ = accept(result)) {
28
- if (kind === "field") initializers.unshift(_);
29
- else descriptor[key] = _;
30
- }
31
- }
32
- if (target) Object.defineProperty(target, contextIn.name, descriptor);
33
- done = true;
34
- };
35
- import { applyChanges } from '../algorithms/shared/applyChanges.js';
36
- import { transformPatch } from '../json-patch/transformPatch.js';
37
- import { blockable } from '../utils/concurrency.js';
38
- import { deferred } from '../utils/deferred.js';
1
+ import {
2
+ __decorateElement,
3
+ __decoratorMetadata,
4
+ __decoratorStart,
5
+ __publicField,
6
+ __runInitializers
7
+ } from "../chunk-IZ2YBCUP.js";
8
+ var _getLastRevs_dec, _saveCommittedChanges_dec, _replacePendingChanges_dec, _getPendingChanges_dec, _savePendingChanges_dec, _saveDoc_dec, _confirmDeleteDoc_dec, _deleteDoc_dec, _getDoc_dec, _init;
9
+ import { applyChanges } from "../algorithms/shared/applyChanges.js";
10
+ import { transformPatch } from "../json-patch/transformPatch.js";
11
+ import { blockable } from "../utils/concurrency.js";
12
+ import { deferred } from "../utils/deferred.js";
39
13
  const DB_VERSION = 1;
40
14
  const SNAPSHOT_INTERVAL = 200;
41
- /**
42
- * Creates a new IndexedDB database with stores:
43
- * - snapshots<{ docId: string; rev: number; state: any }> (primary key: docId)
44
- * - committedChanges<Change & { docId: string; }> (primary key: [docId, rev])
45
- * - pendingChanges<Change & { docId: string; }> (primary key: [docId, rev])
46
- * - docs<{ docId: string; committedRev: number; deleted?: boolean }> (primary key: docId)
47
- *
48
- * Under the hood, this class will store snapshots of the document only for committed state. It will not update the
49
- * committed state on *every* received committed change as this can cause issues with IndexedDB with many large updates.
50
- * After every 200 committed changes, the class will save the current state to the snapshot store and delete the committed changes that went into it.
51
- * A snapshot will not be created if there are pending changes based on revisions older than the 200th committed change until those pending changes are committed.
52
- */
53
- let IndexedDBStore = (() => {
54
- let _instanceExtraInitializers = [];
55
- let _getDoc_decorators;
56
- let _deleteDoc_decorators;
57
- let _confirmDeleteDoc_decorators;
58
- let _saveDoc_decorators;
59
- let _savePendingChanges_decorators;
60
- let _getPendingChanges_decorators;
61
- let _replacePendingChanges_decorators;
62
- let _saveCommittedChanges_decorators;
63
- let _getLastRevs_decorators;
64
- return class IndexedDBStore {
65
- static {
66
- const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
67
- _getDoc_decorators = [blockable];
68
- _deleteDoc_decorators = [blockable];
69
- _confirmDeleteDoc_decorators = [blockable];
70
- _saveDoc_decorators = [blockable];
71
- _savePendingChanges_decorators = [blockable];
72
- _getPendingChanges_decorators = [blockable];
73
- _replacePendingChanges_decorators = [blockable];
74
- _saveCommittedChanges_decorators = [blockable];
75
- _getLastRevs_decorators = [blockable];
76
- __esDecorate(this, null, _getDoc_decorators, { kind: "method", name: "getDoc", static: false, private: false, access: { has: obj => "getDoc" in obj, get: obj => obj.getDoc }, metadata: _metadata }, null, _instanceExtraInitializers);
77
- __esDecorate(this, null, _deleteDoc_decorators, { kind: "method", name: "deleteDoc", static: false, private: false, access: { has: obj => "deleteDoc" in obj, get: obj => obj.deleteDoc }, metadata: _metadata }, null, _instanceExtraInitializers);
78
- __esDecorate(this, null, _confirmDeleteDoc_decorators, { kind: "method", name: "confirmDeleteDoc", static: false, private: false, access: { has: obj => "confirmDeleteDoc" in obj, get: obj => obj.confirmDeleteDoc }, metadata: _metadata }, null, _instanceExtraInitializers);
79
- __esDecorate(this, null, _saveDoc_decorators, { kind: "method", name: "saveDoc", static: false, private: false, access: { has: obj => "saveDoc" in obj, get: obj => obj.saveDoc }, metadata: _metadata }, null, _instanceExtraInitializers);
80
- __esDecorate(this, null, _savePendingChanges_decorators, { kind: "method", name: "savePendingChanges", static: false, private: false, access: { has: obj => "savePendingChanges" in obj, get: obj => obj.savePendingChanges }, metadata: _metadata }, null, _instanceExtraInitializers);
81
- __esDecorate(this, null, _getPendingChanges_decorators, { kind: "method", name: "getPendingChanges", static: false, private: false, access: { has: obj => "getPendingChanges" in obj, get: obj => obj.getPendingChanges }, metadata: _metadata }, null, _instanceExtraInitializers);
82
- __esDecorate(this, null, _replacePendingChanges_decorators, { kind: "method", name: "replacePendingChanges", static: false, private: false, access: { has: obj => "replacePendingChanges" in obj, get: obj => obj.replacePendingChanges }, metadata: _metadata }, null, _instanceExtraInitializers);
83
- __esDecorate(this, null, _saveCommittedChanges_decorators, { kind: "method", name: "saveCommittedChanges", static: false, private: false, access: { has: obj => "saveCommittedChanges" in obj, get: obj => obj.saveCommittedChanges }, metadata: _metadata }, null, _instanceExtraInitializers);
84
- __esDecorate(this, null, _getLastRevs_decorators, { kind: "method", name: "getLastRevs", static: false, private: false, access: { has: obj => "getLastRevs" in obj, get: obj => obj.getLastRevs }, metadata: _metadata }, null, _instanceExtraInitializers);
85
- if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
86
- }
87
- db = (__runInitializers(this, _instanceExtraInitializers), null);
88
- dbName;
89
- dbPromise;
90
- constructor(dbName) {
91
- this.dbName = dbName;
92
- this.dbPromise = deferred();
93
- if (this.dbName) {
94
- this.initDB();
95
- }
96
- }
97
- async initDB() {
98
- if (!this.dbName)
99
- return;
100
- const request = indexedDB.open(this.dbName, DB_VERSION);
101
- request.onerror = () => this.dbPromise.reject(request.error);
102
- request.onsuccess = () => {
103
- this.db = request.result;
104
- this.dbPromise.resolve(this.db);
105
- };
106
- request.onupgradeneeded = event => {
107
- const db = event.target.result;
108
- // Create stores
109
- if (!db.objectStoreNames.contains('snapshots')) {
110
- db.createObjectStore('snapshots', { keyPath: 'docId' });
111
- }
112
- if (!db.objectStoreNames.contains('committedChanges')) {
113
- db.createObjectStore('committedChanges', { keyPath: ['docId', 'rev'] });
114
- }
115
- if (!db.objectStoreNames.contains('pendingChanges')) {
116
- db.createObjectStore('pendingChanges', { keyPath: ['docId', 'rev'] });
117
- }
118
- if (!db.objectStoreNames.contains('docs')) {
119
- db.createObjectStore('docs', { keyPath: 'docId' });
120
- }
121
- };
122
- }
123
- getDB() {
124
- return this.dbPromise.promise;
125
- }
126
- /**
127
- * Set the name of the database, loads a new database connection.
128
- * @param dbName - The new name of the database.
129
- */
130
- setName(dbName) {
131
- this.dbName = dbName;
132
- if (this.db) {
133
- this.db.close();
134
- this.db = null;
135
- this.dbPromise = deferred();
136
- }
137
- this.initDB();
138
- }
139
- /**
140
- * Closes the database connection. After calling this method, the store
141
- * will no longer be usable. A new instance must be created to reopen
142
- * the database.
143
- */
144
- async close() {
145
- await this.dbPromise.promise;
146
- if (this.db) {
147
- this.db.close();
148
- this.db = null;
149
- this.dbPromise = deferred();
150
- this.dbPromise.resolve(null);
151
- }
152
- }
153
- async deleteDB() {
154
- if (!this.dbName)
155
- return;
156
- await this.close();
157
- await new Promise((resolve, reject) => {
158
- const request = indexedDB.deleteDatabase(this.dbName);
159
- request.onsuccess = () => resolve();
160
- request.onerror = () => reject(request.error);
161
- request.onblocked = () => reject(request.error);
162
- });
163
- }
164
- async transaction(storeNames, mode) {
165
- const db = await this.getDB();
166
- const tx = new IDBTransactionWrapper(db.transaction(storeNames, mode));
167
- const stores = storeNames.map(name => tx.getStore(name));
168
- return [tx, ...stores];
169
- }
170
- /**
171
- * Rebuilds a document snapshot + pending queue *without* loading
172
- * the full PatchesDoc into memory.
173
- *
174
- * 1. load the last snapshot (state + rev)
175
- * 2. load committedChanges[rev > snapshot.rev]
176
- * 3. load pendingChanges
177
- * 4. apply committed changes, rebase pending
178
- * 5. return { state, rev, changes: pending }
179
- */
180
- async getDoc(docId) {
181
- const [tx, docsStore, snapshots, committedChanges, pendingChanges] = await this.transaction(['docs', 'snapshots', 'committedChanges', 'pendingChanges'], 'readonly');
182
- const docMeta = await docsStore.get(docId);
183
- if (docMeta?.deleted) {
184
- await tx.complete();
185
- return undefined;
186
- }
187
- const snapshot = await snapshots.get(docId);
188
- const committed = await committedChanges.getAll([docId, snapshot?.rev ?? 0], [docId, Infinity]);
189
- const pending = await pendingChanges.getAll([docId, 0], [docId, Infinity]);
190
- if (!snapshot && !committed.length && !pending.length)
191
- return undefined;
192
- // Apply any committed changes to the snapshot state
193
- const state = applyChanges(snapshot?.state, committed);
194
- // Rebase pending changes if there are any committed changes received since their baseRev
195
- const lastCommitted = committed[committed.length - 1];
196
- const baseRev = pending[0]?.baseRev;
197
- if (lastCommitted && baseRev && baseRev < lastCommitted.rev) {
198
- const patch = committed
199
- .filter(change => change.rev > baseRev)
200
- .map(change => change.ops)
201
- .flat();
202
- const offset = lastCommitted.rev - baseRev;
203
- pending.forEach(change => {
204
- change.rev += offset;
205
- change.ops = transformPatch(state, patch, change.ops);
206
- });
207
- }
208
- await tx.complete();
209
- return {
210
- state,
211
- rev: committed[committed.length - 1]?.rev ?? snapshot?.rev ?? 0,
212
- changes: pending,
213
- };
214
- }
215
- /**
216
- * Completely remove all data for this docId and mark it as deleted (tombstone).
217
- */
218
- async deleteDoc(docId) {
219
- const [tx, snapshots, committedChanges, pendingChanges, docsStore] = await this.transaction(['snapshots', 'committedChanges', 'pendingChanges', 'docs'], 'readwrite');
220
- const docMeta = (await docsStore.get(docId)) ?? { docId, committedRev: 0 };
221
- await docsStore.put({ ...docMeta, deleted: true });
222
- await Promise.all([
223
- snapshots.delete(docId),
224
- committedChanges.delete([docId, 0], [docId, Infinity]),
225
- pendingChanges.delete([docId, 0], [docId, Infinity]),
226
- ]);
227
- await tx.complete();
228
- }
229
- /**
230
- * Confirm the deletion of a document.
231
- * @param docId - The ID of the document to delete.
232
- */
233
- async confirmDeleteDoc(docId) {
234
- const [tx, docsStore] = await this.transaction(['docs'], 'readwrite');
235
- await docsStore.delete(docId);
236
- await tx.complete();
237
- }
238
- /**
239
- * Save a document's state to the store.
240
- * @param docId - The ID of the document to save.
241
- * @param docState - The state of the document to save.
242
- */
243
- async saveDoc(docId, docState) {
244
- const [tx, snapshots, committedChanges, pendingChanges, docsStore] = await this.transaction(['snapshots', 'committedChanges', 'pendingChanges', 'docs'], 'readwrite');
245
- const { rev, state } = docState;
246
- await Promise.all([
247
- docsStore.put({ docId, committedRev: rev }),
248
- snapshots.put({ docId, state, rev }),
249
- committedChanges.delete([docId, 0], [docId, Infinity]),
250
- pendingChanges.delete([docId, 0], [docId, Infinity]),
251
- ]);
252
- await tx.complete();
253
- }
254
- /**
255
- * Append an array of local changes to the pending queue.
256
- * Called *before* you attempt to send them to the server.
257
- */
258
- async savePendingChanges(docId, changes) {
259
- const [tx, pendingChanges, docsStore] = await this.transaction(['pendingChanges', 'docs'], 'readwrite');
260
- let docMeta = await docsStore.get(docId);
261
- if (!docMeta) {
262
- docMeta = { docId, committedRev: 0 };
263
- await docsStore.put(docMeta);
264
- }
265
- else if (docMeta.deleted) {
266
- delete docMeta.deleted;
267
- await docsStore.put(docMeta);
268
- console.warn(`Revived document ${docId} by saving pending changes.`);
269
- }
270
- await Promise.all(changes.map(change => pendingChanges.put({ ...change, docId })));
271
- await tx.complete();
272
- }
273
- /**
274
- * Read back all pending changes for this docId (in order).
275
- * @param docId - The ID of the document to get the pending changes for.
276
- * @returns The pending changes.
277
- */
278
- async getPendingChanges(docId) {
279
- const [tx, pendingChanges] = await this.transaction(['pendingChanges'], 'readonly');
280
- const result = await pendingChanges.getAll([docId, 0], [docId, Infinity]);
281
- await tx.complete();
282
- return result;
283
- }
284
- /**
285
- * Replace all pending changes for a document (used after rebasing).
286
- * @param docId - The ID of the document to replace the pending changes for.
287
- * @param changes - The changes to replace the pending changes with.
288
- */
289
- async replacePendingChanges(docId, changes) {
290
- const [tx, pendingChanges, docsStore] = await this.transaction(['pendingChanges', 'docs'], 'readwrite');
291
- // Ensure the document is tracked
292
- let docMeta = await docsStore.get(docId);
293
- if (!docMeta) {
294
- docMeta = { docId, committedRev: 0 };
295
- await docsStore.put(docMeta);
296
- }
297
- else if (docMeta.deleted) {
298
- delete docMeta.deleted;
299
- await docsStore.put(docMeta);
300
- console.warn(`Revived document ${docId} by replacing pending changes.`);
301
- }
302
- // Remove all existing pending changes and add the new ones
303
- await pendingChanges.delete([docId, 0], [docId, Infinity]);
304
- await Promise.all(changes.map(change => pendingChanges.put({ ...change, docId })));
305
- await tx.complete();
306
- }
307
- // ─── Committed Changes ─────────────────────────────────────────────────────
308
- /**
309
- * Store server‐confirmed changes. Will:
310
- * - persist them in the committedChanges store
311
- * - remove any pending changes whose rev falls within `sentPendingRange`
312
- * - optionally compact a new snapshot after N changes (hidden internally)
313
- * @param docId - The ID of the document to save the changes for
314
- * @param changes - The changes to save
315
- * @param sentPendingRange - The range of pending changes to remove, *must* be provided after receiving the changes
316
- * from the server in response to a patchesDoc request.
317
- */
318
- async saveCommittedChanges(docId, changes, sentPendingRange) {
319
- const [tx, committedChanges, pendingChanges, snapshots, docsStore] = await this.transaction(['committedChanges', 'pendingChanges', 'snapshots', 'docs'], 'readwrite');
320
- // Save committed changes
321
- await Promise.all(changes.map(change => committedChanges.put({ ...change, docId })));
322
- // Remove pending changes if range provided
323
- if (sentPendingRange) {
324
- await pendingChanges.delete([docId, sentPendingRange[0]], [docId, sentPendingRange[1]]);
325
- }
326
- // Check if we should create a snapshot
327
- const count = await committedChanges.count([docId, 0], [docId, Infinity]);
328
- if (count >= SNAPSHOT_INTERVAL) {
329
- // Update the snapshot. A snapshot will not be updated if there are pending changes based on revisions older than
330
- // the latest committed change until those pending changes are committed.
331
- const [snapshot, committed, firstPending] = await Promise.all([
332
- snapshots.get(docId),
333
- committedChanges.getAll([docId, 0], [docId, Infinity], SNAPSHOT_INTERVAL),
334
- pendingChanges.getFirstFromCursor([docId, 0], [docId, Infinity]),
335
- ]);
336
- // Update the snapshot
337
- const lastRev = committed[committed.length - 1]?.rev;
338
- if (!firstPending?.baseRev || firstPending?.baseRev >= lastRev) {
339
- const state = applyChanges(snapshot?.state, committed);
340
- await Promise.all([
341
- snapshots.put({
342
- docId,
343
- rev: lastRev,
344
- state,
345
- }),
346
- committedChanges.delete([docId, 0], [docId, lastRev]),
347
- ]);
348
- }
349
- }
350
- // Update committedRev in the docs store if changes were saved
351
- const lastCommittedRev = changes.at(-1)?.rev;
352
- if (lastCommittedRev !== undefined) {
353
- const docMeta = (await docsStore.get(docId)) ?? { docId, committedRev: 0 };
354
- if (lastCommittedRev > docMeta.committedRev) {
355
- await docsStore.put({ ...docMeta, committedRev: lastCommittedRev, deleted: undefined });
356
- }
357
- }
358
- await tx.complete();
359
- }
360
- /**
361
- * List all documents in the store.
362
- * @param includeDeleted - Whether to include deleted documents.
363
- * @returns The list of documents.
364
- */
365
- async listDocs(includeDeleted = false) {
366
- const [tx, docsStore] = await this.transaction(['docs'], 'readonly');
367
- const allDocs = await docsStore.getAll();
368
- await tx.complete();
369
- return includeDeleted ? allDocs : allDocs.filter(doc => !doc.deleted);
370
- }
371
- /**
372
- * Track a document.
373
- * @param docIds - The IDs of the documents to track.
374
- */
375
- async trackDocs(docIds) {
376
- const [tx, docsStore] = await this.transaction(['docs'], 'readwrite');
377
- await Promise.all(docIds.map(async (docId) => {
378
- const existing = await docsStore.get(docId);
379
- if (existing) {
380
- // If exists but deleted, undelete it
381
- if (existing.deleted) {
382
- await docsStore.put({ ...existing, deleted: undefined });
383
- }
384
- // Otherwise, it's already tracked and not deleted, do nothing
385
- }
386
- else {
387
- // If doesn't exist, add it
388
- await docsStore.put({ docId, committedRev: 0 });
389
- }
390
- }));
391
- await tx.complete();
392
- }
393
- /**
394
- * Untrack a document.
395
- * @param docIds - The IDs of the documents to untrack.
396
- */
397
- async untrackDocs(docIds) {
398
- const [tx, docsStore, snapshots, committedChanges, pendingChanges] = await this.transaction(['docs', 'snapshots', 'committedChanges', 'pendingChanges'], 'readwrite');
399
- await Promise.all(docIds.map(docId => {
400
- return Promise.all([
401
- docsStore.delete(docId),
402
- snapshots.delete(docId),
403
- committedChanges.delete([docId, 0], [docId, Infinity]),
404
- pendingChanges.delete([docId, 0], [docId, Infinity]),
405
- ]);
406
- }));
407
- await tx.complete();
408
- }
409
- /**
410
- * Tell me the last committed revision you have *and* the highest
411
- * rev of any change. Use these to drive:
412
- * - fetch changes: api.getChangesSince(docId, committedRev)
413
- * - build new patch: newChange.rev = pendingRev; baseRev = committedRev
414
- */
415
- async getLastRevs(docId) {
416
- const [tx, committedChanges, pendingChanges] = await this.transaction(['committedChanges', 'pendingChanges'], 'readonly');
417
- const [lastCommitted, lastPending] = await Promise.all([
418
- committedChanges.getLastFromCursor([docId, 0], [docId, Infinity]),
419
- pendingChanges.getLastFromCursor([docId, 0], [docId, Infinity]),
420
- ]);
421
- await tx.complete();
422
- return [lastCommitted?.rev ?? 0, lastPending?.rev ?? lastCommitted?.rev ?? 0];
423
- }
424
- };
425
- })();
426
- export { IndexedDBStore };
427
- class IDBTransactionWrapper {
428
- tx;
429
- promise;
430
- constructor(tx) {
431
- this.tx = tx;
432
- this.promise = new Promise((resolve, reject) => {
433
- tx.oncomplete = () => resolve();
434
- tx.onerror = () => reject(tx.error);
435
- });
436
- }
437
- getStore(name) {
438
- return new IDBStoreWrapper(this.tx.objectStore(name));
15
+ _getDoc_dec = [blockable], _deleteDoc_dec = [blockable], _confirmDeleteDoc_dec = [blockable], _saveDoc_dec = [blockable], _savePendingChanges_dec = [blockable], _getPendingChanges_dec = [blockable], _replacePendingChanges_dec = [blockable], _saveCommittedChanges_dec = [blockable], _getLastRevs_dec = [blockable];
16
+ class IndexedDBStore {
17
+ constructor(dbName) {
18
+ __runInitializers(_init, 5, this);
19
+ __publicField(this, "db", null);
20
+ __publicField(this, "dbName");
21
+ __publicField(this, "dbPromise");
22
+ this.dbName = dbName;
23
+ this.dbPromise = deferred();
24
+ if (this.dbName) {
25
+ this.initDB();
439
26
  }
440
- async complete() {
441
- return this.promise;
442
- }
443
- }
444
- class IDBStoreWrapper {
445
- store;
446
- constructor(store) {
447
- this.store = store;
27
+ }
28
+ async initDB() {
29
+ if (!this.dbName) return;
30
+ const request = indexedDB.open(this.dbName, DB_VERSION);
31
+ request.onerror = () => this.dbPromise.reject(request.error);
32
+ request.onsuccess = () => {
33
+ this.db = request.result;
34
+ this.dbPromise.resolve(this.db);
35
+ };
36
+ request.onupgradeneeded = (event) => {
37
+ const db = event.target.result;
38
+ if (!db.objectStoreNames.contains("snapshots")) {
39
+ db.createObjectStore("snapshots", { keyPath: "docId" });
40
+ }
41
+ if (!db.objectStoreNames.contains("committedChanges")) {
42
+ db.createObjectStore("committedChanges", { keyPath: ["docId", "rev"] });
43
+ }
44
+ if (!db.objectStoreNames.contains("pendingChanges")) {
45
+ db.createObjectStore("pendingChanges", { keyPath: ["docId", "rev"] });
46
+ }
47
+ if (!db.objectStoreNames.contains("docs")) {
48
+ db.createObjectStore("docs", { keyPath: "docId" });
49
+ }
50
+ };
51
+ }
52
+ getDB() {
53
+ return this.dbPromise.promise;
54
+ }
55
+ /**
56
+ * Set the name of the database, loads a new database connection.
57
+ * @param dbName - The new name of the database.
58
+ */
59
+ setName(dbName) {
60
+ this.dbName = dbName;
61
+ if (this.db) {
62
+ this.db.close();
63
+ this.db = null;
64
+ this.dbPromise = deferred();
448
65
  }
449
- createRange(lower, upper) {
450
- if (lower === undefined && upper === undefined)
451
- return undefined;
452
- return IDBKeyRange.bound(lower, upper);
66
+ this.initDB();
67
+ }
68
+ /**
69
+ * Closes the database connection. After calling this method, the store
70
+ * will no longer be usable. A new instance must be created to reopen
71
+ * the database.
72
+ */
73
+ async close() {
74
+ await this.dbPromise.promise;
75
+ if (this.db) {
76
+ this.db.close();
77
+ this.db = null;
78
+ this.dbPromise = deferred();
79
+ this.dbPromise.resolve(null);
453
80
  }
454
- async getAll(lower, upper, count) {
455
- return new Promise((resolve, reject) => {
456
- const request = this.store.getAll(this.createRange(lower, upper), count);
457
- request.onsuccess = () => resolve(request.result);
458
- request.onerror = () => reject(request.error);
459
- });
81
+ }
82
+ async deleteDB() {
83
+ if (!this.dbName) return;
84
+ await this.close();
85
+ await new Promise((resolve, reject) => {
86
+ const request = indexedDB.deleteDatabase(this.dbName);
87
+ request.onsuccess = () => resolve();
88
+ request.onerror = () => reject(request.error);
89
+ request.onblocked = () => reject(request.error);
90
+ });
91
+ }
92
+ async transaction(storeNames, mode) {
93
+ const db = await this.getDB();
94
+ const tx = new IDBTransactionWrapper(db.transaction(storeNames, mode));
95
+ const stores = storeNames.map((name) => tx.getStore(name));
96
+ return [tx, ...stores];
97
+ }
98
+ async getDoc(docId) {
99
+ const [tx, docsStore, snapshots, committedChanges, pendingChanges] = await this.transaction(
100
+ ["docs", "snapshots", "committedChanges", "pendingChanges"],
101
+ "readonly"
102
+ );
103
+ const docMeta = await docsStore.get(docId);
104
+ if (docMeta?.deleted) {
105
+ await tx.complete();
106
+ return void 0;
460
107
  }
461
- async get(key) {
462
- return new Promise((resolve, reject) => {
463
- const request = this.store.get(key);
464
- request.onsuccess = () => resolve(request.result);
465
- request.onerror = () => reject(request.error);
466
- });
108
+ const snapshot = await snapshots.get(docId);
109
+ const committed = await committedChanges.getAll([docId, snapshot?.rev ?? 0], [docId, Infinity]);
110
+ const pending = await pendingChanges.getAll([docId, 0], [docId, Infinity]);
111
+ if (!snapshot && !committed.length && !pending.length) return void 0;
112
+ const state = applyChanges(snapshot?.state, committed);
113
+ const lastCommitted = committed[committed.length - 1];
114
+ const baseRev = pending[0]?.baseRev;
115
+ if (lastCommitted && baseRev && baseRev < lastCommitted.rev) {
116
+ const patch = committed.filter((change) => change.rev > baseRev).map((change) => change.ops).flat();
117
+ const offset = lastCommitted.rev - baseRev;
118
+ pending.forEach((change) => {
119
+ change.rev += offset;
120
+ change.ops = transformPatch(state, patch, change.ops);
121
+ });
467
122
  }
468
- async put(value) {
469
- return new Promise((resolve, reject) => {
470
- const request = this.store.put(value);
471
- request.onsuccess = () => resolve(request.result);
472
- request.onerror = () => reject(request.error);
473
- });
123
+ await tx.complete();
124
+ return {
125
+ state,
126
+ rev: committed[committed.length - 1]?.rev ?? snapshot?.rev ?? 0,
127
+ changes: pending
128
+ };
129
+ }
130
+ async deleteDoc(docId) {
131
+ const [tx, snapshots, committedChanges, pendingChanges, docsStore] = await this.transaction(
132
+ ["snapshots", "committedChanges", "pendingChanges", "docs"],
133
+ "readwrite"
134
+ );
135
+ const docMeta = await docsStore.get(docId) ?? { docId, committedRev: 0 };
136
+ await docsStore.put({ ...docMeta, deleted: true });
137
+ await Promise.all([
138
+ snapshots.delete(docId),
139
+ committedChanges.delete([docId, 0], [docId, Infinity]),
140
+ pendingChanges.delete([docId, 0], [docId, Infinity])
141
+ ]);
142
+ await tx.complete();
143
+ }
144
+ async confirmDeleteDoc(docId) {
145
+ const [tx, docsStore] = await this.transaction(["docs"], "readwrite");
146
+ await docsStore.delete(docId);
147
+ await tx.complete();
148
+ }
149
+ async saveDoc(docId, docState) {
150
+ const [tx, snapshots, committedChanges, pendingChanges, docsStore] = await this.transaction(
151
+ ["snapshots", "committedChanges", "pendingChanges", "docs"],
152
+ "readwrite"
153
+ );
154
+ const { rev, state } = docState;
155
+ await Promise.all([
156
+ docsStore.put({ docId, committedRev: rev }),
157
+ snapshots.put({ docId, state, rev }),
158
+ committedChanges.delete([docId, 0], [docId, Infinity]),
159
+ pendingChanges.delete([docId, 0], [docId, Infinity])
160
+ ]);
161
+ await tx.complete();
162
+ }
163
+ async savePendingChanges(docId, changes) {
164
+ const [tx, pendingChanges, docsStore] = await this.transaction(["pendingChanges", "docs"], "readwrite");
165
+ let docMeta = await docsStore.get(docId);
166
+ if (!docMeta) {
167
+ docMeta = { docId, committedRev: 0 };
168
+ await docsStore.put(docMeta);
169
+ } else if (docMeta.deleted) {
170
+ delete docMeta.deleted;
171
+ await docsStore.put(docMeta);
172
+ console.warn(`Revived document ${docId} by saving pending changes.`);
474
173
  }
475
- async delete(keyOrLower, upper) {
476
- return new Promise((resolve, reject) => {
477
- const key = upper === undefined ? keyOrLower : this.createRange(keyOrLower, upper);
478
- const request = this.store.delete(key);
479
- request.onsuccess = () => resolve();
480
- request.onerror = () => reject(request.error);
481
- });
174
+ await Promise.all(changes.map((change) => pendingChanges.put({ ...change, docId })));
175
+ await tx.complete();
176
+ }
177
+ async getPendingChanges(docId) {
178
+ const [tx, pendingChanges] = await this.transaction(["pendingChanges"], "readonly");
179
+ const result = await pendingChanges.getAll([docId, 0], [docId, Infinity]);
180
+ await tx.complete();
181
+ return result;
182
+ }
183
+ async replacePendingChanges(docId, changes) {
184
+ const [tx, pendingChanges, docsStore] = await this.transaction(["pendingChanges", "docs"], "readwrite");
185
+ let docMeta = await docsStore.get(docId);
186
+ if (!docMeta) {
187
+ docMeta = { docId, committedRev: 0 };
188
+ await docsStore.put(docMeta);
189
+ } else if (docMeta.deleted) {
190
+ delete docMeta.deleted;
191
+ await docsStore.put(docMeta);
192
+ console.warn(`Revived document ${docId} by replacing pending changes.`);
482
193
  }
483
- async count(lower, upper) {
484
- return new Promise((resolve, reject) => {
485
- const request = this.store.count(this.createRange(lower, upper));
486
- request.onsuccess = () => resolve(request.result);
487
- request.onerror = () => reject(request.error);
488
- });
194
+ await pendingChanges.delete([docId, 0], [docId, Infinity]);
195
+ await Promise.all(changes.map((change) => pendingChanges.put({ ...change, docId })));
196
+ await tx.complete();
197
+ }
198
+ async saveCommittedChanges(docId, changes, sentPendingRange) {
199
+ const [tx, committedChanges, pendingChanges, snapshots, docsStore] = await this.transaction(
200
+ ["committedChanges", "pendingChanges", "snapshots", "docs"],
201
+ "readwrite"
202
+ );
203
+ await Promise.all(changes.map((change) => committedChanges.put({ ...change, docId })));
204
+ if (sentPendingRange) {
205
+ await pendingChanges.delete([docId, sentPendingRange[0]], [docId, sentPendingRange[1]]);
489
206
  }
490
- async getFirstFromCursor(lower, upper) {
491
- return new Promise((resolve, reject) => {
492
- const request = this.store.openCursor(this.createRange(lower, upper));
493
- request.onsuccess = () => resolve(request.result?.value);
494
- request.onerror = () => reject(request.error);
495
- });
207
+ const count = await committedChanges.count([docId, 0], [docId, Infinity]);
208
+ if (count >= SNAPSHOT_INTERVAL) {
209
+ const [snapshot, committed, firstPending] = await Promise.all([
210
+ snapshots.get(docId),
211
+ committedChanges.getAll([docId, 0], [docId, Infinity], SNAPSHOT_INTERVAL),
212
+ pendingChanges.getFirstFromCursor([docId, 0], [docId, Infinity])
213
+ ]);
214
+ const lastRev = committed[committed.length - 1]?.rev;
215
+ if (!firstPending?.baseRev || firstPending?.baseRev >= lastRev) {
216
+ const state = applyChanges(snapshot?.state, committed);
217
+ await Promise.all([
218
+ snapshots.put({
219
+ docId,
220
+ rev: lastRev,
221
+ state
222
+ }),
223
+ committedChanges.delete([docId, 0], [docId, lastRev])
224
+ ]);
225
+ }
496
226
  }
497
- async getLastFromCursor(lower, upper) {
498
- return new Promise((resolve, reject) => {
499
- const request = this.store.openCursor(this.createRange(lower, upper), 'prev');
500
- request.onsuccess = () => resolve(request.result?.value);
501
- request.onerror = () => reject(request.error);
502
- });
227
+ const lastCommittedRev = changes.at(-1)?.rev;
228
+ if (lastCommittedRev !== void 0) {
229
+ const docMeta = await docsStore.get(docId) ?? { docId, committedRev: 0 };
230
+ if (lastCommittedRev > docMeta.committedRev) {
231
+ await docsStore.put({ ...docMeta, committedRev: lastCommittedRev, deleted: void 0 });
232
+ }
503
233
  }
234
+ await tx.complete();
235
+ }
236
+ /**
237
+ * List all documents in the store.
238
+ * @param includeDeleted - Whether to include deleted documents.
239
+ * @returns The list of documents.
240
+ */
241
+ async listDocs(includeDeleted = false) {
242
+ const [tx, docsStore] = await this.transaction(["docs"], "readonly");
243
+ const allDocs = await docsStore.getAll();
244
+ await tx.complete();
245
+ return includeDeleted ? allDocs : allDocs.filter((doc) => !doc.deleted);
246
+ }
247
+ /**
248
+ * Track a document.
249
+ * @param docIds - The IDs of the documents to track.
250
+ */
251
+ async trackDocs(docIds) {
252
+ const [tx, docsStore] = await this.transaction(["docs"], "readwrite");
253
+ await Promise.all(
254
+ docIds.map(async (docId) => {
255
+ const existing = await docsStore.get(docId);
256
+ if (existing) {
257
+ if (existing.deleted) {
258
+ await docsStore.put({ ...existing, deleted: void 0 });
259
+ }
260
+ } else {
261
+ await docsStore.put({ docId, committedRev: 0 });
262
+ }
263
+ })
264
+ );
265
+ await tx.complete();
266
+ }
267
+ /**
268
+ * Untrack a document.
269
+ * @param docIds - The IDs of the documents to untrack.
270
+ */
271
+ async untrackDocs(docIds) {
272
+ const [tx, docsStore, snapshots, committedChanges, pendingChanges] = await this.transaction(
273
+ ["docs", "snapshots", "committedChanges", "pendingChanges"],
274
+ "readwrite"
275
+ );
276
+ await Promise.all(
277
+ docIds.map((docId) => {
278
+ return Promise.all([
279
+ docsStore.delete(docId),
280
+ snapshots.delete(docId),
281
+ committedChanges.delete([docId, 0], [docId, Infinity]),
282
+ pendingChanges.delete([docId, 0], [docId, Infinity])
283
+ ]);
284
+ })
285
+ );
286
+ await tx.complete();
287
+ }
288
+ async getLastRevs(docId) {
289
+ const [tx, committedChanges, pendingChanges] = await this.transaction(
290
+ ["committedChanges", "pendingChanges"],
291
+ "readonly"
292
+ );
293
+ const [lastCommitted, lastPending] = await Promise.all([
294
+ committedChanges.getLastFromCursor([docId, 0], [docId, Infinity]),
295
+ pendingChanges.getLastFromCursor([docId, 0], [docId, Infinity])
296
+ ]);
297
+ await tx.complete();
298
+ return [lastCommitted?.rev ?? 0, lastPending?.rev ?? lastCommitted?.rev ?? 0];
299
+ }
504
300
  }
301
+ _init = __decoratorStart(null);
302
+ __decorateElement(_init, 1, "getDoc", _getDoc_dec, IndexedDBStore);
303
+ __decorateElement(_init, 1, "deleteDoc", _deleteDoc_dec, IndexedDBStore);
304
+ __decorateElement(_init, 1, "confirmDeleteDoc", _confirmDeleteDoc_dec, IndexedDBStore);
305
+ __decorateElement(_init, 1, "saveDoc", _saveDoc_dec, IndexedDBStore);
306
+ __decorateElement(_init, 1, "savePendingChanges", _savePendingChanges_dec, IndexedDBStore);
307
+ __decorateElement(_init, 1, "getPendingChanges", _getPendingChanges_dec, IndexedDBStore);
308
+ __decorateElement(_init, 1, "replacePendingChanges", _replacePendingChanges_dec, IndexedDBStore);
309
+ __decorateElement(_init, 1, "saveCommittedChanges", _saveCommittedChanges_dec, IndexedDBStore);
310
+ __decorateElement(_init, 1, "getLastRevs", _getLastRevs_dec, IndexedDBStore);
311
+ __decoratorMetadata(_init, IndexedDBStore);
312
+ class IDBTransactionWrapper {
313
+ tx;
314
+ promise;
315
+ constructor(tx) {
316
+ this.tx = tx;
317
+ this.promise = new Promise((resolve, reject) => {
318
+ tx.oncomplete = () => resolve();
319
+ tx.onerror = () => reject(tx.error);
320
+ });
321
+ }
322
+ getStore(name) {
323
+ return new IDBStoreWrapper(this.tx.objectStore(name));
324
+ }
325
+ async complete() {
326
+ return this.promise;
327
+ }
328
+ }
329
+ class IDBStoreWrapper {
330
+ store;
331
+ constructor(store) {
332
+ this.store = store;
333
+ }
334
+ createRange(lower, upper) {
335
+ if (lower === void 0 && upper === void 0) return void 0;
336
+ return IDBKeyRange.bound(lower, upper);
337
+ }
338
+ async getAll(lower, upper, count) {
339
+ return new Promise((resolve, reject) => {
340
+ const request = this.store.getAll(this.createRange(lower, upper), count);
341
+ request.onsuccess = () => resolve(request.result);
342
+ request.onerror = () => reject(request.error);
343
+ });
344
+ }
345
+ async get(key) {
346
+ return new Promise((resolve, reject) => {
347
+ const request = this.store.get(key);
348
+ request.onsuccess = () => resolve(request.result);
349
+ request.onerror = () => reject(request.error);
350
+ });
351
+ }
352
+ async put(value) {
353
+ return new Promise((resolve, reject) => {
354
+ const request = this.store.put(value);
355
+ request.onsuccess = () => resolve(request.result);
356
+ request.onerror = () => reject(request.error);
357
+ });
358
+ }
359
+ async delete(keyOrLower, upper) {
360
+ return new Promise((resolve, reject) => {
361
+ const key = upper === void 0 ? keyOrLower : this.createRange(keyOrLower, upper);
362
+ const request = this.store.delete(key);
363
+ request.onsuccess = () => resolve();
364
+ request.onerror = () => reject(request.error);
365
+ });
366
+ }
367
+ async count(lower, upper) {
368
+ return new Promise((resolve, reject) => {
369
+ const request = this.store.count(this.createRange(lower, upper));
370
+ request.onsuccess = () => resolve(request.result);
371
+ request.onerror = () => reject(request.error);
372
+ });
373
+ }
374
+ async getFirstFromCursor(lower, upper) {
375
+ return new Promise((resolve, reject) => {
376
+ const request = this.store.openCursor(this.createRange(lower, upper));
377
+ request.onsuccess = () => resolve(request.result?.value);
378
+ request.onerror = () => reject(request.error);
379
+ });
380
+ }
381
+ async getLastFromCursor(lower, upper) {
382
+ return new Promise((resolve, reject) => {
383
+ const request = this.store.openCursor(this.createRange(lower, upper), "prev");
384
+ request.onsuccess = () => resolve(request.result?.value);
385
+ request.onerror = () => reject(request.error);
386
+ });
387
+ }
388
+ }
389
+ export {
390
+ IndexedDBStore
391
+ };