@vex-chat/libvex 1.1.0 → 4.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 (149) hide show
  1. package/README.md +104 -41
  2. package/dist/Client.d.ts +473 -560
  3. package/dist/Client.d.ts.map +1 -0
  4. package/dist/Client.js +1486 -1551
  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 +6 -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 +8 -6
  31. package/dist/keystore/node.d.ts.map +1 -0
  32. package/dist/keystore/node.js +47 -22
  33. package/dist/keystore/node.js.map +1 -1
  34. package/dist/preset/common.d.ts +7 -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 +4 -7
  39. package/dist/preset/node.d.ts.map +1 -0
  40. package/dist/preset/node.js +4 -11
  41. package/dist/preset/node.js.map +1 -1
  42. package/dist/preset/test.d.ts +4 -5
  43. package/dist/preset/test.d.ts.map +1 -0
  44. package/dist/preset/test.js +3 -20
  45. package/dist/preset/test.js.map +1 -1
  46. package/dist/storage/node.d.ts +3 -3
  47. package/dist/storage/node.d.ts.map +1 -0
  48. package/dist/storage/node.js +4 -10
  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 +41 -28
  53. package/dist/storage/sqlite.d.ts.map +1 -0
  54. package/dist/storage/sqlite.js +339 -297
  55. package/dist/storage/sqlite.js.map +1 -1
  56. package/dist/transport/types.d.ts +17 -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 +38 -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 +22 -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/formatBytes.d.ts +1 -0
  77. package/dist/utils/formatBytes.d.ts.map +1 -0
  78. package/dist/utils/formatBytes.js +3 -1
  79. package/dist/utils/formatBytes.js.map +1 -1
  80. package/dist/utils/sqlSessionToCrypto.d.ts +4 -2
  81. package/dist/utils/sqlSessionToCrypto.d.ts.map +1 -0
  82. package/dist/utils/sqlSessionToCrypto.js +5 -5
  83. package/dist/utils/sqlSessionToCrypto.js.map +1 -1
  84. package/dist/utils/uint8uuid.d.ts +1 -4
  85. package/dist/utils/uint8uuid.d.ts.map +1 -0
  86. package/dist/utils/uint8uuid.js +1 -7
  87. package/dist/utils/uint8uuid.js.map +1 -1
  88. package/package.json +74 -91
  89. package/src/Client.ts +3086 -0
  90. package/{dist/IStorage.d.ts → src/Storage.ts} +70 -62
  91. package/src/__tests__/codec.test.ts +256 -0
  92. package/src/__tests__/ghost.png +0 -0
  93. package/src/__tests__/harness/fixtures.ts +22 -0
  94. package/src/__tests__/harness/memory-storage.ts +254 -0
  95. package/src/__tests__/harness/platform-transports.ts +4 -0
  96. package/src/__tests__/harness/poison-node-imports.ts +107 -0
  97. package/src/__tests__/harness/shared-suite.ts +426 -0
  98. package/src/__tests__/platform-browser.test.ts +14 -0
  99. package/src/__tests__/platform-node.test.ts +9 -0
  100. package/src/__tests__/triggered.png +0 -0
  101. package/src/codec.ts +68 -0
  102. package/src/codecs.ts +101 -0
  103. package/src/index.ts +40 -0
  104. package/src/keystore/memory.ts +30 -0
  105. package/src/keystore/node.ts +102 -0
  106. package/src/preset/common.ts +7 -0
  107. package/src/preset/node.ts +18 -0
  108. package/src/preset/test.ts +20 -0
  109. package/src/storage/node.ts +22 -0
  110. package/src/storage/schema.ts +94 -0
  111. package/src/storage/sqlite.ts +655 -0
  112. package/src/transport/types.ts +22 -0
  113. package/src/transport/websocket.ts +106 -0
  114. package/src/types/crypto.ts +42 -0
  115. package/src/types/identity.ts +23 -0
  116. package/src/types/index.ts +9 -0
  117. package/src/utils/capitalize.ts +6 -0
  118. package/src/utils/formatBytes.ts +15 -0
  119. package/src/utils/sqlSessionToCrypto.ts +16 -0
  120. package/src/utils/uint8uuid.ts +7 -0
  121. package/dist/IStorage.js +0 -2
  122. package/dist/IStorage.js.map +0 -1
  123. package/dist/keystore/types.d.ts +0 -4
  124. package/dist/keystore/types.js +0 -2
  125. package/dist/keystore/types.js.map +0 -1
  126. package/dist/preset/expo.d.ts +0 -2
  127. package/dist/preset/expo.js +0 -39
  128. package/dist/preset/expo.js.map +0 -1
  129. package/dist/preset/tauri.d.ts +0 -2
  130. package/dist/preset/tauri.js +0 -36
  131. package/dist/preset/tauri.js.map +0 -1
  132. package/dist/preset/types.d.ts +0 -14
  133. package/dist/preset/types.js +0 -2
  134. package/dist/preset/types.js.map +0 -1
  135. package/dist/storage/expo.d.ts +0 -3
  136. package/dist/storage/expo.js +0 -18
  137. package/dist/storage/expo.js.map +0 -1
  138. package/dist/storage/tauri.d.ts +0 -3
  139. package/dist/storage/tauri.js +0 -21
  140. package/dist/storage/tauri.js.map +0 -1
  141. package/dist/transport/browser.d.ts +0 -17
  142. package/dist/transport/browser.js +0 -56
  143. package/dist/transport/browser.js.map +0 -1
  144. package/dist/utils/constants.d.ts +0 -8
  145. package/dist/utils/constants.js +0 -9
  146. package/dist/utils/constants.js.map +0 -1
  147. package/dist/utils/createLogger.d.ts +0 -5
  148. package/dist/utils/createLogger.js +0 -27
  149. package/dist/utils/createLogger.js.map +0 -1
