@agora-sdk/secure-chat-react-js 0.1.0 → 0.2.0

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.
@@ -32,6 +32,8 @@ function createWebSecureChatCrypto() {
32
32
  processProposal: notImplemented,
33
33
  exportGroupState: notImplemented,
34
34
  importGroupState: notImplemented,
35
+ exportDeviceState: notImplemented,
36
+ importDeviceState: notImplemented,
35
37
  exportBackup: notImplemented,
36
38
  importBackup: notImplemented,
37
39
  };
@@ -1 +1 @@
1
- {"version":3,"file":"crypto-web.js","sourceRoot":"","sources":["../../src/crypto-web.ts"],"names":[],"mappings":";AAAA,gDAAgD;AAChD,EAAE;AACF,6FAA6F;AAC7F,kGAAkG;AAClG,oGAAoG;AACpG,mFAAmF;AACnF,EAAE;AACF,mGAAmG;AACnG,sFAAsF;;AAUtF,8DAoBC;AA1BD,MAAM,OAAO,GAAG,8EAA8E,CAAC;AAE/F;;;GAGG;AACH,SAAgB,yBAAyB;IACvC,MAAM,cAAc,GAAG,GAAU,EAAE;QACjC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC,CAAC;IACF,OAAO;QACL,sBAAsB,EAAE,cAAc;QACtC,mBAAmB,EAAE,cAAc;QACnC,WAAW,EAAE,cAAc;QAC3B,SAAS,EAAE,cAAc;QACzB,YAAY,EAAE,cAAc;QAC5B,cAAc,EAAE,cAAc;QAC9B,cAAc,EAAE,cAAc;QAC9B,cAAc,EAAE,cAAc;QAC9B,aAAa,EAAE,cAAc;QAC7B,eAAe,EAAE,cAAc;QAC/B,gBAAgB,EAAE,cAAc;QAChC,gBAAgB,EAAE,cAAc;QAChC,YAAY,EAAE,cAAc;QAC5B,YAAY,EAAE,cAAc;KAC7B,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"crypto-web.js","sourceRoot":"","sources":["../../src/crypto-web.ts"],"names":[],"mappings":";AAAA,gDAAgD;AAChD,EAAE;AACF,6FAA6F;AAC7F,kGAAkG;AAClG,oGAAoG;AACpG,mFAAmF;AACnF,EAAE;AACF,mGAAmG;AACnG,sFAAsF;;AAUtF,8DAsBC;AA5BD,MAAM,OAAO,GAAG,8EAA8E,CAAC;AAE/F;;;GAGG;AACH,SAAgB,yBAAyB;IACvC,MAAM,cAAc,GAAG,GAAU,EAAE;QACjC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC,CAAC;IACF,OAAO;QACL,sBAAsB,EAAE,cAAc;QACtC,mBAAmB,EAAE,cAAc;QACnC,WAAW,EAAE,cAAc;QAC3B,SAAS,EAAE,cAAc;QACzB,YAAY,EAAE,cAAc;QAC5B,cAAc,EAAE,cAAc;QAC9B,cAAc,EAAE,cAAc;QAC9B,cAAc,EAAE,cAAc;QAC9B,aAAa,EAAE,cAAc;QAC7B,eAAe,EAAE,cAAc;QAC/B,gBAAgB,EAAE,cAAc;QAChC,gBAAgB,EAAE,cAAc;QAChC,iBAAiB,EAAE,cAAc;QACjC,iBAAiB,EAAE,cAAc;QACjC,YAAY,EAAE,cAAc;QAC5B,YAAY,EAAE,cAAc;KAC7B,CAAC;AACJ,CAAC"}
@@ -1,2 +1,4 @@
1
1
  export * from "@agora-sdk/secure-chat-core";
2
- export { createWebSecureChatCrypto } from "./crypto-web";
2
+ export { createWebSecureChatCrypto } from "./crypto-web.js";
3
+ export { createIndexedDBStore } from "./indexeddb-store.js";
4
+ export type { IndexedDBStoreOptions } from "./indexeddb-store.js";
package/dist/cjs/index.js CHANGED
@@ -19,8 +19,10 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
19
19
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
20
20
  };
