@interncom/diplomatic 0.0.9 → 0.0.11
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/client.d.ts +4 -3
- package/dist/index.mjs +70 -54
- package/dist/localStorageStore.d.ts +3 -8
- package/dist/queue.d.ts +10 -0
- package/dist/types.d.ts +32 -6
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -26,11 +26,12 @@ export default class DiplomaticClient {
|
|
|
26
26
|
loadHost(): Promise<void>;
|
|
27
27
|
register(hostURL: string): Promise<void>;
|
|
28
28
|
get state(): DiplomaticClientState;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
processOps(): Promise<void>;
|
|
30
|
+
pullOpPaths(): Promise<never[] | undefined>;
|
|
31
|
+
fetchAndExecQueuedOps(): Promise<never[] | undefined>;
|
|
32
32
|
private pushQueuedOp;
|
|
33
33
|
pushQueuedOps(): Promise<void>;
|
|
34
|
+
sync(): Promise<void>;
|
|
34
35
|
apply(op: IOp): Promise<void>;
|
|
35
36
|
upsert<T>(type: string, body: T, version?: number): Promise<void>;
|
|
36
37
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -80,6 +80,31 @@ 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
|
+
|
|
83
108
|
// ../shared/lib.ts
|
|
84
109
|
function btoh(bytes) {
|
|
85
110
|
const hex = Array.from(bytes).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
@@ -124,29 +149,8 @@ var LocalStorageStore = class {
|
|
|
124
149
|
async setHostID(id) {
|
|
125
150
|
return localStorage.setItem(hostIDKey, id);
|
|
126
151
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const hex = btoh(sha256);
|
|
130
|
-
this.uploadQueue.set(hex, cipherOp);
|
|
131
|
-
};
|
|
132
|
-
dequeueUpload = async (sha256) => {
|
|
133
|
-
const hex = btoh(sha256);
|
|
134
|
-
this.uploadQueue.delete(hex);
|
|
135
|
-
};
|
|
136
|
-
peekUpload = async (sha256) => {
|
|
137
|
-
const hex = btoh(sha256);
|
|
138
|
-
return this.uploadQueue.get(hex);
|
|
139
|
-
};
|
|
140
|
-
async listUploadQueue() {
|
|
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
|
-
};
|
|
152
|
+
pushQueue = new Queue();
|
|
153
|
+
pullQueue = new Queue();
|
|
150
154
|
};
|
|
151
155
|
var localStorageStore = new LocalStorageStore();
|
|
152
156
|
|
|
@@ -8440,7 +8444,6 @@ var DiplomaticClient = class {
|
|
|
8440
8444
|
constructor(params) {
|
|
8441
8445
|
this.store = params.store;
|
|
8442
8446
|
this.applier = params.stateManager.apply;
|
|
8443
|
-
console.log("constructing");
|
|
8444
8447
|
this.init(params);
|
|
8445
8448
|
}
|
|
8446
8449
|
websocket;
|
|
@@ -8466,7 +8469,7 @@ var DiplomaticClient = class {
|
|
|
8466
8469
|
};
|
|
8467
8470
|
this.websocket.onmessage = (e) => {
|
|
8468
8471
|
console.log(`RECEIVED: ${e.data}`);
|
|
8469
|
-
this.
|
|
8472
|
+
this.processOps();
|
|
8470
8473
|
};
|
|
8471
8474
|
this.websocket.onerror = (e) => {
|
|
8472
8475
|
console.log(`ERROR: ${e}`);
|
|
@@ -8490,7 +8493,7 @@ var DiplomaticClient = class {
|
|
|
8490
8493
|
if (this.hostURL) {
|
|
8491
8494
|
await this.connect(this.hostURL);
|
|
8492
8495
|
}
|
|
8493
|
-
await this.
|
|
8496
|
+
await this.sync();
|
|
8494
8497
|
this.listener?.(this.state);
|
|
8495
8498
|
}
|
|
8496
8499
|
async loadSeed() {
|
|
@@ -8540,53 +8543,65 @@ var DiplomaticClient = class {
|
|
|
8540
8543
|
}
|
|
8541
8544
|
return "ready";
|
|
8542
8545
|
}
|
|
8543
|
-
async
|
|
8544
|
-
|
|
8545
|
-
|
|
8546
|
-
}
|
|
8547
|
-
const packed = encode(delta);
|
|
8548
|
-
const cipherOp = await crypto_default.encryptXSalsa20Poly1305Combined(packed, this.encKey);
|
|
8549
|
-
await api_default.putDelta(this.hostURL, cipherOp, this.hostKeyPair);
|
|
8546
|
+
async processOps() {
|
|
8547
|
+
await this.pullOpPaths();
|
|
8548
|
+
await this.fetchAndExecQueuedOps();
|
|
8550
8549
|
}
|
|
8551
|
-
async
|
|
8550
|
+
async pullOpPaths() {
|
|
8552
8551
|
if (!this.hostURL || !this.hostKeyPair || !this.encKey) {
|
|
8553
8552
|
return [];
|
|
8554
8553
|
}
|
|
8555
8554
|
const begin = new Date(this.lastFetchedAt ?? 0);
|
|
8556
|
-
const { hostURL, hostKeyPair
|
|
8555
|
+
const { hostURL, hostKeyPair } = this;
|
|
8557
8556
|
const pathResp = await api_default.getDeltaPaths(hostURL, begin, hostKeyPair);
|
|
8558
8557
|
const paths = pathResp.paths;
|
|
8558
|
+
for (const path of paths) {
|
|
8559
|
+
await this.store.pullQueue.enqueue(path, null);
|
|
8560
|
+
}
|
|
8559
8561
|
this.lastFetchedAt = pathResp.fetchedAt;
|
|
8560
|
-
|
|
8562
|
+
}
|
|
8563
|
+
async fetchAndExecQueuedOps() {
|
|
8564
|
+
if (!this.hostURL || !this.hostKeyPair || !this.encKey) {
|
|
8565
|
+
return [];
|
|
8566
|
+
}
|
|
8567
|
+
const { hostURL, hostKeyPair, encKey } = this;
|
|
8568
|
+
const entries = await this.store.pullQueue.entries();
|
|
8569
|
+
const paths = entries.map(([path]) => path);
|
|
8570
|
+
paths.sort((p1, p2) => p2.localeCompare(p1));
|
|
8571
|
+
for (const path of paths) {
|
|
8561
8572
|
const cipher = await api_default.getDelta(hostURL, path, hostKeyPair);
|
|
8562
|
-
const
|
|
8563
|
-
const
|
|
8564
|
-
|
|
8565
|
-
|
|
8566
|
-
|
|
8567
|
-
|
|
8568
|
-
|
|
8569
|
-
|
|
8570
|
-
|
|
8571
|
-
|
|
8573
|
+
const packed = await crypto_default.decryptXSalsa20Poly1305Combined(cipher, encKey);
|
|
8574
|
+
const op = decode(packed);
|
|
8575
|
+
try {
|
|
8576
|
+
await this.applier(op);
|
|
8577
|
+
this.store.pullQueue.dequeue(path);
|
|
8578
|
+
} catch {
|
|
8579
|
+
const transient = true;
|
|
8580
|
+
if (!transient) {
|
|
8581
|
+
this.store.pullQueue.dequeue(path);
|
|
8582
|
+
}
|
|
8583
|
+
}
|
|
8572
8584
|
}
|
|
8573
8585
|
}
|
|
8574
8586
|
async pushQueuedOp(sha256) {
|
|
8575
8587
|
if (!this.hostURL || !this.hostKeyPair) {
|
|
8576
8588
|
return;
|
|
8577
8589
|
}
|
|
8578
|
-
const cipherOp = await this.store.
|
|
8590
|
+
const cipherOp = await this.store.pushQueue.peek(sha256);
|
|
8579
8591
|
if (cipherOp) {
|
|
8580
8592
|
await api_default.putDelta(this.hostURL, cipherOp, this.hostKeyPair);
|
|
8581
8593
|
}
|
|
8582
|
-
await this.store.
|
|
8594
|
+
await this.store.pushQueue.dequeue(sha256);
|
|
8583
8595
|
}
|
|
8584
8596
|
async pushQueuedOps() {
|
|
8585
|
-
for (const sha256 of await this.store.
|
|
8586
|
-
|
|
8587
|
-
await this.pushQueuedOp(bytes);
|
|
8597
|
+
for (const [sha256] of await this.store.pushQueue.entries()) {
|
|
8598
|
+
await this.pushQueuedOp(sha256);
|
|
8588
8599
|
}
|
|
8589
8600
|
}
|
|
8601
|
+
async sync() {
|
|
8602
|
+
await this.processOps();
|
|
8603
|
+
await this.pushQueuedOps();
|
|
8604
|
+
}
|
|
8590
8605
|
async apply(op) {
|
|
8591
8606
|
if (!this.encKey) {
|
|
8592
8607
|
throw "No encryption key";
|
|
@@ -8594,13 +8609,14 @@ var DiplomaticClient = class {
|
|
|
8594
8609
|
const packed = encode(op);
|
|
8595
8610
|
const cipherOp = await crypto_default.encryptXSalsa20Poly1305Combined(packed, this.encKey);
|
|
8596
8611
|
const sha256 = await crypto_default.sha256Hash(cipherOp);
|
|
8597
|
-
|
|
8612
|
+
const shaHex = btoh(sha256);
|
|
8613
|
+
await this.store.pushQueue.enqueue(shaHex, cipherOp);
|
|
8598
8614
|
try {
|
|
8599
8615
|
await this.applier(op);
|
|
8600
8616
|
} catch {
|
|
8601
|
-
await this.store.
|
|
8617
|
+
await this.store.pushQueue.dequeue(shaHex);
|
|
8602
8618
|
}
|
|
8603
|
-
await this.pushQueuedOp(
|
|
8619
|
+
await this.pushQueuedOp(shaHex);
|
|
8604
8620
|
}
|
|
8605
8621
|
async upsert(type, body, version = 0) {
|
|
8606
8622
|
const op = genUpsertOp(type, body, version);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Queue } from "./queue";
|
|
1
2
|
import type { IClientStateStore } from "./types";
|
|
2
3
|
declare class LocalStorageStore implements IClientStateStore {
|
|
3
4
|
getSeed(): Promise<Uint8Array | undefined>;
|
|
@@ -6,14 +7,8 @@ declare class LocalStorageStore implements IClientStateStore {
|
|
|
6
7
|
setHostURL(url: string): Promise<void>;
|
|
7
8
|
getHostID(): Promise<string | undefined>;
|
|
8
9
|
setHostID(id: string): Promise<void>;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
dequeueUpload: (sha256: Uint8Array) => Promise<void>;
|
|
12
|
-
peekUpload: (sha256: Uint8Array) => Promise<Uint8Array | undefined>;
|
|
13
|
-
listUploadQueue(): Promise<string[]>;
|
|
14
|
-
downloadQueue: Set<string>;
|
|
15
|
-
enqueueDownload: (path: string) => Promise<void>;
|
|
16
|
-
dequeueDownload: (path: string) => Promise<void>;
|
|
10
|
+
pushQueue: Queue<string, Uint8Array>;
|
|
11
|
+
pullQueue: Queue<string, null>;
|
|
17
12
|
}
|
|
18
13
|
export declare const localStorageStore: LocalStorageStore;
|
|
19
14
|
export {};
|
package/dist/queue.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IQueue } from "./types";
|
|
2
|
+
export declare class Queue<K, V> implements IQueue<K, V> {
|
|
3
|
+
private map;
|
|
4
|
+
constructor();
|
|
5
|
+
enqueue(key: K, value: V): Promise<void>;
|
|
6
|
+
peek(key: K): Promise<V | undefined>;
|
|
7
|
+
entries(): Promise<Array<[K, V]>>;
|
|
8
|
+
dequeue(key: K): Promise<V | undefined>;
|
|
9
|
+
size(): Promise<number>;
|
|
10
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,34 @@
|
|
|
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
|
+
}
|
|
2
32
|
export interface IClientStateStore {
|
|
3
33
|
init?: () => Promise<void>;
|
|
4
34
|
getSeed: () => Promise<Uint8Array | undefined>;
|
|
@@ -7,12 +37,8 @@ export interface IClientStateStore {
|
|
|
7
37
|
setHostURL: (url: string) => Promise<void>;
|
|
8
38
|
getHostID: () => Promise<string | undefined>;
|
|
9
39
|
setHostID: (id: string) => Promise<void>;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
peekUpload: (sha256: Uint8Array) => Promise<Uint8Array | undefined>;
|
|
13
|
-
listUploadQueue: () => Promise<string[]>;
|
|
14
|
-
enqueueDownload: (path: string) => Promise<void>;
|
|
15
|
-
dequeueDownload: (path: string) => Promise<void>;
|
|
40
|
+
pushQueue: IQueue<string, Uint8Array>;
|
|
41
|
+
pullQueue: IQueue<string, null>;
|
|
16
42
|
}
|
|
17
43
|
export type DiplomaticClientState = "loading" | "seedless" | "hostless" | "ready";
|
|
18
44
|
export type Applier = (op: IOp) => Promise<void>;
|