package/README.md CHANGED
@@ -1,51 +1,114 @@
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
+ The client implements an X3DH-style handshake (X25519 DH + KDF), XSalsa20-Poly1305 (xSecretbox) for payloads, and HMAC over mail objects for integrity on the wire. Message payloads are intended to be end-to-end encrypted; the server still sees ciphertext, routing metadata, timing, and who talks to whom, and controls key-bundle distribution—so a malicious or compromised Spire can mount impersonation unless users verify sessions out-of-band.
21
+
22
+ - **End-to-end encrypted messaging** with X3DH key agreement — sessions, prekeys, and one-time keys handled internally.
23
+ - **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.
24
+ - **Pluggable storage backend** via Kysely so node consumers can use SQLite and browser/tauri/expo consumers can wire their own.
25
+ - **Pluggable key store** so secrets can live in memory (tests), the OS keychain (`./keystore/node`), or wherever the embedding app keeps them.
26
+ - **WebSocket transport** for live message delivery with automatic reconnection and HTTP fallback for the REST API.
27
+
28
+ ## Install
29
+
30
+ ```sh
31
+ npm install @vex-chat/libvex
32
+ ```
33
+
34
+ `@vex-chat/types`, `@vex-chat/crypto`, `axios`, `kysely`, `winston`, and `zod` are required runtime dependencies and install automatically.
35
+
36
+ `better-sqlite3` is an **optional peer dependency** — install it explicitly only if you plan to use the SQLite storage backend on Node:
37
+
38
+ ```sh
39
+ npm install @vex-chat/libvex better-sqlite3
40
+ ```
41
+
42
+ Browser, Tauri, and Expo consumers should leave `better-sqlite3` out and supply their own storage adapter via `./storage/schema`.
8
43
 
9
44
  ## Quickstart
10
45
 
11
46
  ```ts
12
47
  import { Client } from "@vex-chat/libvex";
13
48
 
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();
49
+ // Generate or load a long-lived secret key — store it in the OS keychain.
50
+ const secretKey = Client.generateSecretKey();
51
+
52
+ const client = await Client.create(secretKey);
53
+
54
+ // First-time devices must register before logging in.
55
+ await client.register(Client.randomUsername());
56
+ await client.login();
57
+
58
+ client.on("authed", async () => {
59
+ const me = await client.users.me();
60
+ await client.messages.send(me.userID, "Hello world!");
61
+ });
62
+
63
+ client.on("message", (message) => {
64
+ console.log("message:", message);
65
+ });
51
66
  ```
67
+
68
+ ## Platform presets
69
+
70
+ libvex ships per-platform "presets" that wire together the appropriate storage and keystore:
71
+
72
+ ```ts
73
+ // Node — sqlite storage + OS keychain
74
+ import {
75
+ Client,
76
+ makeStorage,
77
+ BootstrapConfig,
78
+ } from "@vex-chat/libvex/preset/node";
79
+
80
+ // Tests / ephemeral — in-memory storage + memory keystore
81
+ import {
82
+ Client,
83
+ makeStorage,
84
+ BootstrapConfig,
85
+ } from "@vex-chat/libvex/preset/test";
86
+ ```
87
+
88
+ 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`.
89
+
90
+ ## Development
91
+
92
+ ```sh
93
+ npm run build # tsc -p tsconfig.build.json
94
+ npm run lint # eslint
95
+ npm run lint:fix # eslint --fix
96
+ npm run format # prettier --write
97
+ npm run format:check
98
+ npm test # vitest unit suite (browser-safe, no spire required)
99
+ npm run test:e2e # vitest node + browser e2e — needs a running spire
100
+ npm run lint:pkg # publint --strict
101
+ npm run lint:types # @arethetypeswrong/cli
102
+ npm run lint:api # api-extractor — regenerates api/libvex.api.md
103
+ npx type-coverage # type-coverage (≥95%)
104
+ npm run license:check # license allowlist gate
105
+ npm run docs # typedoc — writes ./docs
106
+ ```
107
+
108
+ 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.
109
+
110
+ See [AGENTS.md](./AGENTS.md) for the release flow (changesets → publish) and the rules for writing changesets.
111
+
112
+ ## License
113
+
114
+ [AGPL-3.0-or-later](./LICENSE)