@vex-chat/libvex 1.0.1 → 1.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.
Files changed (58) hide show
  1. package/dist/Client.d.ts +12 -8
  2. package/dist/Client.js +131 -74
  3. package/dist/Client.js.map +1 -1
  4. package/dist/IStorage.d.ts +1 -1
  5. package/dist/IStorage.js +1 -1
  6. package/dist/IStorage.js.map +1 -1
  7. package/dist/__tests__/harness/memory-storage.d.ts +45 -0
  8. package/dist/__tests__/harness/memory-storage.js +181 -0
  9. package/dist/__tests__/harness/memory-storage.js.map +1 -0
  10. package/dist/index.d.ts +3 -0
  11. package/dist/keystore/memory.d.ts +11 -0
  12. package/dist/keystore/memory.js +18 -0
  13. package/dist/keystore/memory.js.map +1 -0
  14. package/dist/keystore/node.d.ts +10 -0
  15. package/dist/keystore/node.js +64 -0
  16. package/dist/keystore/node.js.map +1 -0
  17. package/dist/keystore/types.d.ts +4 -0
  18. package/dist/keystore/types.js +2 -0
  19. package/dist/keystore/types.js.map +1 -0
  20. package/dist/preset/expo.d.ts +2 -0
  21. package/dist/preset/expo.js +37 -0
  22. package/dist/preset/expo.js.map +1 -0
  23. package/dist/preset/node.d.ts +12 -0
  24. package/dist/preset/node.js +16 -0
  25. package/dist/preset/node.js.map +1 -0
  26. package/dist/preset/tauri.d.ts +2 -0
  27. package/dist/preset/tauri.js +35 -0
  28. package/dist/preset/tauri.js.map +1 -0
  29. package/dist/preset/test.d.ts +10 -0
  30. package/dist/preset/test.js +28 -0
  31. package/dist/preset/test.js.map +1 -0
  32. package/dist/preset/types.d.ts +13 -0
  33. package/dist/preset/types.js +2 -0
  34. package/dist/preset/types.js.map +1 -0
  35. package/dist/storage/expo.d.ts +3 -0
  36. package/dist/storage/expo.js +18 -0
  37. package/dist/storage/expo.js.map +1 -0
  38. package/dist/storage/node.d.ts +3 -0
  39. package/dist/storage/node.js +24 -0
  40. package/dist/storage/node.js.map +1 -0
  41. package/dist/storage/schema.d.ts +79 -0
  42. package/dist/storage/schema.js +2 -0
  43. package/dist/storage/schema.js.map +1 -0
  44. package/dist/{Storage.d.ts → storage/sqlite.d.ts} +19 -21
  45. package/dist/storage/sqlite.js +487 -0
  46. package/dist/storage/sqlite.js.map +1 -0
  47. package/dist/storage/tauri.d.ts +3 -0
  48. package/dist/storage/tauri.js +21 -0
  49. package/dist/storage/tauri.js.map +1 -0
  50. package/dist/transport/browser.d.ts +17 -0
  51. package/dist/transport/browser.js +56 -0
  52. package/dist/transport/browser.js.map +1 -0
  53. package/dist/transport/types.d.ts +20 -0
  54. package/dist/transport/types.js +2 -0
  55. package/dist/transport/types.js.map +1 -0
  56. package/package.json +102 -14
  57. package/dist/Storage.js +0 -444
  58. package/dist/Storage.js.map +0 -1
