@interncom/diplomatic 0.0.0 → 0.0.2

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/README.md CHANGED
@@ -5,7 +5,7 @@ Secure sync layer for web apps.
5
5
  ## Usage
6
6
 
7
7
  ```tsx
8
- import { useClient, StateManager, useStateWatcher } from '@interncom/diplomatic'
8
+ import { StateManager, useStateWatcher, localStorageStore, DiplomaticClient } from '@interncom/diplomatic'
9
9
 
10
10
  const appState = { count: 0 };
11
11
  const stateMgr = new StateManager(async (op) => {
@@ -14,21 +14,27 @@ const stateMgr = new StateManager(async (op) => {
14
14
  }
15
15
  })
16
16
 
17
+ const client = new DiplomaticClient({
18
+ seed: "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF",
19
+ hostURL: "https://diplomatic-cloudflare-host.root-a00.workers.dev",
20
+ stateManager: stateMgr,
21
+ store: localStorageStore,
22
+ });
23
+
17
24
  export default function App() {
18
- const [client] = useClient({
19
- seed: "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF",
20
- hostURL: "https://diplomatic-cloudflare-host.root-a00.workers.dev",
21
- stateManager: stateMgr,
22
- })
23
25
  const count = useStateWatcher(stateMgr, "count", () => appState.count)
24
26
  const inc = () => client.upsert("count", count + 1)
25
27
 
26
28
  return (
27
- <>
29
+ <div style={{ width: "100vw", textAlign: "center" }}>
28
30
  <h1>COUNT</h1>
29
31
  <h2>{count}</h2>
30
- <button type="button" onClick={inc}>+1</button>
31
- </>
32
+ <button onClick={inc}>+1</button>
33
+ </div>
32
34
  )
33
35
  }
34
36
  ```
