@interncom/diplomatic 0.0.11 → 0.0.13
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/dist/idbStore.d.ts +24 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.mjs +370 -38
- package/dist/localStorageStore.d.ts +10 -3
- package/dist/memoryStore.d.ts +24 -0
- package/dist/types.d.ts +8 -33
- package/package.json +8 -5
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { IClientStateStore } from "./types";
|
|
2
|
+
declare class IDBStore implements IClientStateStore {
|
|
3
|
+
seed?: Uint8Array;
|
|
4
|
+
hostURL?: string;
|
|
5
|
+
hostID?: string;
|
|
6
|
+
wipe(): Promise<void>;
|
|
7
|
+
getSeed(): Promise<Uint8Array | undefined>;
|
|
8
|
+
setSeed(seed: Uint8Array): Promise<void>;
|
|
9
|
+
getHostURL(): Promise<string | undefined>;
|
|
10
|
+
setHostURL(url: string): Promise<void>;
|
|
11
|
+
getHostID(): Promise<string | undefined>;
|
|
12
|
+
setHostID(id: string): Promise<void>;
|
|
13
|
+
uploadQueue: Map<string, Uint8Array>;
|
|
14
|
+
enqueueUpload: (sha256: string, cipherOp: Uint8Array) => Promise<void>;
|
|
15
|
+
dequeueUpload: (sha256: string) => Promise<void>;
|
|
16
|
+
peekUpload: (sha256: string) => Promise<Uint8Array | undefined>;
|
|
17
|
+
listUploads: () => Promise<string[]>;
|
|
18
|
+
downloadQueue: Set<string>;
|
|
19
|
+
enqueueDownload: (path: string) => Promise<void>;
|
|
20
|
+
dequeueDownload: (path: string) => Promise<void>;
|
|
21
|
+
listDownloads: () => Promise<string[]>;
|
|
22
|
+
}
|
|
23
|
+
export declare const idbStore: IDBStore;
|
|
24
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { useClientState } from "./useClient";
|
|
2
2
|
import { StateManager, useStateWatcher } from './state';
|
|
3
3
|
import { localStorageStore } from "./localStorageStore";
|
|
4
|
+
import { idbStore } from "./idbStore";
|
|
4
5
|
import DiplomaticClient from "./client";
|
|
5
6
|
import libsodiumCrypto from "./crypto";
|
|
6
7
|
import { btoh, htob } from "./shared/lib";
|
|
7
8
|
import { type IOp, Verb } from "./shared/types";
|
|
8
|
-
export { useClientState, StateManager, useStateWatcher, localStorageStore, DiplomaticClient, libsodiumCrypto, btoh, htob, Verb, };
|
|
9
|
+
export { useClientState, StateManager, useStateWatcher, localStorageStore, idbStore, DiplomaticClient, libsodiumCrypto, btoh, htob, Verb, };
|
|
9
10
|
export type { IOp, };
|
package/dist/index.mjs
CHANGED
|
@@ -80,31 +80,6 @@ function useStateWatcher(mgr, opType, callback) {
|
|
|
80
80
|
return val;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
// src/queue.ts
|
|
84
|
-
var Queue = class {
|
|
85
|
-
map;
|
|
86
|
-
constructor() {
|
|
87
|
-
this.map = /* @__PURE__ */ new Map();
|
|
88
|
-
}
|
|
89
|
-
async enqueue(key, value) {
|
|
90
|
-
this.map.set(key, value);
|
|
91
|
-
}
|
|
92
|
-
async peek(key) {
|
|
93
|
-
return this.map.get(key);
|
|
94
|
-
}
|
|
95
|
-
async entries() {
|
|
96
|
-
return Array.from(this.map.entries());
|
|
97
|
-
}
|
|
98
|
-
async dequeue(key) {
|
|
99
|
-
const value = this.map.get(key);
|
|
100
|
-
this.map.delete(key);
|
|
101
|
-
return value;
|
|
102
|
-
}
|
|
103
|
-
async size() {
|
|
104
|
-
return this.map.size;
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
|
|
108
83
|
// ../shared/lib.ts
|
|
109
84
|
function btoh(bytes) {
|
|
110
85
|
const hex = Array.from(bytes).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
@@ -126,6 +101,9 @@ var seedKey = "seedHex";
|
|
|
126
101
|
var hostURLKey = "hostURL";
|
|
127
102
|
var hostIDKey = "hostID";
|
|
128
103
|
var LocalStorageStore = class {
|
|
104
|
+
async wipe() {
|
|
105
|
+
localStorage.clear();
|
|
106
|
+
}
|
|
129
107
|
async getSeed() {
|
|
130
108
|
const storedSeed = localStorage.getItem(seedKey);
|
|
131
109
|
if (storedSeed) {
|
|
@@ -149,11 +127,366 @@ var LocalStorageStore = class {
|
|
|
149
127
|
async setHostID(id) {
|
|
150
128
|
return localStorage.setItem(hostIDKey, id);
|
|
151
129
|
}
|
|
152
|
-
|
|
153
|
-
|
|
130
|
+
uploadQueue = /* @__PURE__ */ new Map();
|
|
131
|
+
enqueueUpload = async (sha256, cipherOp) => {
|
|
132
|
+
this.uploadQueue.set(sha256, cipherOp);
|
|
133
|
+
};
|
|
134
|
+
dequeueUpload = async (sha256) => {
|
|
135
|
+
this.uploadQueue.delete(sha256);
|
|
136
|
+
};
|
|
137
|
+
peekUpload = async (sha256) => {
|
|
138
|
+
return this.uploadQueue.get(sha256);
|
|
139
|
+
};
|
|
140
|
+
listUploads = async () => {
|
|
141
|
+
return Array.from(this.uploadQueue.keys());
|
|
142
|
+
};
|
|
143
|
+
downloadQueue = /* @__PURE__ */ new Set();
|
|
144
|
+
enqueueDownload = async (path) => {
|
|
145
|
+
this.downloadQueue.add(path);
|
|
146
|
+
};
|
|
147
|
+
dequeueDownload = async (path) => {
|
|
148
|
+
this.downloadQueue.delete(path);
|
|
149
|
+
};
|
|
150
|
+
listDownloads = async () => {
|
|
151
|
+
return Array.from(this.downloadQueue.keys());
|
|
152
|
+
};
|
|
154
153
|
};
|
|
155
154
|
var localStorageStore = new LocalStorageStore();
|
|
156
155
|
|
|
156
|
+
// node_modules/idb/build/index.js
|
|
157
|
+
var instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c);
|
|
158
|
+
var idbProxyableTypes;
|
|
159
|
+
var cursorAdvanceMethods;
|
|
160
|
+
function getIdbProxyableTypes() {
|
|
161
|
+
return idbProxyableTypes || (idbProxyableTypes = [
|
|
162
|
+
IDBDatabase,
|
|
163
|
+
IDBObjectStore,
|
|
164
|
+
IDBIndex,
|
|
165
|
+
IDBCursor,
|
|
166
|
+
IDBTransaction
|
|
167
|
+
]);
|
|
168
|
+
}
|
|
169
|
+
function getCursorAdvanceMethods() {
|
|
170
|
+
return cursorAdvanceMethods || (cursorAdvanceMethods = [
|
|
171
|
+
IDBCursor.prototype.advance,
|
|
172
|
+
IDBCursor.prototype.continue,
|
|
173
|
+
IDBCursor.prototype.continuePrimaryKey
|
|
174
|
+
]);
|
|
175
|
+
}
|
|
176
|
+
var transactionDoneMap = /* @__PURE__ */ new WeakMap();
|
|
177
|
+
var transformCache = /* @__PURE__ */ new WeakMap();
|
|
178
|
+
var reverseTransformCache = /* @__PURE__ */ new WeakMap();
|
|
179
|
+
function promisifyRequest(request) {
|
|
180
|
+
const promise = new Promise((resolve, reject) => {
|
|
181
|
+
const unlisten = () => {
|
|
182
|
+
request.removeEventListener("success", success);
|
|
183
|
+
request.removeEventListener("error", error);
|
|
184
|
+
};
|
|
185
|
+
const success = () => {
|
|
186
|
+
resolve(wrap(request.result));
|
|
187
|
+
unlisten();
|
|
188
|
+
};
|
|
189
|
+
const error = () => {
|
|
190
|
+
reject(request.error);
|
|
191
|
+
unlisten();
|
|
192
|
+
};
|
|
193
|
+
request.addEventListener("success", success);
|
|
194
|
+
request.addEventListener("error", error);
|
|
195
|
+
});
|
|
196
|
+
reverseTransformCache.set(promise, request);
|
|
197
|
+
return promise;
|
|
198
|
+
}
|
|
199
|
+
function cacheDonePromiseForTransaction(tx) {
|
|
200
|
+
if (transactionDoneMap.has(tx))
|
|
201
|
+
return;
|
|
202
|
+
const done = new Promise((resolve, reject) => {
|
|
203
|
+
const unlisten = () => {
|
|
204
|
+
tx.removeEventListener("complete", complete);
|
|
205
|
+
tx.removeEventListener("error", error);
|
|
206
|
+
tx.removeEventListener("abort", error);
|
|
207
|
+
};
|
|
208
|
+
const complete = () => {
|
|
209
|
+
resolve();
|
|
210
|
+
unlisten();
|
|
211
|
+
};
|
|
212
|
+
const error = () => {
|
|
213
|
+
reject(tx.error || new DOMException("AbortError", "AbortError"));
|
|
214
|
+
unlisten();
|
|
215
|
+
};
|
|
216
|
+
tx.addEventListener("complete", complete);
|
|
217
|
+
tx.addEventListener("error", error);
|
|
218
|
+
tx.addEventListener("abort", error);
|
|
219
|
+
});
|
|
220
|
+
transactionDoneMap.set(tx, done);
|
|
221
|
+
}
|
|
222
|
+
var idbProxyTraps = {
|
|
223
|
+
get(target, prop, receiver) {
|
|
224
|
+
if (target instanceof IDBTransaction) {
|
|
225
|
+
if (prop === "done")
|
|
226
|
+
return transactionDoneMap.get(target);
|
|
227
|
+
if (prop === "store") {
|
|
228
|
+
return receiver.objectStoreNames[1] ? void 0 : receiver.objectStore(receiver.objectStoreNames[0]);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return wrap(target[prop]);
|
|
232
|
+
},
|
|
233
|
+
set(target, prop, value) {
|
|
234
|
+
target[prop] = value;
|
|
235
|
+
return true;
|
|
236
|
+
},
|
|
237
|
+
has(target, prop) {
|
|
238
|
+
if (target instanceof IDBTransaction && (prop === "done" || prop === "store")) {
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
return prop in target;
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
function replaceTraps(callback) {
|
|
245
|
+
idbProxyTraps = callback(idbProxyTraps);
|
|
246
|
+
}
|
|
247
|
+
function wrapFunction(func) {
|
|
248
|
+
if (getCursorAdvanceMethods().includes(func)) {
|
|
249
|
+
return function(...args) {
|
|
250
|
+
func.apply(unwrap(this), args);
|
|
251
|
+
return wrap(this.request);
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
return function(...args) {
|
|
255
|
+
return wrap(func.apply(unwrap(this), args));
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
function transformCachableValue(value) {
|
|
259
|
+
if (typeof value === "function")
|
|
260
|
+
return wrapFunction(value);
|
|
261
|
+
if (value instanceof IDBTransaction)
|
|
262
|
+
cacheDonePromiseForTransaction(value);
|
|
263
|
+
if (instanceOfAny(value, getIdbProxyableTypes()))
|
|
264
|
+
return new Proxy(value, idbProxyTraps);
|
|
265
|
+
return value;
|
|
266
|
+
}
|
|
267
|
+
function wrap(value) {
|
|
268
|
+
if (value instanceof IDBRequest)
|
|
269
|
+
return promisifyRequest(value);
|
|
270
|
+
if (transformCache.has(value))
|
|
271
|
+
return transformCache.get(value);
|
|
272
|
+
const newValue = transformCachableValue(value);
|
|
273
|
+
if (newValue !== value) {
|
|
274
|
+
transformCache.set(value, newValue);
|
|
275
|
+
reverseTransformCache.set(newValue, value);
|
|
276
|
+
}
|
|
277
|
+
return newValue;
|
|
278
|
+
}
|
|
279
|
+
var unwrap = (value) => reverseTransformCache.get(value);
|
|
280
|
+
function openDB(name, version, { blocked, upgrade, blocking, terminated } = {}) {
|
|
281
|
+
const request = indexedDB.open(name, version);
|
|
282
|
+
const openPromise = wrap(request);
|
|
283
|
+
if (upgrade) {
|
|
284
|
+
request.addEventListener("upgradeneeded", (event) => {
|
|
285
|
+
upgrade(wrap(request.result), event.oldVersion, event.newVersion, wrap(request.transaction), event);
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
if (blocked) {
|
|
289
|
+
request.addEventListener("blocked", (event) => blocked(
|
|
290
|
+
// Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405
|
|
291
|
+
event.oldVersion,
|
|
292
|
+
event.newVersion,
|
|
293
|
+
event
|
|
294
|
+
));
|
|
295
|
+
}
|
|
296
|
+
openPromise.then((db) => {
|
|
297
|
+
if (terminated)
|
|
298
|
+
db.addEventListener("close", () => terminated());
|
|
299
|
+
if (blocking) {
|
|
300
|
+
db.addEventListener("versionchange", (event) => blocking(event.oldVersion, event.newVersion, event));
|
|
301
|
+
}
|
|
302
|
+
}).catch(() => {
|
|
303
|
+
});
|
|
304
|
+
return openPromise;
|
|
305
|
+
}
|
|
306
|
+
function deleteDB(name, { blocked } = {}) {
|
|
307
|
+
const request = indexedDB.deleteDatabase(name);
|
|
308
|
+
if (blocked) {
|
|
309
|
+
request.addEventListener("blocked", (event) => blocked(
|
|
310
|
+
// Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405
|
|
311
|
+
event.oldVersion,
|
|
312
|
+
event
|
|
313
|
+
));
|
|
314
|
+
}
|
|
315
|
+
return wrap(request).then(() => void 0);
|
|
316
|
+
}
|
|
317
|
+
var readMethods = ["get", "getKey", "getAll", "getAllKeys", "count"];
|
|
318
|
+
var writeMethods = ["put", "add", "delete", "clear"];
|
|
319
|
+
var cachedMethods = /* @__PURE__ */ new Map();
|
|
320
|
+
function getMethod(target, prop) {
|
|
321
|
+
if (!(target instanceof IDBDatabase && !(prop in target) && typeof prop === "string")) {
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
if (cachedMethods.get(prop))
|
|
325
|
+
return cachedMethods.get(prop);
|
|
326
|
+
const targetFuncName = prop.replace(/FromIndex$/, "");
|
|
327
|
+
const useIndex = prop !== targetFuncName;
|
|
328
|
+
const isWrite = writeMethods.includes(targetFuncName);
|
|
329
|
+
if (
|
|
330
|
+
// Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.
|
|
331
|
+
!(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) || !(isWrite || readMethods.includes(targetFuncName))
|
|
332
|
+
) {
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
const method = async function(storeName, ...args) {
|
|
336
|
+
const tx = this.transaction(storeName, isWrite ? "readwrite" : "readonly");
|
|
337
|
+
let target2 = tx.store;
|
|
338
|
+
if (useIndex)
|
|
339
|
+
target2 = target2.index(args.shift());
|
|
340
|
+
return (await Promise.all([
|
|
341
|
+
target2[targetFuncName](...args),
|
|
342
|
+
isWrite && tx.done
|
|
343
|
+
]))[0];
|
|
344
|
+
};
|
|
345
|
+
cachedMethods.set(prop, method);
|
|
346
|
+
return method;
|
|
347
|
+
}
|
|
348
|
+
replaceTraps((oldTraps) => ({
|
|
349
|
+
...oldTraps,
|
|
350
|
+
get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),
|
|
351
|
+
has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop)
|
|
352
|
+
}));
|
|
353
|
+
var advanceMethodProps = ["continue", "continuePrimaryKey", "advance"];
|
|
354
|
+
var methodMap = {};
|
|
355
|
+
var advanceResults = /* @__PURE__ */ new WeakMap();
|
|
356
|
+
var ittrProxiedCursorToOriginalProxy = /* @__PURE__ */ new WeakMap();
|
|
357
|
+
var cursorIteratorTraps = {
|
|
358
|
+
get(target, prop) {
|
|
359
|
+
if (!advanceMethodProps.includes(prop))
|
|
360
|
+
return target[prop];
|
|
361
|
+
let cachedFunc = methodMap[prop];
|
|
362
|
+
if (!cachedFunc) {
|
|
363
|
+
cachedFunc = methodMap[prop] = function(...args) {
|
|
364
|
+
advanceResults.set(this, ittrProxiedCursorToOriginalProxy.get(this)[prop](...args));
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
return cachedFunc;
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
async function* iterate(...args) {
|
|
371
|
+
let cursor = this;
|
|
372
|
+
if (!(cursor instanceof IDBCursor)) {
|
|
373
|
+
cursor = await cursor.openCursor(...args);
|
|
374
|
+
}
|
|
375
|
+
if (!cursor)
|
|
376
|
+
return;
|
|
377
|
+
cursor = cursor;
|
|
378
|
+
const proxiedCursor = new Proxy(cursor, cursorIteratorTraps);
|
|
379
|
+
ittrProxiedCursorToOriginalProxy.set(proxiedCursor, cursor);
|
|
380
|
+
reverseTransformCache.set(proxiedCursor, unwrap(cursor));
|
|
381
|
+
while (cursor) {
|
|
382
|
+
yield proxiedCursor;
|
|
383
|
+
cursor = await (advanceResults.get(proxiedCursor) || cursor.continue());
|
|
384
|
+
advanceResults.delete(proxiedCursor);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
function isIteratorProp(target, prop) {
|
|
388
|
+
return prop === Symbol.asyncIterator && instanceOfAny(target, [IDBIndex, IDBObjectStore, IDBCursor]) || prop === "iterate" && instanceOfAny(target, [IDBIndex, IDBObjectStore]);
|
|
389
|
+
}
|
|
390
|
+
replaceTraps((oldTraps) => ({
|
|
391
|
+
...oldTraps,
|
|
392
|
+
get(target, prop, receiver) {
|
|
393
|
+
if (isIteratorProp(target, prop))
|
|
394
|
+
return iterate;
|
|
395
|
+
return oldTraps.get(target, prop, receiver);
|
|
396
|
+
},
|
|
397
|
+
has(target, prop) {
|
|
398
|
+
return isIteratorProp(target, prop) || oldTraps.has(target, prop);
|
|
399
|
+
}
|
|
400
|
+
}));
|
|
401
|
+
|
|
402
|
+
// src/idbStore.ts
|
|
403
|
+
var dbPromise = openDB("client-store-db", 1, {
|
|
404
|
+
upgrade(db) {
|
|
405
|
+
db.createObjectStore("metaKV");
|
|
406
|
+
db.createObjectStore("uploadQueue", {
|
|
407
|
+
keyPath: "sha256"
|
|
408
|
+
});
|
|
409
|
+
db.createObjectStore("downloadQueue", {
|
|
410
|
+
keyPath: "path"
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
var IDBStore = class {
|
|
415
|
+
seed;
|
|
416
|
+
hostURL;
|
|
417
|
+
hostID;
|
|
418
|
+
async wipe() {
|
|
419
|
+
await deleteDB("client-store-db");
|
|
420
|
+
}
|
|
421
|
+
async getSeed() {
|
|
422
|
+
const db = await dbPromise;
|
|
423
|
+
const hex = await db.get("metaKV", "seed");
|
|
424
|
+
if (!hex) {
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
const bytes = htob(hex);
|
|
428
|
+
return bytes;
|
|
429
|
+
}
|
|
430
|
+
async setSeed(seed) {
|
|
431
|
+
const hex = btoh(seed);
|
|
432
|
+
const db = await dbPromise;
|
|
433
|
+
await db.put("metaKV", hex, "seed");
|
|
434
|
+
this.seed = seed;
|
|
435
|
+
}
|
|
436
|
+
async getHostURL() {
|
|
437
|
+
const db = await dbPromise;
|
|
438
|
+
const url = await db.get("metaKV", "hostURL");
|
|
439
|
+
return url;
|
|
440
|
+
}
|
|
441
|
+
async setHostURL(url) {
|
|
442
|
+
const db = await dbPromise;
|
|
443
|
+
db.put("metaKV", url, "hostURL");
|
|
444
|
+
}
|
|
445
|
+
async getHostID() {
|
|
446
|
+
const db = await dbPromise;
|
|
447
|
+
const id = await db.get("metaKV", "hostID");
|
|
448
|
+
return id;
|
|
449
|
+
}
|
|
450
|
+
async setHostID(id) {
|
|
451
|
+
const db = await dbPromise;
|
|
452
|
+
await db.put("metaKV", id, "hostID");
|
|
453
|
+
}
|
|
454
|
+
uploadQueue = /* @__PURE__ */ new Map();
|
|
455
|
+
enqueueUpload = async (sha256, cipherOp) => {
|
|
456
|
+
const db = await dbPromise;
|
|
457
|
+
await db.put("uploadQueue", { sha256, cipherOp });
|
|
458
|
+
};
|
|
459
|
+
dequeueUpload = async (sha256) => {
|
|
460
|
+
const db = await dbPromise;
|
|
461
|
+
await db.delete("uploadQueue", sha256);
|
|
462
|
+
};
|
|
463
|
+
peekUpload = async (sha256) => {
|
|
464
|
+
const db = await dbPromise;
|
|
465
|
+
const row = await db.get("uploadQueue", sha256);
|
|
466
|
+
return row?.cipherOp;
|
|
467
|
+
};
|
|
468
|
+
listUploads = async () => {
|
|
469
|
+
const db = await dbPromise;
|
|
470
|
+
const sha256s = await db.getAllKeys("uploadQueue");
|
|
471
|
+
return sha256s;
|
|
472
|
+
};
|
|
473
|
+
downloadQueue = /* @__PURE__ */ new Set();
|
|
474
|
+
enqueueDownload = async (path) => {
|
|
475
|
+
const db = await dbPromise;
|
|
476
|
+
await db.put("downloadQueue", { path });
|
|
477
|
+
};
|
|
478
|
+
dequeueDownload = async (path) => {
|
|
479
|
+
const db = await dbPromise;
|
|
480
|
+
await db.delete("downloadQueue", path);
|
|
481
|
+
};
|
|
482
|
+
listDownloads = async () => {
|
|
483
|
+
const db = await dbPromise;
|
|
484
|
+
const paths = await db.getAllKeys("downloadQueue");
|
|
485
|
+
return paths;
|
|
486
|
+
};
|
|
487
|
+
};
|
|
488
|
+
var idbStore = new IDBStore();
|
|
489
|
+
|
|
157
490
|
// node_modules/@msgpack/msgpack/dist.es5+esm/utils/utf8.mjs
|
|
158
491
|
function utf8Count(str) {
|
|
159
492
|
var strLength = str.length;
|
|
@@ -8476,7 +8809,6 @@ var DiplomaticClient = class {
|
|
|
8476
8809
|
};
|
|
8477
8810
|
};
|
|
8478
8811
|
async init(params) {
|
|
8479
|
-
await this.store.init?.();
|
|
8480
8812
|
if (params.seed) {
|
|
8481
8813
|
const bytes = typeof params.seed === "string" ? htob(params.seed) : params.seed;
|
|
8482
8814
|
await this.store.setSeed(bytes);
|
|
@@ -8556,7 +8888,7 @@ var DiplomaticClient = class {
|
|
|
8556
8888
|
const pathResp = await api_default.getDeltaPaths(hostURL, begin, hostKeyPair);
|
|
8557
8889
|
const paths = pathResp.paths;
|
|
8558
8890
|
for (const path of paths) {
|
|
8559
|
-
await this.store.
|
|
8891
|
+
await this.store.enqueueDownload(path);
|
|
8560
8892
|
}
|
|
8561
8893
|
this.lastFetchedAt = pathResp.fetchedAt;
|
|
8562
8894
|
}
|
|
@@ -8565,8 +8897,7 @@ var DiplomaticClient = class {
|
|
|
8565
8897
|
return [];
|
|
8566
8898
|
}
|
|
8567
8899
|
const { hostURL, hostKeyPair, encKey } = this;
|
|
8568
|
-
const
|
|
8569
|
-
const paths = entries.map(([path]) => path);
|
|
8900
|
+
const paths = await this.store.listDownloads();
|
|
8570
8901
|
paths.sort((p1, p2) => p2.localeCompare(p1));
|
|
8571
8902
|
for (const path of paths) {
|
|
8572
8903
|
const cipher = await api_default.getDelta(hostURL, path, hostKeyPair);
|
|
@@ -8574,11 +8905,11 @@ var DiplomaticClient = class {
|
|
|
8574
8905
|
const op = decode(packed);
|
|
8575
8906
|
try {
|
|
8576
8907
|
await this.applier(op);
|
|
8577
|
-
this.store.
|
|
8908
|
+
await this.store.dequeueDownload(path);
|
|
8578
8909
|
} catch {
|
|
8579
8910
|
const transient = true;
|
|
8580
8911
|
if (!transient) {
|
|
8581
|
-
this.store.
|
|
8912
|
+
await this.store.dequeueDownload(path);
|
|
8582
8913
|
}
|
|
8583
8914
|
}
|
|
8584
8915
|
}
|
|
@@ -8587,14 +8918,14 @@ var DiplomaticClient = class {
|
|
|
8587
8918
|
if (!this.hostURL || !this.hostKeyPair) {
|
|
8588
8919
|
return;
|
|
8589
8920
|
}
|
|
8590
|
-
const cipherOp = await this.store.
|
|
8921
|
+
const cipherOp = await this.store.peekUpload(sha256);
|
|
8591
8922
|
if (cipherOp) {
|
|
8592
8923
|
await api_default.putDelta(this.hostURL, cipherOp, this.hostKeyPair);
|
|
8593
8924
|
}
|
|
8594
|
-
await this.store.
|
|
8925
|
+
await this.store.dequeueUpload(sha256);
|
|
8595
8926
|
}
|
|
8596
8927
|
async pushQueuedOps() {
|
|
8597
|
-
for (const
|
|
8928
|
+
for (const sha256 of await this.store.listUploads()) {
|
|
8598
8929
|
await this.pushQueuedOp(sha256);
|
|
8599
8930
|
}
|
|
8600
8931
|
}
|
|
@@ -8610,11 +8941,11 @@ var DiplomaticClient = class {
|
|
|
8610
8941
|
const cipherOp = await crypto_default.encryptXSalsa20Poly1305Combined(packed, this.encKey);
|
|
8611
8942
|
const sha256 = await crypto_default.sha256Hash(cipherOp);
|
|
8612
8943
|
const shaHex = btoh(sha256);
|
|
8613
|
-
await this.store.
|
|
8944
|
+
await this.store.enqueueUpload(shaHex, cipherOp);
|
|
8614
8945
|
try {
|
|
8615
8946
|
await this.applier(op);
|
|
8616
8947
|
} catch {
|
|
8617
|
-
await this.store.
|
|
8948
|
+
await this.store.dequeueUpload(shaHex);
|
|
8618
8949
|
}
|
|
8619
8950
|
await this.pushQueuedOp(shaHex);
|
|
8620
8951
|
}
|
|
@@ -8629,6 +8960,7 @@ export {
|
|
|
8629
8960
|
Verb,
|
|
8630
8961
|
btoh,
|
|
8631
8962
|
htob,
|
|
8963
|
+
idbStore,
|
|
8632
8964
|
crypto_default as libsodiumCrypto,
|
|
8633
8965
|
localStorageStore,
|
|
8634
8966
|
useClientState,
|
|
@@ -1,14 +1,21 @@
|
|
|
1
|
-
import { Queue } from "./queue";
|
|
2
1
|
import type { IClientStateStore } from "./types";
|
|
3
2
|
declare class LocalStorageStore implements IClientStateStore {
|
|
3
|
+
wipe(): Promise<void>;
|
|
4
4
|
getSeed(): Promise<Uint8Array | undefined>;
|
|
5
5
|
setSeed(seed: Uint8Array): Promise<void>;
|
|
6
6
|
getHostURL(): Promise<string | undefined>;
|
|
7
7
|
setHostURL(url: string): Promise<void>;
|
|
8
8
|
getHostID(): Promise<string | undefined>;
|
|
9
9
|
setHostID(id: string): Promise<void>;
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
uploadQueue: Map<string, Uint8Array>;
|
|
11
|
+
enqueueUpload: (sha256: string, cipherOp: Uint8Array) => Promise<void>;
|
|
12
|
+
dequeueUpload: (sha256: string) => Promise<void>;
|
|
13
|
+
peekUpload: (sha256: string) => Promise<Uint8Array | undefined>;
|
|
14
|
+
listUploads: () => Promise<string[]>;
|
|
15
|
+
downloadQueue: Set<string>;
|
|
16
|
+
enqueueDownload: (path: string) => Promise<void>;
|
|
17
|
+
dequeueDownload: (path: string) => Promise<void>;
|
|
18
|
+
listDownloads: () => Promise<string[]>;
|
|
12
19
|
}
|
|
13
20
|
export declare const localStorageStore: LocalStorageStore;
|
|
14
21
|
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { IClientStateStore } from "./types";
|
|
2
|
+
declare class MemoryStore implements IClientStateStore {
|
|
3
|
+
seed?: Uint8Array;
|
|
4
|
+
hostURL?: string;
|
|
5
|
+
hostID?: string;
|
|
6
|
+
wipe(): Promise<void>;
|
|
7
|
+
getSeed(): Promise<Uint8Array | undefined>;
|
|
8
|
+
setSeed(seed: Uint8Array): Promise<void>;
|
|
9
|
+
getHostURL(): Promise<string | undefined>;
|
|
10
|
+
setHostURL(url: string): Promise<void>;
|
|
11
|
+
getHostID(): Promise<string | undefined>;
|
|
12
|
+
setHostID(id: string): Promise<void>;
|
|
13
|
+
uploadQueue: Map<string, Uint8Array>;
|
|
14
|
+
enqueueUpload: (sha256: string, cipherOp: Uint8Array) => Promise<void>;
|
|
15
|
+
dequeueUpload: (sha256: string) => Promise<void>;
|
|
16
|
+
peekUpload: (sha256: string) => Promise<Uint8Array | undefined>;
|
|
17
|
+
listUploads: () => Promise<string[]>;
|
|
18
|
+
downloadQueue: Set<string>;
|
|
19
|
+
enqueueDownload: (path: string) => Promise<void>;
|
|
20
|
+
dequeueDownload: (path: string) => Promise<void>;
|
|
21
|
+
listDownloads: () => Promise<string[]>;
|
|
22
|
+
}
|
|
23
|
+
export declare const memoryStore: MemoryStore;
|
|
24
|
+
export {};
|
package/dist/types.d.ts
CHANGED
|
@@ -1,44 +1,19 @@
|
|
|
1
1
|
import type { IOp } from "./shared/types";
|
|
2
|
-
export interface IQueue<K, V> {
|
|
3
|
-
/**
|
|
4
|
-
* Adds an entry to the queue.
|
|
5
|
-
* @param key - The key of the entry.
|
|
6
|
-
* @param value - The value of the entry.
|
|
7
|
-
*/
|
|
8
|
-
enqueue(key: K, value: V): Promise<void>;
|
|
9
|
-
/**
|
|
10
|
-
* Returns the value of the entry with the specified key without removing it.
|
|
11
|
-
* @param key - The key of the entry.
|
|
12
|
-
* @returns The value of the entry if found, or undefined if the key does not exist.
|
|
13
|
-
*/
|
|
14
|
-
peek(key: K): Promise<V | undefined>;
|
|
15
|
-
/**
|
|
16
|
-
* Returns an array of entries in the queue, allowing sorting and iteration over all entries.
|
|
17
|
-
* @returns An array of entries in the queue.
|
|
18
|
-
*/
|
|
19
|
-
entries(): Promise<Array<[K, V]>>;
|
|
20
|
-
/**
|
|
21
|
-
* Removes the entry with the specified key from the queue.
|
|
22
|
-
* @param key - The key of the entry.
|
|
23
|
-
* @returns The value of the removed entry if found, or undefined if the key does not exist.
|
|
24
|
-
*/
|
|
25
|
-
dequeue(key: K): Promise<V | undefined>;
|
|
26
|
-
/**
|
|
27
|
-
* Returns the number of entries in the queue.
|
|
28
|
-
* @returns The size of the queue.
|
|
29
|
-
*/
|
|
30
|
-
size(): Promise<number>;
|
|
31
|
-
}
|
|
32
2
|
export interface IClientStateStore {
|
|
33
|
-
init?: () => Promise<void>;
|
|
34
3
|
getSeed: () => Promise<Uint8Array | undefined>;
|
|
35
4
|
setSeed: (seed: Uint8Array) => Promise<void>;
|
|
36
5
|
getHostURL: () => Promise<string | undefined>;
|
|
37
6
|
setHostURL: (url: string) => Promise<void>;
|
|
38
7
|
getHostID: () => Promise<string | undefined>;
|
|
39
8
|
setHostID: (id: string) => Promise<void>;
|
|
40
|
-
|
|
41
|
-
|
|
9
|
+
wipe: () => Promise<void>;
|
|
10
|
+
enqueueUpload: (sha256: string, cipherOp: Uint8Array) => Promise<void>;
|
|
11
|
+
dequeueUpload: (sha256: string) => Promise<void>;
|
|
12
|
+
peekUpload: (sha256: string) => Promise<Uint8Array | undefined>;
|
|
13
|
+
listUploads: () => Promise<string[]>;
|
|
14
|
+
enqueueDownload: (path: string) => Promise<void>;
|
|
15
|
+
dequeueDownload: (path: string) => Promise<void>;
|
|
16
|
+
listDownloads: () => Promise<string[]>;
|
|
42
17
|
}
|
|
43
18
|
export type DiplomaticClientState = "loading" | "seedless" | "hostless" | "ready";
|
|
44
19
|
export type Applier = (op: IOp) => Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interncom/diplomatic",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Secure sync layer",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
],
|
|
11
11
|
"scripts": {
|
|
12
12
|
"tsc": "tsc",
|
|
13
|
-
"build": "node esbuild.mjs"
|
|
13
|
+
"build": "node esbuild.mjs",
|
|
14
|
+
"test": "vitest"
|
|
14
15
|
},
|
|
15
16
|
"author": "The Internet Committee",
|
|
16
17
|
"license": "ISC",
|
|
@@ -19,14 +20,16 @@
|
|
|
19
20
|
},
|
|
20
21
|
"devDependencies": {
|
|
21
22
|
"@types/react": "^18.3.3",
|
|
22
|
-
"react": "^18.3.1",
|
|
23
23
|
"esbuild": "0.21.5",
|
|
24
|
-
"
|
|
24
|
+
"react": "^18.3.1",
|
|
25
|
+
"typescript": "^5.5.2",
|
|
26
|
+
"vitest": "^1.6.0"
|
|
25
27
|
},
|
|
26
28
|
"peerDependencies": {
|
|
27
29
|
"react": "^18.3.1"
|
|
28
30
|
},
|
|
29
31
|
"dependencies": {
|
|
30
|
-
"@msgpack/msgpack": "^3.0.0-beta2"
|
|
32
|
+
"@msgpack/msgpack": "^3.0.0-beta2",
|
|
33
|
+
"idb": "^8.0.0"
|
|
31
34
|
}
|
|
32
35
|
}
|