@@ -0,0 +1,487 @@
1
+ /**
2
+ * Unified Kysely-based SQLite storage implementation.
3
+ *
4
+ * Accepts any `Kysely<ClientDatabase>` instance — the caller picks the
5
+ * dialect (better-sqlite3, Tauri plugin-sql, expo-sqlite, etc.) and
6
+ * passes the configured Kysely handle here.
7
+ *
8
+ * This replaces three separate storage classes (Storage.ts, TauriStorage,
9
+ * ExpoStorage) with a single implementation.
10
+ */
11
+ import { XKeyConvert, XUtils } from "@vex-chat/crypto";
12
+ import { EventEmitter } from "eventemitter3";
13
+ import nacl from "tweetnacl";
14
+ export class SqliteStorage extends EventEmitter {
15
+ ready = false;
16
+ closing = false;
17
+ db;
18
+ log;
19
+ idKeys;
20
+ constructor(db, SK, logger) {
21
+ super();
22
+ this.db = db;
23
+ this.log = logger;
24
+ const idKeys = XKeyConvert.convertKeyPair(nacl.sign.keyPair.fromSecretKey(XUtils.decodeHex(SK)));
25
+ if (!idKeys) {
26
+ throw new Error("Can't convert SK!");
27
+ }
28
+ this.idKeys = idKeys;
29
+ }
30
+ // ── Lifecycle ────────────────────────────────────────────────────────────
31
+ async init() {
32
+ this.log.info("Initializing database tables.");
33
+ try {
34
+ await this.db.schema
35
+ .createTable("messages")
36
+ .ifNotExists()
37
+ .addColumn("nonce", "text", (col) => col.primaryKey())
38
+ .addColumn("sender", "text")
39
+ .addColumn("recipient", "text")
40
+ .addColumn("group", "text")
41
+ .addColumn("mailID", "text")
42
+ .addColumn("message", "text")
43
+ .addColumn("direction", "text")
44
+ .addColumn("timestamp", "text")
45
+ .addColumn("decrypted", "integer")
46
+ .addColumn("forward", "integer")
47
+ .addColumn("authorID", "text")
48
+ .addColumn("readerID", "text")
49
+ .execute();
50
+ await this.db.schema
51
+ .createTable("devices")
52
+ .ifNotExists()
53
+ .addColumn("deviceID", "text", (col) => col.primaryKey())
54
+ .addColumn("owner", "text")
55
+ .addColumn("signKey", "text")
56
+ .addColumn("name", "text")
57
+ .addColumn("lastLogin", "text")
58
+ .addColumn("deleted", "integer")
59
+ .execute();
60
+ await this.db.schema
61
+ .createTable("sessions")
62
+ .ifNotExists()
63
+ .addColumn("sessionID", "text", (col) => col.primaryKey())
64
+ .addColumn("userID", "text")
65
+ .addColumn("deviceID", "text")
66
+ .addColumn("SK", "text", (col) => col.unique())
67
+ .addColumn("publicKey", "text")
68
+ .addColumn("fingerprint", "text")
69
+ .addColumn("mode", "text")
70
+ .addColumn("lastUsed", "text")
71
+ .addColumn("verified", "integer")
72
+ .execute();
73
+ await this.db.schema
74
+ .createTable("preKeys")
75
+ .ifNotExists()
76
+ .addColumn("index", "integer", (col) => col.primaryKey().autoIncrement())
77
+ .addColumn("keyID", "text", (col) => col.unique())
78
+ .addColumn("userID", "text")
79
+ .addColumn("deviceID", "text")
80
+ .addColumn("privateKey", "text")
81
+ .addColumn("publicKey", "text")
82
+ .addColumn("signature", "text")
83
+ .execute();
84
+ await this.db.schema
85
+ .createTable("oneTimeKeys")
86
+ .ifNotExists()
87
+ .addColumn("index", "integer", (col) => col.primaryKey().autoIncrement())
88
+ .addColumn("keyID", "text", (col) => col.unique())
89
+ .addColumn("userID", "text")
90
+ .addColumn("deviceID", "text")
91
+ .addColumn("privateKey", "text")
92
+ .addColumn("publicKey", "text")
93
+ .addColumn("signature", "text")
94
+ .execute();
95
+ this.ready = true;
96
+ this.emit("ready");
97
+ }
98
+ catch (err) {
99
+ this.emit("error", err);
100
+ }
101
+ }
102
+ async close() {
103
+ this.closing = true;
104
+ this.log.info("Closing database.");
105
+ await this.db.destroy();
106
+ }
107
+ // ── Messages ─────────────────────────────────────────────────────────────
108
+ async saveMessage(message) {
109
+ if (this.closing) {
110
+ this.log.warn("Database is closing, saveMessage() will not complete.");
111
+ return;
112
+ }
113
+ // Encrypt plaintext with our idkey before saving to disk
114
+ const encryptedMessage = XUtils.encodeHex(nacl.secretbox(XUtils.decodeUTF8(message.message), XUtils.decodeHex(message.nonce), this.idKeys.secretKey));
115
+ try {
116
+ await this.db
117
+ .insertInto("messages")
118
+ .values({
119
+ nonce: message.nonce,
120
+ sender: message.sender,
121
+ recipient: message.recipient,
122
+ group: message.group ?? null,
123
+ mailID: message.mailID,
124
+ message: encryptedMessage,
125
+ direction: message.direction,
126
+ timestamp: message.timestamp instanceof Date
127
+ ? message.timestamp.toISOString()
128
+ : String(message.timestamp),
129
+ decrypted: message.decrypted ? 1 : 0,
130
+ forward: message.forward ? 1 : 0,
131
+ authorID: message.authorID,
132
+ readerID: message.readerID,
133
+ })
134
+ .execute();
135
+ }
136
+ catch (err) {
137
+ // SQLite UNIQUE constraint violation
138
+ if (err?.errno === 19 || err?.message?.includes("UNIQUE")) {
139
+ this.log.warn("Attempted to insert duplicate nonce into message table.");
140
+ }
141
+ else {
142
+ throw err;
143
+ }
144
+ }
145
+ }
146
+ async deleteMessage(mailID) {
147
+ if (this.closing) {
148
+ this.log.warn("Database is closing, deleteMessage() will not complete.");
149
+ return;
150
+ }
151
+ await this.db
152
+ .deleteFrom("messages")
153
+ .where("mailID", "=", mailID)
154
+ .execute();
155
+ }
156
+ async getMessageHistory(userID) {
157
+ if (this.closing) {
158
+ this.log.warn("Database is closing, getMessageHistory() will not complete.");
159
+ return [];
160
+ }
161
+ const messages = await this.db
162
+ .selectFrom("messages")
163
+ .selectAll()
164
+ .where((eb) => eb.or([
165
+ eb.and([
166
+ eb("direction", "=", "incoming"),
167
+ eb("authorID", "=", userID),
168
+ eb("group", "is", null),
169
+ ]),
170
+ eb.and([
171
+ eb("direction", "=", "outgoing"),
172
+ eb("readerID", "=", userID),
173
+ eb("group", "is", null),
174
+ ]),
175
+ ]))
176
+ .orderBy("timestamp", "asc")
177
+ .execute();
178
+ return this.decryptMessages(messages);
179
+ }
180
+ async getGroupHistory(channelID) {
181
+ if (this.closing) {
182
+ this.log.warn("Database is closing, getGroupHistory() will not complete.");
183
+ return [];
184
+ }
185
+ const messages = await this.db
186
+ .selectFrom("messages")
187
+ .selectAll()
188
+ .where("group", "=", channelID)
189
+ .orderBy("timestamp", "asc")
190
+ .execute();
191
+ return this.decryptMessages(messages);
192
+ }
193
+ async deleteHistory(channelOrUserID, _olderThan) {
194
+ await this.db
195
+ .deleteFrom("messages")
196
+ .where((eb) => eb.or([
197
+ eb("group", "=", channelOrUserID),
198
+ eb.and([
199
+ eb("group", "is", null),
200
+ eb("authorID", "=", channelOrUserID),
201
+ ]),
202
+ eb.and([
203
+ eb("group", "is", null),
204
+ eb("readerID", "=", channelOrUserID),
205
+ ]),
206
+ ]))
207
+ .execute();
208
+ }
209
+ async purgeHistory() {
210
+ await this.db.deleteFrom("messages").execute();
211
+ }
212
+ // ── Sessions ─────────────────────────────────────────────────────────────
213
+ async markSessionVerified(sessionID) {
214
+ if (this.closing) {
215
+ this.log.warn("Database is closing, markSessionVerified() will not complete.");
216
+ return;
217
+ }
218
+ await this.db
219
+ .updateTable("sessions")
220
+ .set({ verified: 1 })
221
+ .where("sessionID", "=", sessionID)
222
+ .execute();
223
+ }
224
+ async markSessionUsed(sessionID) {
225
+ if (this.closing) {
226
+ this.log.warn("Database is closing, markSessionUsed() will not complete.");
227
+ return;
228
+ }
229
+ await this.db
230
+ .updateTable("sessions")
231
+ .set({ lastUsed: new Date(Date.now()).toISOString() })
232
+ .where("sessionID", "=", sessionID)
233
+ .execute();
234
+ }
235
+ async getSessionByPublicKey(publicKey) {
236
+ if (this.closing) {
237
+ this.log.warn("Database is closing, getSessionByPublicKey() will not complete.");
238
+ return null;
239
+ }
240
+ const hex = XUtils.encodeHex(publicKey);
241
+ const rows = await this.db
242
+ .selectFrom("sessions")
243
+ .selectAll()
244
+ .where("publicKey", "=", hex)
245
+ .limit(1)
246
+ .execute();
247
+ if (rows.length === 0) {
248
+ this.log.warn(`getSessionByPublicKey(${hex}) => ${JSON.stringify(null)}`);
249
+ return null;
250
+ }
251
+ return this.sqlToCrypto(rows[0]);
252
+ }
253
+ async getAllSessions() {
254
+ if (this.closing) {
255
+ this.log.warn("Database is closing, getAllSessions() will not complete.");
256
+ return [];
257
+ }
258
+ const rows = await this.db
259
+ .selectFrom("sessions")
260
+ .selectAll()
261
+ .orderBy("lastUsed", "desc")
262
+ .execute();
263
+ return rows.map((s) => ({
264
+ ...s,
265
+ verified: Boolean(s.verified),
266
+ }));
267
+ }
268
+ async getSessionByDeviceID(deviceID) {
269
+ if (this.closing) {
270
+ this.log.warn("Database is closing, getSessionByDeviceID() will not complete.");
271
+ return null;
272
+ }
273
+ const rows = await this.db
274
+ .selectFrom("sessions")
275
+ .selectAll()
276
+ .where("deviceID", "=", deviceID)
277
+ .orderBy("lastUsed", "desc")
278
+ .limit(1)
279
+ .execute();
280
+ if (rows.length === 0) {
281
+ this.log.debug("getSession() => " + JSON.stringify(null));
282
+ return null;
283
+ }
284
+ return this.sqlToCrypto(rows[0]);
285
+ }
286
+ async saveSession(session) {
287
+ if (this.closing) {
288
+ this.log.warn("Database is closing, saveSession() will not complete.");
289
+ return;
290
+ }
291
+ try {
292
+ await this.db
293
+ .insertInto("sessions")
294
+ .values({
295
+ sessionID: session.sessionID,
296
+ userID: session.userID,
297
+ deviceID: session.deviceID,
298
+ SK: session.SK,
299
+ publicKey: session.publicKey,
300
+ fingerprint: session.fingerprint,
301
+ mode: session.mode,
302
+ lastUsed: session.lastUsed instanceof Date
303
+ ? session.lastUsed.toISOString()
304
+ : String(session.lastUsed),
305
+ verified: session.verified ? 1 : 0,
306
+ })
307
+ .execute();
308
+ }
309
+ catch (err) {
310
+ if (err?.errno === 19 || err?.message?.includes("UNIQUE")) {
311
+ this.log.warn("Attempted to insert duplicate SK");
312
+ }
313
+ else {
314
+ throw err;
315
+ }
316
+ }
317
+ }
318
+ // ── PreKeys / OneTimeKeys ────────────────────────────────────────────────
319
+ async savePreKeys(preKeys, oneTime) {
320
+ await this.untilReady();
321
+ if (this.closing) {
322
+ this.log.warn("Database is closing, savePreKeys() will not complete.");
323
+ return [];
324
+ }
325
+ const table = oneTime ? "oneTimeKeys" : "preKeys";
326
+ const addedIndexes = [];
327
+ for (const preKey of preKeys) {
328
+ const result = await this.db
329
+ .insertInto(table)
330
+ .values({
331
+ privateKey: XUtils.encodeHex(preKey.keyPair.secretKey),
332
+ publicKey: XUtils.encodeHex(preKey.keyPair.publicKey),
333
+ signature: XUtils.encodeHex(preKey.signature),
334
+ })
335
+ .executeTakeFirst();
336
+ if (result.insertId !== undefined) {
337
+ addedIndexes.push(Number(result.insertId));
338
+ }
339
+ }
340
+ const rows = await this.db
341
+ .selectFrom(table)
342
+ .selectAll()
343
+ .where("index", "in", addedIndexes)
344
+ .execute();
345
+ return rows.map((key) => {
346
+ delete key.privateKey;
347
+ return key;
348
+ });
349
+ }
350
+ async getPreKeys() {
351
+ await this.untilReady();
352
+ if (this.closing) {
353
+ this.log.warn("Database is closing, getPreKeys() will not complete.");
354
+ return null;
355
+ }
356
+ const rows = await this.db.selectFrom("preKeys").selectAll().execute();
357
+ if (rows.length === 0) {
358
+ this.log.debug("getPreKeys() => " + JSON.stringify(null));
359
+ return null;
360
+ }
361
+ const preKeyInfo = rows[0];
362
+ return {
363
+ keyPair: nacl.box.keyPair.fromSecretKey(XUtils.decodeHex(preKeyInfo.privateKey)),
364
+ signature: XUtils.decodeHex(preKeyInfo.signature),
365
+ };
366
+ }
367
+ async getOneTimeKey(index) {
368
+ await this.untilReady();
369
+ if (this.closing) {
370
+ this.log.warn("Database is closing, getOneTimeKey() will not complete.");
371
+ return null;
372
+ }
373
+ const rows = await this.db
374
+ .selectFrom("oneTimeKeys")
375
+ .selectAll()
376
+ .where("index", "=", index)
377
+ .execute();
378
+ if (rows.length === 0) {
379
+ this.log.debug("getOneTimeKey() => " + JSON.stringify(null));
380
+ return null;
381
+ }
382
+ const otkInfo = rows[0];
383
+ return {
384
+ keyPair: nacl.box.keyPair.fromSecretKey(XUtils.decodeHex(otkInfo.privateKey)),
385
+ signature: XUtils.decodeHex(otkInfo.signature),
386
+ index: otkInfo.index,
387
+ };
388
+ }
389
+ async deleteOneTimeKey(index) {
390
+ if (this.closing) {
391
+ this.log.warn("Database is closing, deleteOneTimeKey() will not complete.");
392
+ return;
393
+ }
394
+ await this.db
395
+ .deleteFrom("oneTimeKeys")
396
+ .where("index", "=", index)
397
+ .execute();
398
+ }
399
+ // ── Devices ──────────────────────────────────────────────────────────────
400
+ async getDevice(deviceID) {
401
+ const rows = await this.db
402
+ .selectFrom("devices")
403
+ .selectAll()
404
+ .where("deviceID", "=", deviceID)
405
+ .execute();
406
+ if (rows.length === 0) {
407
+ return null;
408
+ }
409
+ return rows[0];
410
+ }
411
+ async saveDevice(device) {
412
+ if (this.closing) {
413
+ this.log.warn("Database is closing, saveDevice() will not complete.");
414
+ return;
415
+ }
416
+ try {
417
+ await this.db
418
+ .insertInto("devices")
419
+ .values({
420
+ deviceID: device.deviceID,
421
+ owner: device.owner,
422
+ signKey: device.signKey,
423
+ name: device.name,
424
+ lastLogin: device.lastLogin,
425
+ deleted: device.deleted ? 1 : 0,
426
+ })
427
+ .execute();
428
+ }
429
+ catch (err) {
430
+ if (err?.errno === 19 || err?.message?.includes("UNIQUE")) {
431
+ this.log.warn("Attempted to insert duplicate deviceID");
432
+ }
433
+ else {
434
+ throw err;
435
+ }
436
+ }
437
+ }
438
+ // ── Purge ────────────────────────────────────────────────────────────────
439
+ async purgeKeyData() {
440
+ await this.db.deleteFrom("sessions").execute();
441
+ await this.db.deleteFrom("oneTimeKeys").execute();
442
+ await this.db.deleteFrom("preKeys").execute();
443
+ await this.db.deleteFrom("messages").execute();
444
+ }
445
+ // ── Private helpers ──────────────────────────────────────────────────────
446
+ decryptMessages(messages) {
447
+ return messages.map((msg) => {
448
+ msg.timestamp = new Date(msg.timestamp);
449
+ msg.decrypted = Boolean(msg.decrypted);
450
+ msg.forward = Boolean(msg.forward);
451
+ if (msg.decrypted) {
452
+ const decrypted = nacl.secretbox.open(XUtils.decodeHex(msg.message), XUtils.decodeHex(msg.nonce), this.idKeys.secretKey);
453
+ if (decrypted) {
454
+ msg.message = XUtils.encodeUTF8(decrypted);
455
+ }
456
+ else {
457
+ throw new Error("Couldn't decrypt messages on disk!");
458
+ }
459
+ }
460
+ return msg;
461
+ });
462
+ }
463
+ sqlToCrypto(session) {
464
+ return {
465
+ sessionID: session.sessionID,
466
+ userID: session.userID,
467
+ mode: session.mode,
468
+ SK: XUtils.decodeHex(session.SK),
469
+ publicKey: XUtils.decodeHex(session.publicKey),
470
+ lastUsed: session.lastUsed,
471
+ fingerprint: XUtils.decodeHex(session.fingerprint),
472
+ };
473
+ }
474
+ async untilReady() {
475
+ if (this.ready)
476
+ return;
477
+ return new Promise((resolve) => {
478
+ const check = () => {
479
+ if (this.ready)
480
+ return resolve();
481
+ setTimeout(check, 10);
482
+ };
483
+ check();
484
+ });
485
+ }
486
+ }
487
+ //# sourceMappingURL=sqlite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../src/storage/sqlite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { IStorage } from "../IStorage.js";
2
+ import type { ILogger } from "../transport/types.js";
3
+ export declare function createTauriStorage(dbName: string, SK: string, logger: ILogger): Promise<IStorage>;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Tauri storage factory — creates SqliteStorage with kysely-dialect-tauri.
3
+ *
4
+ * @tauri-apps/plugin-sql and kysely-dialect-tauri are peerDependencies —
5
+ * only available inside a Tauri app.
6
+ */
7
+ import { Kysely } from "kysely";
8
+ import { SqliteStorage } from "./sqlite.js";
9
+ export async function createTauriStorage(dbName, SK, logger) {
10
+ const { TauriSqliteDialect } = await import("kysely-dialect-tauri");
11
+ const { default: Database } = await import("@tauri-apps/plugin-sql");
12
+ const db = new Kysely({
13
+ dialect: new TauriSqliteDialect({
14
+ database: () => Database.load(`sqlite:${dbName}`),
15
+ }),
16
+ });
17
+ const storage = new SqliteStorage(db, SK, logger);
18
+ await storage.init();
19
+ return storage;
20
+ }
21
+ //# sourceMappingURL=tauri.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tauri.js","sourceRoot":"","sources":["../../src/storage/tauri.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAI5C,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACpC,MAAc,EACd,EAAU,EACV,MAAe;IAEf,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;IACpE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;IACrE,MAAM,EAAE,GAAG,IAAI,MAAM,CAAiB;QAClC,OAAO,EAAE,IAAI,kBAAkB,CAAC;YAC5B,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,MAAM,EAAE,CAAC;SACpD,CAAQ;KACZ,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,IAAI,aAAa,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;IAClD,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;IACrB,OAAO,OAAO,CAAC;AACnB,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Wraps the browser's native WebSocket to match the IWebSocketLike interface
3
+ * expected by Client. Used by Tauri (webview) and future web builds.
4
+ */
5
+ import type { IWebSocketLike } from "./types.js";
6
+ export declare class BrowserWebSocket implements IWebSocketLike {
7
+ private ws;
8
+ private listeners;
9
+ onerror: ((err: any) => void) | null;
10
+ constructor(url: string, _options?: object);
11
+ get readyState(): 0 | 1 | 2 | 3;
12
+ on(event: string, listener: (...args: any[]) => void): void;
13
+ off(event: string, listener: (...args: any[]) => void): void;
14
+ send(data: any): void;
15
+ close(): void;
16
+ terminate(): void;
17
+ }
@@ -0,0 +1,56 @@
1
+ export class BrowserWebSocket {
2
+ ws;
3
+ listeners = new Map();
4
+ onerror = null;
5
+ constructor(url, _options) {
6
+ this.ws = new globalThis.WebSocket(url);
7
+ this.ws.binaryType = "arraybuffer";
8
+ this.ws.onerror = (ev) => this.onerror?.(ev);
9
+ }
10
+ get readyState() {
11
+ return this.ws.readyState;
12
+ }
13
+ on(event, listener) {
14
+ let wrapped;
15
+ if (event === "message") {
16
+ // Browser WebSocket wraps data in MessageEvent — unwrap to Uint8Array
17
+ wrapped = (ev) => {
18
+ const data = ev.data;
19
+ if (data instanceof ArrayBuffer) {
20
+ listener(new Uint8Array(data));
21
+ }
22
+ else {
23
+ listener(data);
24
+ }
25
+ };
26
+ }
27
+ else if (event === "open" || event === "close" || event === "error") {
28
+ wrapped = () => listener();
29
+ }
30
+ else {
31
+ wrapped = (ev) => listener(ev);
32
+ }
33
+ if (!this.listeners.has(event)) {
34
+ this.listeners.set(event, new Map());
35
+ }
36
+ this.listeners.get(event).set(listener, wrapped);
37
+ this.ws.addEventListener(event, wrapped);
38
+ }
39
+ off(event, listener) {
40
+ const wrapped = this.listeners.get(event)?.get(listener);
41
+ if (wrapped) {
42
+ this.ws.removeEventListener(event, wrapped);
43
+ this.listeners.get(event).delete(listener);
44
+ }
45
+ }
46
+ send(data) {
47
+ this.ws.send(data);
48
+ }
49
+ close() {
50
+ this.ws.close();
51
+ }
52
+ terminate() {
53
+ this.ws.close();
54
+ }
55
+ }
56
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/transport/browser.ts"],"names":[],"mappings":"AAMA,MAAM,OAAO,gBAAgB;IACjB,EAAE,CAAY;IACd,SAAS,GAAG,IAAI,GAAG,EAA4C,CAAC;IACxE,OAAO,GAAgC,IAAI,CAAC;IAE5C,YAAY,GAAW,EAAE,QAAiB;QACtC,IAAI,CAAC,EAAE,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,CAAC,EAAE,CAAC,UAAU,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,EAAE,CAAC,OAAO,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,UAAU;QACV,OAAO,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC;IAC9B,CAAC;IAED,EAAE,CAAC,KAAa,EAAE,QAAkC;QAChD,IAAI,OAA0B,CAAC;QAE/B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACtB,sEAAsE;YACtE,OAAO,GAAG,CAAC,EAAS,EAAE,EAAE;gBACpB,MAAM,IAAI,GAAI,EAAmB,CAAC,IAAI,CAAC;gBACvC,IAAI,IAAI,YAAY,WAAW,EAAE,CAAC;oBAC9B,QAAQ,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;gBACnC,CAAC;qBAAM,CAAC;oBACJ,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACnB,CAAC;YACL,CAAC,CAAC;QACN,CAAC;aAAM,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;YACpE,OAAO,GAAG,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;QAC/B,CAAC;aAAM,CAAC;YACJ,OAAO,GAAG,CAAC,EAAS,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC1C,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;QACzC,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAClD,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IAED,GAAG,CAAC,KAAa,EAAE,QAAkC;QACjD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;QACzD,IAAI,OAAO,EAAE,CAAC;YACV,IAAI,CAAC,EAAE,CAAC,mBAAmB,CAAC,KAAK,EAAE,OAAc,CAAC,CAAC;YACnD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAChD,CAAC;IACL,CAAC;IAED,IAAI,CAAC,IAAS;QACV,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC;IAED,KAAK;QACD,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IACpB,CAAC;IAED,SAAS;QACL,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IACpB,CAAC;CACJ"}
@@ -0,0 +1,20 @@
1
+ export interface ILogger {
2
+ info(message: string, ...args: any[]): void;
3
+ warn(message: string, ...args: any[]): void;
4
+ error(message: string, ...args: any[]): void;
5
+ debug(message: string, ...args: any[]): void;
6
+ }
7
+ export type IWebSocketCtor = new (url: string, options?: object) => IWebSocketLike;
8
+ export interface IWebSocketLike {
9
+ on(event: string, listener: (...args: any[]) => void): void;
10
+ off(event: string, listener: (...args: any[]) => void): void;
11
+ send(data: any): void;
12
+ close(): void;
13
+ terminate?(): void;
14
+ onerror: ((err: any) => void) | null;
15
+ readyState: number;
16
+ }
17
+ export interface IClientAdapters {
18
+ logger: ILogger;
19
+ WebSocket: IWebSocketCtor;
20
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/transport/types.ts"],"names":[],"mappings":""}