@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/src/codecs.ts ADDED
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Pre-built codec instances for every HTTP response type.
3
+ *
4
+ * Usage: import { UserCodec } from "./codecs.js";
5
+ * const data = decodeAxios(UserCodec, res.data);
6
+ *
7
+ * decode() returns typed data without runtime validation (SDK trusts server).
8
+ * For trust boundary validation, use codec.decodeSafe() directly.
9
+ */
10
+ import {
11
+ ActionTokenSchema,
12
+ ChannelSchema,
13
+ DeviceSchema,
14
+ EmojiSchema,
15
+ FileSQLSchema,
16
+ InviteSchema,
17
+ KeyBundleSchema,
18
+ PermissionSchema,
19
+ ServerSchema,
20
+ UserSchema,
21
+ } from "@vex-chat/types";
22
+
23
+ import { z } from "zod/v4";
24
+
25
+ import { createCodec } from "./codec.js";
26
+
27
+ // ── Named schema codecs ─────────────────────────────────────────────────────
28
+
29
+ export const UserCodec = createCodec(UserSchema);
30
+ export const DeviceCodec = createCodec(DeviceSchema);
31
+ export const ServerCodec = createCodec(ServerSchema);
32
+ export const ChannelCodec = createCodec(ChannelSchema);
33
+ export const PermissionCodec = createCodec(PermissionSchema);
34
+ export const InviteCodec = createCodec(InviteSchema);
35
+ export const EmojiCodec = createCodec(EmojiSchema);
36
+ export const FileSQLCodec = createCodec(FileSQLSchema);
37
+ export const ActionTokenCodec = createCodec(ActionTokenSchema);
38
+ export const KeyBundleCodec = createCodec(KeyBundleSchema);
39
+
40
+ // ── Array codecs ────────────────────────────────────────────────────────────
41
+
42
+ export const UserArrayCodec = createCodec(z.array(UserSchema));
43
+ export const DeviceArrayCodec = createCodec(z.array(DeviceSchema));
44
+ export const ServerArrayCodec = createCodec(z.array(ServerSchema));
45
+ export const ChannelArrayCodec = createCodec(z.array(ChannelSchema));
46
+ export const PermissionArrayCodec = createCodec(z.array(PermissionSchema));
47
+ export const InviteArrayCodec = createCodec(z.array(InviteSchema));
48
+ export const EmojiArrayCodec = createCodec(z.array(EmojiSchema));
49
+
50
+ // ── Inline ad-hoc response codecs ───────────────────────────────────────────
51
+
52
+ export const ConnectResponseCodec = createCodec(
53
+ z.object({ deviceToken: z.string() }),
54
+ );
55
+
56
+ export const AuthResponseCodec = createCodec(
57
+ z.object({
58
+ token: z.string(),
59
+ user: UserSchema,
60
+ }),
61
+ );
62
+
63
+ export const DeviceChallengeCodec = createCodec(
64
+ z.object({
65
+ challenge: z.string(),
66
+ challengeID: z.string(),
67
+ }),
68
+ );
69
+
70
+ export const WhoamiCodec = createCodec(
71
+ z.object({
72
+ exp: z.number(),
73
+ token: z.string(),
74
+ user: UserSchema,
75
+ }),
76
+ );
77
+
78
+ export const OtkCountCodec = createCodec(z.object({ count: z.number() }));
79
+
80
+ // ── Helper: decode axios response buffer ────────────────────────────────────
81
+
82
+ /**
83
+ * Decode an axios arraybuffer response with a typed codec.
84
+ * Uses decodeSafe (Zod-validated) so schema mismatches surface immediately.
85
+ */
86
+ export function decodeAxios<T>(
87
+ codec: { decodeSafe: (data: Uint8Array) => T },
88
+ /**
89
+ * Accepts `unknown` because axios types its `responseType: 'arraybuffer'`
90
+ * responses as `any`. At runtime this is always an `ArrayBuffer`.
91
+ */
92
+ data: unknown,
93
+ ): T {
94
+ if (data instanceof Uint8Array) {
95
+ return codec.decodeSafe(data);
96
+ }
97
+ if (data instanceof ArrayBuffer) {
98
+ return codec.decodeSafe(new Uint8Array(data));
99
+ }
100
+ throw new Error("Expected Uint8Array or ArrayBuffer from axios response");
101
+ }
package/src/index.ts ADDED
@@ -0,0 +1,33 @@
1
+ export { Client } from "./Client.js";
2
+ export type {
3
+ Channel,
4
+ Channels,
5
+ ClientOptions,
6
+ Device,
7
+ Devices,
8
+ Emojis,
9
+ FileProgress,
10
+ FileRes,
11
+ Files,
12
+ Invites,
13
+ Keys,
14
+ Me,
15
+ Message,
16
+ Messages,
17
+ Moderation,
18
+ Permission,
19
+ Permissions,
20
+ Server,
21
+ Servers,
22
+ Session,
23
+ Sessions,
24
+ User,
25
+ Users,
26
+ VexFile,
27
+ } from "./Client.js";
28
+ export { createCodec, msgpack } from "./codec.js";
29
+ export type { Storage } from "./Storage.js";
30
+ export type { Logger } from "./transport/types.js";
31
+ export type { KeyStore, StoredCredentials } from "./types/index.js";
32
+ // Re-export app-facing types
33
+ export type { Invite } from "@vex-chat/types";
@@ -0,0 +1,30 @@
1
+ /**
2
+ * In-memory KeyStore for testing and ephemeral sessions.
3
+ * No persistence — credentials are lost when the process exits.
4
+ */
5
+ import type { KeyStore, StoredCredentials } from "../types/index.js";
6
+
7
+ export class MemoryKeyStore implements KeyStore {
8
+ private readonly store = new Map<string, StoredCredentials>();
9
+
10
+ clear(username: string): Promise<void> {
11
+ this.store.delete(username);
12
+ return Promise.resolve();
13
+ }
14
+
15
+ load(username?: string): Promise<null | StoredCredentials> {
16
+ if (username) {
17
+ return Promise.resolve(this.store.get(username) ?? null);
18
+ }
19
+ // Return the most recently saved credentials
20
+ const entries = [...this.store.values()];
21
+ return Promise.resolve(
22
+ entries.length > 0 ? (entries[entries.length - 1] ?? null) : null,
23
+ );
24
+ }
25
+
26
+ save(creds: StoredCredentials): Promise<void> {
27
+ this.store.set(creds.username, creds);
28
+ return Promise.resolve();
29
+ }
30
+ }
@@ -0,0 +1,91 @@
1
+ import type { KeyStore, StoredCredentials } from "../types/index.js";
2
+
3
+ import * as fs from "node:fs";
4
+ import * as path from "node:path";
5
+
6
+ /**
7
+ * File-backed KeyStore for Node.js (CLI tools, bots, integration tests).
8
+ *
9
+ * Stores credentials as encrypted files on disk using XUtils.encryptKeyData.
10
+ * Node-only — imports node:fs.
11
+ */
12
+ import { XUtils } from "@vex-chat/crypto";
13
+
14
+ export class NodeKeyStore implements KeyStore {
15
+ private readonly dir: string;
16
+
17
+ constructor(dir: string = ".") {
18
+ this.dir = dir;
19
+ }
20
+
21
+ clear(username: string): Promise<void> {
22
+ try {
23
+ fs.unlinkSync(this.filePath(username));
24
+ } catch {
25
+ // File may not exist
26
+ }
27
+ return Promise.resolve();
28
+ }
29
+
30
+ load(username?: string): Promise<null | StoredCredentials> {
31
+ if (username) {
32
+ return Promise.resolve(this.readFile(this.filePath(username)));
33
+ }
34
+ // Find most recent .vex file in the directory
35
+ try {
36
+ const files = fs
37
+ .readdirSync(this.dir)
38
+ .filter((f) => f.endsWith(".vex"))
39
+ .map((f) => ({
40
+ mtime: fs.statSync(path.join(this.dir, f)).mtimeMs,
41
+ name: f,
42
+ }))
43
+ .sort((a, b) => b.mtime - a.mtime);
44
+ if (files.length === 0) return Promise.resolve(null);
45
+ const newest = files[0];
46
+ if (!newest) return Promise.resolve(null);
47
+ return Promise.resolve(
48
+ this.readFile(path.join(this.dir, newest.name)),
49
+ );
50
+ } catch {
51
+ return Promise.resolve(null);
52
+ }
53
+ }
54
+
55
+ save(creds: StoredCredentials): Promise<void> {
56
+ const data = JSON.stringify(creds);
57
+ const encrypted = XUtils.encryptKeyData("", data);
58
+ fs.writeFileSync(this.filePath(creds.username), encrypted);
59
+ return Promise.resolve();
60
+ }
61
+
62
+ private filePath(username: string): string {
63
+ return path.join(this.dir, `${username}.vex`);
64
+ }
65
+
66
+ private readFile(filePath: string): null | StoredCredentials {
67
+ try {
68
+ const data = fs.readFileSync(filePath);
69
+ const decrypted = XUtils.decryptKeyData(new Uint8Array(data), "");
70
+ const parsed: unknown = JSON.parse(decrypted);
71
+ if (isStoredCredentials(parsed)) {
72
+ return parsed;
73
+ }
74
+ return null;
75
+ } catch {
76
+ return null;
77
+ }
78
+ }
79
+ }
80
+
81
+ function isStoredCredentials(value: unknown): value is StoredCredentials {
82
+ if (typeof value !== "object" || value === null) return false;
83
+ return (
84
+ "username" in value &&
85
+ typeof value.username === "string" &&
86
+ "deviceID" in value &&
87
+ typeof value.deviceID === "string" &&
88
+ "deviceKey" in value &&
89
+ typeof value.deviceKey === "string"
90
+ );
91
+ }
@@ -0,0 +1,13 @@
1
+ import type { Storage } from "../Storage.js";
2
+ import type { Logger } from "../transport/types.js";
3
+
4
+ /** Internal preset interface used by nodePreset and testPreset. */
5
+ export interface PlatformPreset {
6
+ createStorage(
7
+ dbName: string,
8
+ privateKey: string,
9
+ logger: Logger,
10
+ ): Promise<Storage>;
11
+ deviceName: string;
12
+ logger: Logger;
13
+ }
@@ -0,0 +1,34 @@
1
+ import type { Storage } from "../Storage.js";
2
+ import type { Logger } from "../transport/types.js";
3
+ /**
4
+ * Platform preset for Node.js (CLI tools, bots, tests).
5
+ *
6
+ * - WebSocket: native global (Node 22+)
7
+ * - Storage: Kysely + better-sqlite3
8
+ * - Logger: winston (loaded dynamically)
9
+ */
10
+ import type { PlatformPreset } from "./common.js";
11
+
12
+ export async function nodePreset(logLevel?: string): Promise<PlatformPreset> {
13
+ const { createLogger } = await import("../utils/createLogger.js");
14
+ const logger: Logger = createLogger("libvex", logLevel);
15
+
16
+ return {
17
+ async createStorage(
18
+ dbName,
19
+ privateKey,
20
+ storageLogger,
21
+ ): Promise<Storage> {
22
+ const { createNodeStorage } = await import("../storage/node.js");
23
+
24
+ const storage: Storage = createNodeStorage(
25
+ dbName,
26
+ privateKey,
27
+ storageLogger,
28
+ );
29
+ return storage;
30
+ },
31
+ deviceName: process.platform,
32
+ logger,
33
+ };
34
+ }
@@ -0,0 +1,37 @@
1
+ import type { Logger } from "../transport/types.js";
2
+ /**
3
+ * Platform preset for tests — no I/O, no platform dependencies.
4
+ *
5
+ * - WebSocket: native global (Node 22+)
6
+ * - Storage: in-memory (no persistence)
7
+ * - Logger: console
8
+ */
9
+ import type { PlatformPreset } from "./common.js";
10
+
11
+ const logger: Logger = {
12
+ debug() {},
13
+ error(m: string) {
14
+ console.error(`[test] ${m}`);
15
+ },
16
+ info(m: string) {
17
+ console.log(`[test] ${m}`);
18
+ },
19
+ warn(m: string) {
20
+ console.warn(`[test] ${m}`);
21
+ },
22
+ };
23
+
24
+ export function testPreset(): PlatformPreset {
25
+ return {
26
+ async createStorage(_dbName, privateKey, _logger) {
27
+ // Lazy import to avoid pulling eventemitter3 into the type graph
28
+ const { MemoryStorage } =
29
+ await import("../__tests__/harness/memory-storage.js");
30
+ const storage = new MemoryStorage(privateKey);
31
+ await storage.init();
32
+ return storage;
33
+ },
34
+ deviceName: "test",
35
+ logger,
36
+ };
37
+ }
@@ -0,0 +1,33 @@
1
+ import type { Storage } from "../Storage.js";
2
+ import type { Logger } from "../transport/types.js";
3
+ import type { ClientDatabase } from "./schema.js";
4
+
5
+ import BetterSqlite3 from "better-sqlite3";
6
+ /**
7
+ * Node.js storage factory — creates SqliteStorage with better-sqlite3 dialect.
8
+ * Node-only — imports better-sqlite3 which is a native addon.
9
+ */
10
+ import { Kysely, SqliteDialect } from "kysely";
11
+
12
+ import { SqliteStorage } from "./sqlite.js";
13
+
14
+ export function createNodeStorage(
15
+ dbPath: string,
16
+ SK: string,
17
+ logger?: Logger,
18
+ ): Storage {
19
+ const db = new Kysely<ClientDatabase>({
20
+ dialect: new SqliteDialect({
21
+ database: new BetterSqlite3(dbPath),
22
+ }),
23
+ });
24
+ const log: Logger = logger ?? {
25
+ debug() {},
26
+ error() {},
27
+ info() {},
28
+ warn() {},
29
+ };
30
+ const storage = new SqliteStorage(db, SK, log);
31
+ void storage.init();
32
+ return storage;
33
+ }
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Kysely typed table interfaces for the client-side SQLite database.
3
+ */
4
+ import type {
5
+ ColumnType,
6
+ Generated,
7
+ Insertable,
8
+ Selectable,
9
+ Updateable,
10
+ } from "kysely";
11
+
12
+ export interface ClientDatabase {
13
+ devices: DevicesTable;
14
+ messages: MessagesTable;
15
+ oneTimeKeys: OneTimeKeysTable;
16
+ preKeys: PreKeysTable;
17
+ sessions: SessionsTable;
18
+ }
19
+
20
+ export type DeviceRow = Selectable<DevicesTable>;
21
+
22
+ export type DeviceUpdate = Updateable<DevicesTable>;
23
+
24
+ export type MessageRow = Selectable<MessagesTable>;
25
+
26
+ export type MessageUpdate = Updateable<MessagesTable>;
27
+
28
+ export type NewDevice = Insertable<DevicesTable>;
29
+
30
+ // ── Row utility types ────────────────────────────────────────────────────────
31
+
32
+ export type NewMessage = Insertable<MessagesTable>;
33
+ export type NewOneTimeKey = Insertable<OneTimeKeysTable>;
34
+ export type NewPreKey = Insertable<PreKeysTable>;
35
+
36
+ export type NewSession = Insertable<SessionsTable>;
37
+ export type OneTimeKeyRow = Selectable<OneTimeKeysTable>;
38
+ export type PreKeyRow = Selectable<PreKeysTable>;
39
+
40
+ export type SessionRow = Selectable<SessionsTable>;
41
+ export type SessionUpdate = Updateable<SessionsTable>;
42
+ interface DevicesTable {
43
+ deleted: number;
44
+ deviceID: string;
45
+ lastLogin: string;
46
+ name: string;
47
+ owner: string;
48
+ signKey: string;
49
+ }
50
+
51
+ interface MessagesTable {
52
+ authorID: string;
53
+ decrypted: number;
54
+ direction: string;
55
+ forward: number;
56
+ group: null | string;
57
+ mailID: string;
58
+ message: string;
59
+ nonce: string;
60
+ readerID: string;
61
+ recipient: string;
62
+ sender: string;
63
+ timestamp: string;
64
+ }
65
+ interface OneTimeKeysTable {
66
+ deviceID: ColumnType<string, string | undefined, string>;
67
+ index: Generated<number>;
68
+ keyID: ColumnType<string, string | undefined, string>;
69
+ privateKey: string;
70
+ publicKey: string;
71
+ signature: string;
72
+ userID: ColumnType<string, string | undefined, string>;
73
+ }
74
+
75
+ interface PreKeysTable {
76
+ deviceID: ColumnType<string, string | undefined, string>;
77
+ index: Generated<number>;
78
+ keyID: ColumnType<string, string | undefined, string>;
79
+ privateKey: string;
80
+ publicKey: string;
81
+ signature: string;
82
+ userID: ColumnType<string, string | undefined, string>;
83
+ }
84
+ interface SessionsTable {
85
+ deviceID: string;
86
+ fingerprint: string;
87
+ lastUsed: string;
88
+ mode: string;
89
+ publicKey: string;
90
+ sessionID: string;
91
+ SK: string;
92
+ userID: string;
93
+ verified: number;
94
+ }