@vex-chat/libvex 1.1.0 → 2.0.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.
Files changed (151) hide show
  1. package/README.md +103 -41
  2. package/dist/Client.d.ts +440 -551
  3. package/dist/Client.d.ts.map +1 -0
  4. package/dist/Client.js +1566 -1502
  5. package/dist/Client.js.map +1 -1
  6. package/dist/Storage.d.ts +111 -0
  7. package/dist/Storage.d.ts.map +1 -0
  8. package/dist/Storage.js +2 -0
  9. package/dist/Storage.js.map +1 -0
  10. package/dist/__tests__/harness/memory-storage.d.ts +29 -27
  11. package/dist/__tests__/harness/memory-storage.d.ts.map +1 -0
  12. package/dist/__tests__/harness/memory-storage.js +120 -109
  13. package/dist/__tests__/harness/memory-storage.js.map +1 -1
  14. package/dist/codec.d.ts +44 -0
  15. package/dist/codec.d.ts.map +1 -0
  16. package/dist/codec.js +51 -0
  17. package/dist/codec.js.map +1 -0
  18. package/dist/codecs.d.ts +201 -0
  19. package/dist/codecs.d.ts.map +1 -0
  20. package/dist/codecs.js +67 -0
  21. package/dist/codecs.js.map +1 -0
  22. package/dist/index.d.ts +7 -5
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +1 -0
  25. package/dist/index.js.map +1 -1
  26. package/dist/keystore/memory.d.ts +5 -4
  27. package/dist/keystore/memory.d.ts.map +1 -0
  28. package/dist/keystore/memory.js +9 -7
  29. package/dist/keystore/memory.js.map +1 -1
  30. package/dist/keystore/node.d.ts +6 -5
  31. package/dist/keystore/node.d.ts.map +1 -0
  32. package/dist/keystore/node.js +38 -19
  33. package/dist/keystore/node.js.map +1 -1
  34. package/dist/preset/common.d.ts +9 -0
  35. package/dist/preset/common.d.ts.map +1 -0
  36. package/dist/preset/common.js +2 -0
  37. package/dist/preset/common.js.map +1 -0
  38. package/dist/preset/node.d.ts +3 -5
  39. package/dist/preset/node.d.ts.map +1 -0
  40. package/dist/preset/node.js +5 -8
  41. package/dist/preset/node.js.map +1 -1
  42. package/dist/preset/test.d.ts +4 -4
  43. package/dist/preset/test.d.ts.map +1 -0
  44. package/dist/preset/test.js +8 -11
  45. package/dist/preset/test.js.map +1 -1
  46. package/dist/storage/node.d.ts +4 -3
  47. package/dist/storage/node.d.ts.map +1 -0
  48. package/dist/storage/node.js +4 -4
  49. package/dist/storage/node.js.map +1 -1
  50. package/dist/storage/schema.d.ts +55 -54
  51. package/dist/storage/schema.d.ts.map +1 -0
  52. package/dist/storage/sqlite.d.ts +33 -28
  53. package/dist/storage/sqlite.d.ts.map +1 -0
  54. package/dist/storage/sqlite.js +330 -291
  55. package/dist/storage/sqlite.js.map +1 -1
  56. package/dist/transport/types.d.ts +23 -16
  57. package/dist/transport/types.d.ts.map +1 -0
  58. package/dist/transport/websocket.d.ts +26 -0
  59. package/dist/transport/websocket.d.ts.map +1 -0
  60. package/dist/transport/websocket.js +83 -0
  61. package/dist/transport/websocket.js.map +1 -0
  62. package/dist/types/crypto.d.ts +35 -0
  63. package/dist/types/crypto.d.ts.map +1 -0
  64. package/dist/types/crypto.js +9 -0
  65. package/dist/types/crypto.js.map +1 -0
  66. package/dist/types/identity.d.ts +17 -0
  67. package/dist/types/identity.d.ts.map +1 -0
  68. package/dist/types/identity.js +6 -0
  69. package/dist/types/identity.js.map +1 -0
  70. package/dist/types/index.d.ts +3 -0
  71. package/dist/types/index.d.ts.map +1 -0
  72. package/dist/types/index.js +2 -0
  73. package/dist/types/index.js.map +1 -0
  74. package/dist/utils/capitalize.d.ts +1 -0
  75. package/dist/utils/capitalize.d.ts.map +1 -0
  76. package/dist/utils/createLogger.d.ts +1 -0
  77. package/dist/utils/createLogger.d.ts.map +1 -0
  78. package/dist/utils/createLogger.js +3 -3
  79. package/dist/utils/createLogger.js.map +1 -1
  80. package/dist/utils/formatBytes.d.ts +1 -0
  81. package/dist/utils/formatBytes.d.ts.map +1 -0
  82. package/dist/utils/formatBytes.js +3 -1
  83. package/dist/utils/formatBytes.js.map +1 -1
  84. package/dist/utils/sqlSessionToCrypto.d.ts +4 -2
  85. package/dist/utils/sqlSessionToCrypto.d.ts.map +1 -0
  86. package/dist/utils/sqlSessionToCrypto.js +5 -5
  87. package/dist/utils/sqlSessionToCrypto.js.map +1 -1
  88. package/dist/utils/uint8uuid.d.ts +1 -4
  89. package/dist/utils/uint8uuid.d.ts.map +1 -0
  90. package/dist/utils/uint8uuid.js +1 -7
  91. package/dist/utils/uint8uuid.js.map +1 -1
  92. package/package.json +58 -83
  93. package/src/Client.ts +3304 -0
  94. package/{dist/IStorage.d.ts → src/Storage.ts} +70 -62
  95. package/src/__tests__/codec.test.ts +251 -0
  96. package/src/__tests__/ghost.png +0 -0
  97. package/src/__tests__/harness/fixtures.ts +22 -0
  98. package/src/__tests__/harness/memory-storage.ts +254 -0
  99. package/src/__tests__/harness/platform-transports.ts +17 -0
  100. package/src/__tests__/harness/poison-node-imports.ts +108 -0
  101. package/src/__tests__/harness/shared-suite.ts +446 -0
  102. package/src/__tests__/platform-browser.test.ts +19 -0
  103. package/src/__tests__/platform-node.test.ts +10 -0
  104. package/src/__tests__/triggered.png +0 -0
  105. package/src/codec.ts +68 -0
  106. package/src/codecs.ts +101 -0
  107. package/src/index.ts +33 -0
  108. package/src/keystore/memory.ts +30 -0
  109. package/src/keystore/node.ts +91 -0
  110. package/src/preset/common.ts +13 -0
  111. package/src/preset/node.ts +34 -0
  112. package/src/preset/test.ts +37 -0
  113. package/src/storage/node.ts +33 -0
  114. package/src/storage/schema.ts +94 -0
  115. package/src/storage/sqlite.ts +676 -0
  116. package/src/transport/types.ts +29 -0
  117. package/src/transport/websocket.ts +106 -0
  118. package/src/types/crypto.ts +39 -0
  119. package/src/types/identity.ts +18 -0
  120. package/src/types/index.ts +9 -0
  121. package/src/utils/capitalize.ts +6 -0
  122. package/src/utils/createLogger.ts +37 -0
  123. package/src/utils/formatBytes.ts +15 -0
  124. package/src/utils/sqlSessionToCrypto.ts +16 -0
  125. package/src/utils/uint8uuid.ts +7 -0
  126. package/dist/IStorage.js +0 -2
  127. package/dist/IStorage.js.map +0 -1
  128. package/dist/keystore/types.d.ts +0 -4
  129. package/dist/keystore/types.js +0 -2
  130. package/dist/keystore/types.js.map +0 -1
  131. package/dist/preset/expo.d.ts +0 -2
  132. package/dist/preset/expo.js +0 -39
  133. package/dist/preset/expo.js.map +0 -1
  134. package/dist/preset/tauri.d.ts +0 -2
  135. package/dist/preset/tauri.js +0 -36
  136. package/dist/preset/tauri.js.map +0 -1
  137. package/dist/preset/types.d.ts +0 -14
  138. package/dist/preset/types.js +0 -2
  139. package/dist/preset/types.js.map +0 -1
  140. package/dist/storage/expo.d.ts +0 -3
  141. package/dist/storage/expo.js +0 -18
  142. package/dist/storage/expo.js.map +0 -1
  143. package/dist/storage/tauri.d.ts +0 -3
  144. package/dist/storage/tauri.js +0 -21
  145. package/dist/storage/tauri.js.map +0 -1
  146. package/dist/transport/browser.d.ts +0 -17
  147. package/dist/transport/browser.js +0 -56
  148. package/dist/transport/browser.js.map +0 -1
  149. package/dist/utils/constants.d.ts +0 -8
  150. package/dist/utils/constants.js +0 -9
  151. package/dist/utils/constants.js.map +0 -1
