@interncom/diplomatic 0.0.14 → 0.0.16

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 CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { IOp, KeyPair } from "./shared/types";
2
- import type { IClientStateStore, DiplomaticClientState, Applier } from "./types";
2
+ import type { IClientStateStore, Applier, IDiplomaticClientState } from "./types";
3
3
  import type { StateManager } from "./state";
4
4
  export interface IDiplomaticClientParams {
5
5
  store: IClientStateStore;
@@ -11,7 +11,7 @@ export interface IDiplomaticClientParams {
11
11
  export default class DiplomaticClient {
12
12
  store: IClientStateStore;
13
13
  applier: Applier;
14
- listener?: (state: DiplomaticClientState) => void;
14
+ listener?: (state: IDiplomaticClientState) => void;
15
15
  seed?: Uint8Array;
16
16
  encKey?: Uint8Array;
17
17
  hostURL?: URL;
@@ -25,7 +25,8 @@ export default class DiplomaticClient {
25
25
  setSeed(seed: Uint8Array): Promise<void>;
26
26
  loadHost(): Promise<void>;
27
27
  register(hostURL: string): Promise<void>;
28
- get state(): DiplomaticClientState;
28
+ emitUpdate(): Promise<void>;
29
+ getState(): Promise<IDiplomaticClientState>;
29
30
  processOps(): Promise<void>;
30
31
  pullOpPaths(): Promise<never[] | undefined>;
31
32
  fetchAndExecQueuedOps(): Promise<never[] | undefined>;
@@ -15,10 +15,12 @@ declare class IDBStore implements IClientStateStore {
15
15
  dequeueUpload: (sha256: string) => Promise<void>;
16
16
  peekUpload: (sha256: string) => Promise<Uint8Array | undefined>;
17
17
  listUploads: () => Promise<string[]>;
18
+ numUploads: () => Promise<number>;
18
19
  downloadQueue: Set<string>;
19
20
  enqueueDownload: (path: string) => Promise<void>;
20
21
  dequeueDownload: (path: string) => Promise<void>;
21
22
  listDownloads: () => Promise<string[]>;
23
+ numDownloads: () => Promise<number>;
22
24
  }
23
25
  export declare const idbStore: IDBStore;
24
26
  export {};
package/dist/index.d.ts CHANGED
@@ -2,9 +2,10 @@ import { useClientState, useSyncOnResume } from "./useClient";
2
2
  import { StateManager, useStateWatcher } from './state';
3
3
  import { localStorageStore } from "./localStorageStore";
4
4
  import { idbStore } from "./idbStore";
5
+ import type { IDiplomaticClientState } from "./types";
5
6
  import DiplomaticClient from "./client";
6
7
  import libsodiumCrypto from "./crypto";
7
8
  import { btoh, htob } from "./shared/lib";
8
9
  import { type IOp, Verb } from "./shared/types";
9
10
  export { useClientState, useSyncOnResume, StateManager, useStateWatcher, localStorageStore, idbStore, DiplomaticClient, libsodiumCrypto, btoh, htob, Verb, };
10
- export type { IOp, };
11
+ export type { IOp, IDiplomaticClientState, };
package/dist/index.mjs CHANGED
@@ -12,12 +12,18 @@ var __export = (target, all) => {
12
12
 
13
13
  // src/useClient.ts
14
14
  import { useState, useEffect } from "react";
15
- var initialState = "loading";
16
15
  function useClientState(client) {
17
- const [state, setState] = useState(initialState);
16
+ const [state, setState] = useState();
18
17
  useEffect(() => {
19
- setState(client.state);
20
- client.listener = setState;
18
+ async function updateState() {
19
+ const state2 = await client.getState();
20
+ setState(state2);
21
+ }
22
+ client.listener = updateState;
23
+ updateState();
24
+ return () => {
25
+ client.listener = void 0;
26
+ };
21
27
  }, [client]);
22
28
  return state;
23
29
  }
@@ -151,6 +157,9 @@ var LocalStorageStore = class {
151
157
  listUploads = async () => {
152
158
  return Array.from(this.uploadQueue.keys());
153
159
  };
160
+ numUploads = async () => {
161
+ return this.uploadQueue.size;
162
+ };
154
163
  downloadQueue = /* @__PURE__ */ new Set();
155
164
  enqueueDownload = async (path) => {
156
165
  this.downloadQueue.add(path);
@@ -161,6 +170,9 @@ var LocalStorageStore = class {
161
170
  listDownloads = async () => {
162
171
  return Array.from(this.downloadQueue.keys());
163
172
  };
173
+ numDownloads = async () => {
174
+ return this.downloadQueue.size;
175
+ };
164
176
  };
165
177
  var localStorageStore = new LocalStorageStore();
166
178
 
@@ -481,6 +493,10 @@ var IDBStore = class {
481
493
  const sha256s = await db.getAllKeys("uploadQueue");
482
494
  return sha256s;
483
495
  };
496
+ numUploads = async () => {
497
+ const db = await dbPromise;
498
+ return db.count("uploadQueue");
499
+ };
484
500
  downloadQueue = /* @__PURE__ */ new Set();
485
501
  enqueueDownload = async (path) => {
486
502
  const db = await dbPromise;
@@ -495,6 +511,10 @@ var IDBStore = class {
495
511
  const paths = await db.getAllKeys("downloadQueue");
496
512
  return paths;
497
513
  };
514
+ numDownloads = async () => {
515
+ const db = await dbPromise;
516
+ return db.count("downloadQueue");
517
+ };
498
518
  };
499
519
  var idbStore = new IDBStore();
500
520
 
@@ -8806,10 +8826,12 @@ var DiplomaticClient = class {
8806
8826
  this.websocket = new WebSocket(url);
8807
8827
  this.websocket.onopen = (e) => {
8808
8828
  console.log("CONNECTED");
8829
+ this.emitUpdate();
8809
8830
  };
8810
8831
  this.websocket.onclose = (e) => {
8811
8832
  console.log("DISCONNECTED");
8812
8833
  this.connect(hostURL);
8834
+ this.emitUpdate();
8813
8835
  };
8814
8836
  this.websocket.onmessage = (e) => {
8815
8837
  console.log(`RECEIVED: ${e.data}`);
@@ -8837,7 +8859,7 @@ var DiplomaticClient = class {
8837
8859
  await this.connect(this.hostURL);
8838
8860
  }
8839
8861
  await this.sync();
8840
- this.listener?.(this.state);
8862
+ this.emitUpdate();
8841
8863
  }
8842
8864
  async loadSeed() {
8843
8865
  const seed = await this.store.getSeed();
@@ -8850,7 +8872,7 @@ var DiplomaticClient = class {
8850
8872
  this.seed = seed;
8851
8873
  this.encKey = await crypto_default.deriveXSalsa20Poly1305Key(seed);
8852
8874
  await this.store.setSeed(seed);
8853
- this.listener?.(this.state);
8875
+ this.emitUpdate();
8854
8876
  }
8855
8877
  async loadHost() {
8856
8878
  if (!this.seed) {
@@ -8875,16 +8897,20 @@ var DiplomaticClient = class {
8875
8897
  await api_default.register(this.hostURL, this.hostKeyPair.publicKey, "tok123");
8876
8898
  await this.store.setHostURL(hostURL);
8877
8899
  await this.store.setHostID(hostID);
8878
- this.listener?.(this.state);
8879
- }
8880
- get state() {
8881
- if (!this.seed || !this.encKey) {
8882
- return "seedless";
8883
- }
8884
- if (!this.hostURL || !this.hostKeyPair) {
8885
- return "hostless";
8886
- }
8887
- return "ready";
8900
+ this.emitUpdate();
8901
+ }
8902
+ async emitUpdate() {
8903
+ const state = await this.getState();
8904
+ this.listener?.(state);
8905
+ }
8906
+ async getState() {
8907
+ return {
8908
+ hasSeed: this.seed !== void 0 && this.encKey !== void 0,
8909
+ hasHost: this.hostURL !== void 0 && this.hostKeyPair !== void 0,
8910
+ connected: this.websocket?.readyState === WebSocket.OPEN,
8911
+ numUploads: await this.store.numUploads(),
8912
+ numDownloads: await this.store.numDownloads()
8913
+ };
8888
8914
  }
8889
8915
  async processOps() {
8890
8916
  await this.pullOpPaths();
@@ -8900,6 +8926,7 @@ var DiplomaticClient = class {
8900
8926
  const paths = pathResp.paths;
8901
8927
  for (const path of paths) {
8902
8928
  await this.store.enqueueDownload(path);
8929
+ this.emitUpdate();
8903
8930
  }
8904
8931
  this.lastFetchedAt = pathResp.fetchedAt;
8905
8932
  }
@@ -8917,10 +8944,12 @@ var DiplomaticClient = class {
8917
8944
  try {
8918
8945
  await this.applier(op);
8919
8946
  await this.store.dequeueDownload(path);
8947
+ this.emitUpdate();
8920
8948
  } catch {
8921
8949
  const transient = true;
8922
8950
  if (!transient) {
8923
8951
  await this.store.dequeueDownload(path);
8952
+ this.emitUpdate();
8924
8953
  }
8925
8954
  }
8926
8955
  }
@@ -8934,6 +8963,7 @@ var DiplomaticClient = class {
8934
8963
  await api_default.putDelta(this.hostURL, cipherOp, this.hostKeyPair);
8935
8964
  }
8936
8965
  await this.store.dequeueUpload(sha256);
8966
+ this.emitUpdate();
8937
8967
  }
8938
8968
  async pushQueuedOps() {
8939
8969
  for (const sha256 of await this.store.listUploads()) {
@@ -8953,12 +8983,18 @@ var DiplomaticClient = class {
8953
8983
  const sha256 = await crypto_default.sha256Hash(cipherOp);
8954
8984
  const shaHex = btoh(sha256);
8955
8985
  await this.store.enqueueUpload(shaHex, cipherOp);
8986
+ this.emitUpdate();
8956
8987
  try {
8957
8988
  await this.applier(op);
8958
8989
  } catch {
8959
8990
  await this.store.dequeueUpload(shaHex);
8991
+ this.emitUpdate();
8992
+ }
8993
+ try {
8994
+ await this.pushQueuedOp(shaHex);
8995
+ } catch (err) {
8996
+ console.info("failed to push");
8960
8997
  }
8961
- await this.pushQueuedOp(shaHex);
8962
8998
  }
8963
8999
  async upsert(type, body, version = 0) {
8964
9000
  const op = genUpsertOp(type, body, version);
@@ -12,10 +12,12 @@ declare class LocalStorageStore implements IClientStateStore {
12
12
  dequeueUpload: (sha256: string) => Promise<void>;
13
13
  peekUpload: (sha256: string) => Promise<Uint8Array | undefined>;
14
14
  listUploads: () => Promise<string[]>;
15
+ numUploads: () => Promise<number>;
15
16
  downloadQueue: Set<string>;
16
17
  enqueueDownload: (path: string) => Promise<void>;
17
18
  dequeueDownload: (path: string) => Promise<void>;
18
19
  listDownloads: () => Promise<string[]>;
20
+ numDownloads: () => Promise<number>;
19
21
  }
20
22
  export declare const localStorageStore: LocalStorageStore;
21
23
  export {};
@@ -15,10 +15,12 @@ declare class MemoryStore implements IClientStateStore {
15
15
  dequeueUpload: (sha256: string) => Promise<void>;
16
16
  peekUpload: (sha256: string) => Promise<Uint8Array | undefined>;
17
17
  listUploads: () => Promise<string[]>;
18
+ numUploads: () => Promise<number>;
18
19
  downloadQueue: Set<string>;
19
20
  enqueueDownload: (path: string) => Promise<void>;
20
21
  dequeueDownload: (path: string) => Promise<void>;
21
22
  listDownloads: () => Promise<string[]>;
23
+ numDownloads: () => Promise<number>;
22
24
  }
23
25
  export declare const memoryStore: MemoryStore;
24
26
  export {};
package/dist/types.d.ts CHANGED
@@ -11,9 +11,17 @@ export interface IClientStateStore {
11
11
  dequeueUpload: (sha256: string) => Promise<void>;
12
12
  peekUpload: (sha256: string) => Promise<Uint8Array | undefined>;
13
13
  listUploads: () => Promise<string[]>;
14
+ numUploads: () => Promise<number>;
14
15
  enqueueDownload: (path: string) => Promise<void>;
15
16
  dequeueDownload: (path: string) => Promise<void>;
16
17
  listDownloads: () => Promise<string[]>;
18
+ numDownloads: () => Promise<number>;
19
+ }
20
+ export interface IDiplomaticClientState {
21
+ hasSeed: boolean;
22
+ hasHost: boolean;
23
+ connected: boolean;
24
+ numUploads: number;
25
+ numDownloads: number;
17
26
  }
18
- export type DiplomaticClientState = "loading" | "seedless" | "hostless" | "ready";
19
27
  export type Applier = (op: IOp) => Promise<void>;
@@ -1,4 +1,4 @@
1
- import type { DiplomaticClientState } from "./types";
1
+ import type { IDiplomaticClientState } from "./types";
2
2
  import type DiplomaticClient from "./client";
3
- export declare function useClientState(client: DiplomaticClient): DiplomaticClientState;
3
+ export declare function useClientState(client: DiplomaticClient): IDiplomaticClientState | undefined;
4
4
  export declare function useSyncOnResume(client: DiplomaticClient): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@interncom/diplomatic",
3
- "version": "0.0.14",
3
+ "version": "0.0.16",
4
4
  "type": "module",
5
5
  "description": "Secure sync layer",
6
6
  "main": "dist/index.mjs",