21
21
  Object.defineProperty(exports, "__esModule", { value: true });
22
- exports.createWebSecureChatCrypto = void 0;
22
+ exports.createIndexedDBStore = exports.createWebSecureChatCrypto = void 0;
23
23
  __exportStar(require("@agora-sdk/secure-chat-core"), exports);
24
- var crypto_web_1 = require("./crypto-web");
25
- Object.defineProperty(exports, "createWebSecureChatCrypto", { enumerable: true, get: function () { return crypto_web_1.createWebSecureChatCrypto; } });
24
+ var crypto_web_js_1 = require("./crypto-web.js");
25
+ Object.defineProperty(exports, "createWebSecureChatCrypto", { enumerable: true, get: function () { return crypto_web_js_1.createWebSecureChatCrypto; } });
26
+ var indexeddb_store_js_1 = require("./indexeddb-store.js");
27
+ Object.defineProperty(exports, "createIndexedDBStore", { enumerable: true, get: function () { return indexeddb_store_js_1.createIndexedDBStore; } });
26
28
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA,wEAAwE;AACxE,EAAE;AACF,iGAAiG;AACjG,kGAAkG;AAClG,8CAA8C;;;;;;;;;;;;;;;;;AAE9C,8DAA4C;AAE5C,2CAAyD;AAAhD,uHAAA,yBAAyB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA,wEAAwE;AACxE,EAAE;AACF,iGAAiG;AACjG,kGAAkG;AAClG,8CAA8C;;;;;;;;;;;;;;;;;AAE9C,8DAA4C;AAE5C,iDAA4D;AAAnD,0HAAA,yBAAyB,OAAA;AAClC,2DAA4D;AAAnD,0HAAA,oBAAoB,OAAA"}
@@ -0,0 +1,21 @@
1
+ import type { SecureChatStore } from "@agora-sdk/secure-chat-core";
2
+ /** Options for {@link createIndexedDBStore}. */
3
+ export interface IndexedDBStoreOptions {
4
+ /** Database name. Default `agora-secure-chat`. */
5
+ dbName?: string;
6
+ /** Object store name. Default `kv`. */
7
+ storeName?: string;
8
+ }
9
+ /**
10
+ * Create an IndexedDB-backed {@link SecureChatStore} for the web.
11
+ *
12
+ * @param opts - {@link IndexedDBStoreOptions} — database + object-store names.
13
+ * @returns A durable store; pass it to `<SecureChatProvider store={...}>`.
14
+ * @throws {Error} On first access when `indexedDB` is unavailable (SSR / disabled).
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * <SecureChatProvider store={createIndexedDBStore()} crypto={crypto} projectId={id} />
19
+ * ```
20
+ */
21
+ export declare function createIndexedDBStore(opts?: IndexedDBStoreOptions): SecureChatStore;
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ // Web SecureChatStore — IndexedDB-backed durable persistence.
3
+ //
4
+ // One object store keyed by string, value Uint8Array (structured-cloneable). Plaintext at rest for
5
+ // Phase 2 — IndexedDB is readable by any same-origin script; the threat model is "blind server", and
6
+ // passphrase backup (task 5) is the recovery path. The DB handle opens lazily on first use.
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.createIndexedDBStore = createIndexedDBStore;
9
+ function openDb(dbName, storeName) {
10
+ return new Promise((resolve, reject) => {
11
+ if (typeof indexedDB === "undefined") {
12
+ reject(new Error("IndexedDB is unavailable here; inject a different SecureChatStore (e.g. MemoryStore)."));
13
+ return;
14
+ }
15
+ const req = indexedDB.open(dbName, 1);
16
+ req.onupgradeneeded = () => {
17
+ const db = req.result;
18
+ if (!db.objectStoreNames.contains(storeName))
19
+ db.createObjectStore(storeName);
20
+ };
21
+ req.onsuccess = () => resolve(req.result);
22
+ req.onerror = () => reject(req.error);
23
+ req.onblocked = () => reject(new Error("IndexedDB open blocked by an existing connection — close other tabs and retry."));
24
+ });
25
+ }
26
+ function runTx(db, storeName, mode, fn) {
27
+ return new Promise((resolve, reject) => {
28
+ const tx = db.transaction(storeName, mode);
29
+ const req = fn(tx.objectStore(storeName));
30
+ tx.oncomplete = () => resolve(req.result);
31
+ tx.onerror = () => reject(tx.error);
32
+ tx.onabort = () => reject(tx.error);
33
+ });
34
+ }
35
+ /**
36
+ * Create an IndexedDB-backed {@link SecureChatStore} for the web.
37
+ *
38
+ * @param opts - {@link IndexedDBStoreOptions} — database + object-store names.
39
+ * @returns A durable store; pass it to `<SecureChatProvider store={...}>`.
40
+ * @throws {Error} On first access when `indexedDB` is unavailable (SSR / disabled).
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * <SecureChatProvider store={createIndexedDBStore()} crypto={crypto} projectId={id} />
45
+ * ```
46
+ */
47
+ function createIndexedDBStore(opts = {}) {
48
+ const dbName = opts.dbName ?? "agora-secure-chat";
49
+ const storeName = opts.storeName ?? "kv";
50
+ let dbPromise = null;
51
+ const db = () => (dbPromise ?? (dbPromise = openDb(dbName, storeName).catch((e) => {
52
+ dbPromise = null; // don't cache a rejection — allow a retry on the next call
53
+ throw e;
54
+ })));
55
+ return {
56
+ async get(key) {
57
+ const v = await runTx(await db(), storeName, "readonly", (s) => s.get(key));
58
+ return v ?? null;
59
+ },
60
+ async set(key, value) {
61
+ await runTx(await db(), storeName, "readwrite", (s) => s.put(value, key));
62
+ },
63
+ async delete(key) {
64
+ await runTx(await db(), storeName, "readwrite", (s) => s.delete(key));
65
+ },
66
+ async list(prefix) {
67
+ const keys = await runTx(await db(), storeName, "readonly", (s) => s.getAllKeys());
68
+ return keys.filter((k) => typeof k === "string" && k.startsWith(prefix));
69
+ },
70
+ };
71
+ }
72
+ //# sourceMappingURL=indexeddb-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexeddb-store.js","sourceRoot":"","sources":["../../src/indexeddb-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -29,6 +29,8 @@ export function createWebSecureChatCrypto() {
29
29
  processProposal: notImplemented,