37
+
38
+ ## Development
39
+
40
+ To deploy npm package: `npm publish --public`.
package/dist/client.d.ts CHANGED
@@ -18,6 +18,8 @@ export default class DiplomaticClient {
18
18
  hostKeyPair?: KeyPair;
19
19
  lastFetchedAt?: string;
20
20
  constructor(params: IDiplomaticClientParams);
21
+ websocket?: WebSocket;
22
+ connect: (hostURL: URL) => Promise<void>;
21
23
  init(params: IDiplomaticClientParams): Promise<void>;
22
24
  loadSeed(): Promise<void>;
23
25
  setSeed(seed: Uint8Array): Promise<void>;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  import useClient from "./useClient";
2
2
  import { StateManager, useStateWatcher } from './state';
3
- export { useClient, StateManager, useStateWatcher, };
3
+ import { localStorageStore } from "./localStorageStore";
4
+ import DiplomaticClient from "./client";
5
+ export { useClient, StateManager, useStateWatcher, localStorageStore, DiplomaticClient, };
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ var __export = (target, all) => {
11
11
  };
12
12
 
13
13
  // src/useClient.ts
14
- import { useState, useEffect as useEffect2, useCallback } from "react";
14
+ import { useState, useEffect as useEffect2, useCallback, useMemo } from "react";
15
15
 
16
16
  // node_modules/@msgpack/msgpack/dist.es5+esm/utils/utf8.mjs
17
17
  function utf8Count(str) {
@@ -8288,7 +8288,7 @@ var msgpack = {
8288
8288
  var webClientAPI = new DiplomaticClientAPI(msgpack, crypto_default);
8289
8289
  var api_default = webClientAPI;
8290
8290
 
8291
- // src/ops.ts
8291
+ // ../shared/ops.ts
8292
8292
  function genUpsertOp(type, body, version = 0) {
8293
8293
  return {
8294
8294
  ts: (/* @__PURE__ */ new Date()).toISOString(),
@@ -8314,6 +8314,31 @@ var DiplomaticClient = class {
8314
8314
  this.applier = params.stateManager.apply;
8315
8315
  this.init(params);
8316
8316
  }
8317
+ websocket;
8318
+ connect = async (hostURL) => {
8319
+ if (!this.hostKeyPair) {
8320
+ return;
8321
+ }
8322
+ const url = new URL(hostURL);
8323
+ url.protocol = "ws";
8324
+ const keyHex = btoh(this.hostKeyPair?.publicKey);
8325
+ url.searchParams.set("key", keyHex);
8326
+ this.websocket = new WebSocket(url);
8327
+ this.websocket.onopen = (e) => {
8328
+ console.log("CONNECTED");
8329
+ };
8330
+ this.websocket.onclose = (e) => {
8331
+ console.log("DISCONNECTED");
8332
+ this.connect(hostURL);
8333
+ };
8334
+ this.websocket.onmessage = (e) => {
8335
+ console.log(`RECEIVED: ${e.data}`);
8336
+ this.processDeltas();
8337
+ };
8338
+ this.websocket.onerror = (e) => {
8339
+ console.log(`ERROR: ${e}`);
8340
+ };
8341
+ };
8317
8342
  async init(params) {
8318
8343
  await this.store.init?.();
8319
8344
  if (params.seed) {
@@ -8329,6 +8354,10 @@ var DiplomaticClient = class {
8329
8354
  } else {
8330
8355
  await this.loadHost();
8331
8356
  }
8357
+ if (this.hostURL) {
8358
+ await this.connect(this.hostURL);
8359
+ }
8360
+ await this.processDeltas();
8332
8361
  this.listener?.(this.state);
8333
8362
  }
8334
8363
  async loadSeed() {
@@ -8524,14 +8553,19 @@ var localStorageStore = new LocalStorageStore();
8524
8553
  var initialState = "loading";
8525
8554
  function useClient(params) {
8526
8555
  const [state, setState] = useState(initialState);
8527
- const [client, setClient] = useState(new DiplomaticClient({ store: localStorageStore, ...params }));
8556
+ console.log("rendering useClient");
8557
+ const fullParams = useMemo(
8558
+ () => ({ store: localStorageStore, ...params }),
8559
+ [params]
8560
+ );
8561
+ const [client, setClient] = useState(new DiplomaticClient(fullParams));
8528
8562
  useEffect2(() => {
8529
8563
  client.listener = setState;
8530
8564
  }, [client]);
8531
8565
  const reset = useCallback(() => {
8532
- setClient(new DiplomaticClient({ store: localStorageStore, ...params }));
8566
+ setClient(new DiplomaticClient(fullParams));
8533
8567
  setState(initialState);
8534
- }, [params]);
8568
+ }, [fullParams]);
8535
8569
  usePollingSync(client, params.refreshInterval ?? 1e3);
8536
8570
  return [client, state, reset];
8537
8571
  }
@@ -8594,7 +8628,9 @@ function useStateWatcher(mgr, opType, callback) {
8594
8628
  return val;
8595
8629
  }
8596
8630
  export {
8631
+ DiplomaticClient,
8597
8632
  StateManager,
8633
+ localStorageStore,
8598
8634
  useClient,
8599
8635
  useStateWatcher
8600
8636
  };
@@ -0,0 +1,3 @@
1
+ import { type IOp } from './types.ts';
2
+ export declare function genUpsertOp<T>(type: string, body: T, version?: number): IOp;
3
+ export declare function isOp(op: any): op is IOp;
@@ -1,11 +1,12 @@
1
- import type { IHostCrypto, IMsgpackCodec, IStorage } from "./types.ts";
1
+ import type { IHostCrypto, IMsgpackCodec, IStorage, IWebsocketNotifier } from "./types.ts";
2
2
  export declare class DiplomaticServer {
3
3
  hostID: string;
4
4
  regToken: string;
5
5
  storage: IStorage;
6
6
  codec: IMsgpackCodec;
7
7
  crypto: IHostCrypto;
8
- constructor(hostID: string, regToken: string, storage: IStorage, codec: IMsgpackCodec, crypto: IHostCrypto);
8
+ notifier: IWebsocketNotifier;
9
+ constructor(hostID: string, regToken: string, storage: IStorage, codec: IMsgpackCodec, crypto: IHostCrypto, notifier: IWebsocketNotifier);
9
10
  corsHandler: (request: Request) => Promise<Response>;
10
11
  handler: (request: Request) => Promise<Response>;
11
12
  }
@@ -55,4 +55,8 @@ export interface IMsgpackCodec {
55
55
  decode: (packed: ArrayBuffer | Uint8Array) => unknown;
56
56
  decodeAsync: (stream: ReadableStream<Uint8Array>) => Promise<unknown>;
57
57
  }
58
+ export interface IWebsocketNotifier {
59
+ handler: (request: Request, hasUser: (pubKeyHex: string) => Promise<boolean>) => Promise<Response>;
60
+ notify: (pubKeyHex: string) => Promise<void>;
61
+ }
58
62
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@interncom/diplomatic",
3
- "version": "0.0.0",
3
+ "version": "0.0.2",
4
4
  "type": "module",
5
5
  "description": "Secure sync layer",
6
6
  "main": "dist/index.js",