package/README.md CHANGED
@@ -1,51 +1,113 @@
1
- # libvex-js
1
+ # @vex-chat/libvex
2
2
 
3
- ![build](https://github.com/vex-chat/libvex-js/workflows/build/badge.svg)
3
+ [![npm](https://img.shields.io/npm/v/@vex-chat/libvex?style=flat-square&color=cb3837&logo=npm)](https://www.npmjs.com/package/@vex-chat/libvex)
4
+ [![CI](https://img.shields.io/github/actions/workflow/status/vex-protocol/libvex-js/build.yml?branch=master&style=flat-square&logo=github&label=CI)](https://github.com/vex-protocol/libvex-js/actions/workflows/build.yml)
5
+ [![Released](https://img.shields.io/github/release-date/vex-protocol/libvex-js?style=flat-square&label=released)](https://github.com/vex-protocol/libvex-js/releases)
6
+ [![License](https://img.shields.io/npm/l/@vex-chat/libvex?style=flat-square&color=blue)](./LICENSE)
7
+ [![Types](https://img.shields.io/npm/types/@vex-chat/libvex?style=flat-square&logo=typescript&color=3178c6)](./dist/index.d.ts)
8
+ [![Type Coverage](https://img.shields.io/badge/dynamic/json?style=flat-square&label=type-coverage&prefix=%E2%89%A5&suffix=%25&query=$.typeCoverage.atLeast&url=https://raw.githubusercontent.com/vex-protocol/libvex-js/master/package.json&color=3178c6&logo=typescript)](https://github.com/plantain-00/type-coverage)
9
+ [![Node](https://img.shields.io/node/v/@vex-chat/libvex?style=flat-square&color=339933&logo=nodedotjs)](./package.json)
10
+ [![Bundle](https://deno.bundlejs.com/badge?q=@vex-chat/libvex&treeshake=[*])](https://bundlejs.com/?q=@vex-chat/libvex&treeshake=[*])
11
+ [![OpenSSF Scorecard](https://img.shields.io/ossf-scorecard/github.com/vex-protocol/libvex-js?style=flat-square&label=Scorecard)](https://securityscorecards.dev/viewer/?uri=github.com/vex-protocol/libvex-js)
12
+ [![Socket](https://socket.dev/api/badge/npm/package/@vex-chat/libvex)](https://socket.dev/npm/package/@vex-chat/libvex)
4
13
 
5
- nodejs for interfacing with xchat server. Use it for a client, a bot, whatever you'd like to connect to vex.
14
+ Reference TypeScript client for the [Vex](https://vex.wtf) encrypted chat platform. Builds against the wire protocol defined in [@vex-chat/types](https://github.com/vex-protocol/types-js) and the cryptographic primitives in [@vex-chat/crypto](https://github.com/vex-protocol/crypto-js). Use it to build a chat client, a bot, or any application that needs to talk to a [spire](https://github.com/vex-protocol/spire) server.
6
15
 
7
- <a href="https://vex-chat.github.io/libvex-js/">Documentation</a>
16
+ [Documentation](https://vex-chat.github.io/libvex-js/)
17
+
18
+ ## What's in the box
19
+
20
+ - **End-to-end encrypted messaging** with X3DH key agreement and a Double Ratchet message stack — sessions, prekeys, and one-time keys handled internally.
21
+ - **Tree-shakable subpath exports** for platform-specific code: `./preset/node`, `./preset/test`, `./storage/node`, `./storage/sqlite`, `./storage/schema`, `./keystore/node`, `./keystore/memory`. Browser bundles never pull in `better-sqlite3` or other native modules.
22
+ - **Pluggable storage backend** via Kysely so node consumers can use SQLite and browser/tauri/expo consumers can wire their own.
23
+ - **Pluggable key store** so secrets can live in memory (tests), the OS keychain (`./keystore/node`), or wherever the embedding app keeps them.
24
+ - **WebSocket transport** for live message delivery with automatic reconnection and HTTP fallback for the REST API.
25
+ - **Strict runtime validation** on every wire boundary — every server response is parsed through a Zod schema before any logic touches it.
26
+
27
+ ## Install
28
+
29
+ ```sh
30
+ npm install @vex-chat/libvex
31
+ ```
32
+
33
+ `@vex-chat/types`, `@vex-chat/crypto`, `axios`, `kysely`, `winston`, and `zod` are required runtime dependencies and install automatically.
34
+
35
+ `better-sqlite3` is an **optional peer dependency** — install it explicitly only if you plan to use the SQLite storage backend on Node:
36
+
37
+ ```sh
38
+ npm install @vex-chat/libvex better-sqlite3
39
+ ```
40
+
41
+ Browser, Tauri, and Expo consumers should leave `better-sqlite3` out and supply their own storage adapter via `./storage/schema`.
8
42
 
9
43
  ## Quickstart
10
44
 
11
45
  ```ts
12
46
  import { Client } from "@vex-chat/libvex";
13
47
 
14
- async function main() {
15
- // generate a secret key to use, save this somewhere permanent
16
- const privateKey = Client.generateSecretKey();
17
-
18
- const client = new Client(privateKey);
19
-
20
- /* the ready event is emitted when init() is finished.
21
- you must wait until this event fires to perform
22
- registration or login. */
23
- client.on("ready", async () => {
24
- // you must register once before you can log in
25
- await client.register(Client.randomUsername());
26
- await client.login();
27
- });
28
-
29
- /* The authed event fires when login() successfully completes
30
- and the server indicates you are authorized. You must wait to
31
- perform any operations besides register() and login() until
32
- this occurs. */
33
- client.on("authed", async () => {
34
- const me = await client.users.me();
35
-
36
- // send a message
37
- await client.messages.send(me.userID, "Hello world!");
38
- });
39
-
40
- /* Outgoing and incoming messages are emitted here. */
41
- client.on("message", (message) => {
42
- console.log("message:", message);
43
- });
44
-
45
- /* you must call init() to initialize the keyring and
46
- start the client. */
47
- client.init();
48
- }
49
-
50
- main();
48
+ // Generate or load a long-lived secret key — store it in the OS keychain.
49
+ const secretKey = Client.generateSecretKey();
50
+
51
+ const client = await Client.create(secretKey);
52
+
53
+ // First-time devices must register before logging in.
54
+ await client.register(Client.randomUsername());
55
+ await client.login();
56
+
57
+ client.on("authed", async () => {
58
+ const me = await client.users.me();
59
+ await client.messages.send(me.userID, "Hello world!");
60
+ });
61
+
62
+ client.on("message", (message) => {
63
+ console.log("message:", message);
64
+ });
51
65
  ```
66
+
67
+ ## Platform presets
68
+
69
+ libvex ships per-platform "presets" that wire together the appropriate storage and keystore:
70
+
71
+ ```ts
72
+ // Node — sqlite storage + OS keychain
73
+ import {
74
+ Client,
75
+ makeStorage,
76
+ BootstrapConfig,
77
+ } from "@vex-chat/libvex/preset/node";
78
+
79
+ // Tests / ephemeral — in-memory storage + memory keystore
80
+ import {
81
+ Client,
82
+ makeStorage,
83
+ BootstrapConfig,
84
+ } from "@vex-chat/libvex/preset/test";
85
+ ```
86
+
87
+ For a custom platform (browser, tauri, expo), import `Client` from `@vex-chat/libvex` directly and supply your own `Storage` (implementing the schema in `@vex-chat/libvex/storage/schema`) and `KeyStore` to `Client.create`.
88
+
89
+ ## Development
90
+
91
+ ```sh
92
+ npm run build # tsc -p tsconfig.build.json
93
+ npm run lint # eslint
94
+ npm run lint:fix # eslint --fix
95
+ npm run format # prettier --write
96
+ npm run format:check
97
+ npm test # vitest unit suite (browser-safe, no spire required)
98
+ npm run test:e2e # vitest node + browser e2e — needs a running spire
99
+ npm run lint:pkg # publint --strict
100
+ npm run lint:types # @arethetypeswrong/cli
101
+ npm run lint:api # api-extractor — regenerates api/libvex.api.md
102
+ npx type-coverage # type-coverage (≥95%)
103
+ npm run license:check # license allowlist gate
104
+ npm run docs # typedoc — writes ./docs
105
+ ```
106
+
107
+ The unit suite (`npm test`) runs browser-safe and offline. The e2e suite (`npm run test:e2e`) spins up a real spire server in a separate process — point `VEX_API_URL` at a running spire if you want to test against a different host.
108
+
109
+ See [AGENTS.md](./AGENTS.md) for the release flow (changesets → publish) and the rules for writing changesets.
110
+
111
+ ## License
112
+
113
+ [AGPL-3.0-or-later](./LICENSE)