30
30
  exportGroupState: notImplemented,
31
31
  importGroupState: notImplemented,
32
+ exportDeviceState: notImplemented,
33
+ importDeviceState: notImplemented,
32
34
  exportBackup: notImplemented,
33
35
  importBackup: notImplemented,
34
36
  };
@@ -1 +1 @@
1
- {"version":3,"file":"crypto-web.js","sourceRoot":"","sources":["../../src/crypto-web.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,EAAE;AACF,6FAA6F;AAC7F,kGAAkG;AAClG,oGAAoG;AACpG,mFAAmF;AACnF,EAAE;AACF,mGAAmG;AACnG,sFAAsF;AAItF,MAAM,OAAO,GAAG,8EAA8E,CAAC;AAE/F;;;GAGG;AACH,MAAM,UAAU,yBAAyB;IACvC,MAAM,cAAc,GAAG,GAAU,EAAE;QACjC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC,CAAC;IACF,OAAO;QACL,sBAAsB,EAAE,cAAc;QACtC,mBAAmB,EAAE,cAAc;QACnC,WAAW,EAAE,cAAc;QAC3B,SAAS,EAAE,cAAc;QACzB,YAAY,EAAE,cAAc;QAC5B,cAAc,EAAE,cAAc;QAC9B,cAAc,EAAE,cAAc;QAC9B,cAAc,EAAE,cAAc;QAC9B,aAAa,EAAE,cAAc;QAC7B,eAAe,EAAE,cAAc;QAC/B,gBAAgB,EAAE,cAAc;QAChC,gBAAgB,EAAE,cAAc;QAChC,YAAY,EAAE,cAAc;QAC5B,YAAY,EAAE,cAAc;KAC7B,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"crypto-web.js","sourceRoot":"","sources":["../../src/crypto-web.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,EAAE;AACF,6FAA6F;AAC7F,kGAAkG;AAClG,oGAAoG;AACpG,mFAAmF;AACnF,EAAE;AACF,mGAAmG;AACnG,sFAAsF;AAItF,MAAM,OAAO,GAAG,8EAA8E,CAAC;AAE/F;;;GAGG;AACH,MAAM,UAAU,yBAAyB;IACvC,MAAM,cAAc,GAAG,GAAU,EAAE;QACjC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC,CAAC;IACF,OAAO;QACL,sBAAsB,EAAE,cAAc;QACtC,mBAAmB,EAAE,cAAc;QACnC,WAAW,EAAE,cAAc;QAC3B,SAAS,EAAE,cAAc;QACzB,YAAY,EAAE,cAAc;QAC5B,cAAc,EAAE,cAAc;QAC9B,cAAc,EAAE,cAAc;QAC9B,cAAc,EAAE,cAAc;QAC9B,aAAa,EAAE,cAAc;QAC7B,eAAe,EAAE,cAAc;QAC/B,gBAAgB,EAAE,cAAc;QAChC,gBAAgB,EAAE,cAAc;QAChC,iBAAiB,EAAE,cAAc;QACjC,iBAAiB,EAAE,cAAc;QACjC,YAAY,EAAE,cAAc;QAC5B,YAAY,EAAE,cAAc;KAC7B,CAAC;AACJ,CAAC"}
@@ -1,2 +1,4 @@
1
1
  export * from "@agora-sdk/secure-chat-core";
2
- export { createWebSecureChatCrypto } from "./crypto-web";
2
+ export { createWebSecureChatCrypto } from "./crypto-web.js";
3
+ export { createIndexedDBStore } from "./indexeddb-store.js";
4
+ export type { IndexedDBStoreOptions } from "./indexeddb-store.js";
package/dist/esm/index.js CHANGED
@@ -4,5 +4,6 @@
4
4
  // MLS crypto + IndexedDB group-state persistence. Use this package (not core directly) in browser
5
5
  // apps so the right crypto/persistence ships.
6
6
  export * from "@agora-sdk/secure-chat-core";
7
- export { createWebSecureChatCrypto } from "./crypto-web";
7
+ export { createWebSecureChatCrypto } from "./crypto-web.js";
8
+ export { createIndexedDBStore } from "./indexeddb-store.js";
8
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,EAAE;AACF,iGAAiG;AACjG,kGAAkG;AAClG,8CAA8C;AAE9C,cAAc,6BAA6B,CAAC;AAE5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,EAAE;AACF,iGAAiG;AACjG,kGAAkG;AAClG,8CAA8C;AAE9C,cAAc,6BAA6B,CAAC;AAE5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { SecureChatStore } from "@agora-sdk/secure-chat-core";
2
+ /** Options for {@link createIndexedDBStore}. */
3
+ export interface IndexedDBStoreOptions {
4
+ /** Database name. Default `agora-secure-chat`. */
5
+ dbName?: string;
6
+ /** Object store name. Default `kv`. */
7
+ storeName?: string;
8
+ }
9
+ /**
10
+ * Create an IndexedDB-backed {@link SecureChatStore} for the web.
11
+ *
12
+ * @param opts - {@link IndexedDBStoreOptions} — database + object-store names.
13
+ * @returns A durable store; pass it to `<SecureChatProvider store={...}>`.
14
+ * @throws {Error} On first access when `indexedDB` is unavailable (SSR / disabled).
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * <SecureChatProvider store={createIndexedDBStore()} crypto={crypto} projectId={id} />
19
+ * ```
20
+ */
21
+ export declare function createIndexedDBStore(opts?: IndexedDBStoreOptions): SecureChatStore;
@@ -0,0 +1,69 @@
1
+ // Web SecureChatStore — IndexedDB-backed durable persistence.
2
+ //
3
+ // One object store keyed by string, value Uint8Array (structured-cloneable). Plaintext at rest for
4
+ // Phase 2 — IndexedDB is readable by any same-origin script; the threat model is "blind server", and
5
+ // passphrase backup (task 5) is the recovery path. The DB handle opens lazily on first use.
6
+ function openDb(dbName, storeName) {
7
+ return new Promise((resolve, reject) => {
8
+ if (typeof indexedDB === "undefined") {
9
+ reject(new Error("IndexedDB is unavailable here; inject a different SecureChatStore (e.g. MemoryStore)."));
10
+ return;
11
+ }
12
+ const req = indexedDB.open(dbName, 1);
13
+ req.onupgradeneeded = () => {
14
+ const db = req.result;
15
+ if (!db.objectStoreNames.contains(storeName))
16
+ db.createObjectStore(storeName);
17
+ };
18
+ req.onsuccess = () => resolve(req.result);
19
+ req.onerror = () => reject(req.error);
20
+ req.onblocked = () => reject(new Error("IndexedDB open blocked by an existing connection — close other tabs and retry."));
21
+ });
22
+ }
23
+ function runTx(db, storeName, mode, fn) {
24
+ return new Promise((resolve, reject) => {
25
+ const tx = db.transaction(storeName, mode);
26
+ const req = fn(tx.objectStore(storeName));
27
+ tx.oncomplete = () => resolve(req.result);
28
+ tx.onerror = () => reject(tx.error);
29
+ tx.onabort = () => reject(tx.error);
30
+ });
31
+ }
32
+ /**
33
+ * Create an IndexedDB-backed {@link SecureChatStore} for the web.
34
+ *
35
+ * @param opts - {@link IndexedDBStoreOptions} — database + object-store names.
36
+ * @returns A durable store; pass it to `<SecureChatProvider store={...}>`.
37
+ * @throws {Error} On first access when `indexedDB` is unavailable (SSR / disabled).
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * <SecureChatProvider store={createIndexedDBStore()} crypto={crypto} projectId={id} />
42
+ * ```
43
+ */
44
+ export function createIndexedDBStore(opts = {}) {
45
+ const dbName = opts.dbName ?? "agora-secure-chat";
46
+ const storeName = opts.storeName ?? "kv";
47
+ let dbPromise = null;
48
+ const db = () => (dbPromise ?? (dbPromise = openDb(dbName, storeName).catch((e) => {
49
+ dbPromise = null; // don't cache a rejection — allow a retry on the next call
50
+ throw e;
51
+ })));
52
+ return {
53
+ async get(key) {
54
+ const v = await runTx(await db(), storeName, "readonly", (s) => s.get(key));
55
+ return v ?? null;
56
+ },
57
+ async set(key, value) {
58
+ await runTx(await db(), storeName, "readwrite", (s) => s.put(value, key));
59
+ },
60
+ async delete(key) {
61
+ await runTx(await db(), storeName, "readwrite", (s) => s.delete(key));
62
+ },
63
+ async list(prefix) {
64
+ const keys = await runTx(await db(), storeName, "readonly", (s) => s.getAllKeys());
65
+ return keys.filter((k) => typeof k === "string" && k.startsWith(prefix));
66
+ },
67
+ };
68
+ }
69
+ //# sourceMappingURL=indexeddb-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexeddb-store.js","sourceRoot":"","sources":["../../src/indexeddb-store.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agora-sdk/secure-chat-react-js",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "private": false,
5
5
  "license": "Apache-2.0",
6
6
  "author": "Agora SDK Plus, maintained by Jenova Marie",
@@ -34,16 +34,19 @@
34
34
  "dist"
35
35
  ],
36
36
  "dependencies": {
37
- "@agora-sdk/secure-chat-core": "0.1.0"
37
+ "@agora-sdk/secure-chat-core": "0.2.0"
38
38
  },
39
39
  "peerDependencies": {
40
40
  "@agora-sdk/core": "^1.2.2",
41
41
  "react": "^18.0.0 || ^19.0.0",
42
42
  "react-dom": "^18.0.0 || ^19.0.0"
43
43
  },
44
+ "devDependencies": {
45
+ "fake-indexeddb": "^6.2.5"
46
+ },
44
47
  "scripts": {
45
48
  "build:esm": "tsc -p tsconfig.esm.json",
46
- "build:cjs": "tsc -p tsconfig.cjs.json",
49
+ "build:cjs": "tsc -p tsconfig.cjs.json && echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json",
47
50
  "build": "rimraf dist && pnpm run build:esm && pnpm run build:cjs",
48
51
  "prepublish": "pnpm run build"
49
52
  }