@vex-chat/libvex 2.0.0 → 5.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.
- package/README.md +3 -2
- package/dist/Client.d.ts +83 -60
- package/dist/Client.d.ts.map +1 -1
- package/dist/Client.js +161 -275
- package/dist/Client.js.map +1 -1
- package/dist/Storage.d.ts +3 -3
- package/dist/codec.d.ts +4 -4
- package/dist/codec.d.ts.map +1 -1
- package/dist/codec.js +4 -4
- package/dist/codec.js.map +1 -1
- package/dist/codecs.d.ts +0 -4
- package/dist/codecs.d.ts.map +1 -1
- package/dist/codecs.js +0 -1
- package/dist/codecs.js.map +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/keystore/node.d.ts +2 -1
- package/dist/keystore/node.d.ts.map +1 -1
- package/dist/keystore/node.js +9 -3
- package/dist/keystore/node.js.map +1 -1
- package/dist/preset/common.d.ts +1 -3
- package/dist/preset/common.d.ts.map +1 -1
- package/dist/preset/node.d.ts +1 -2
- package/dist/preset/node.d.ts.map +1 -1
- package/dist/preset/node.js +3 -7
- package/dist/preset/node.js.map +1 -1
- package/dist/preset/test.d.ts +0 -1
- package/dist/preset/test.d.ts.map +1 -1
- package/dist/preset/test.js +1 -15
- package/dist/preset/test.js.map +1 -1
- package/dist/storage/node.d.ts +1 -2
- package/dist/storage/node.d.ts.map +1 -1
- package/dist/storage/node.js +2 -8
- package/dist/storage/node.js.map +1 -1
- package/dist/storage/sqlite.d.ts +11 -3
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +36 -33
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/transport/types.d.ts +0 -6
- package/dist/transport/types.d.ts.map +1 -1
- package/dist/types/crypto.d.ts +5 -2
- package/dist/types/crypto.d.ts.map +1 -1
- package/dist/types/crypto.js +2 -2
- package/dist/types/identity.d.ts +6 -1
- package/dist/types/identity.d.ts.map +1 -1
- package/dist/types/identity.js +1 -1
- package/package.json +20 -12
- package/src/Client.ts +220 -428
- package/src/Storage.ts +3 -3
- package/src/__tests__/codec.test.ts +26 -21
- package/src/__tests__/harness/platform-transports.ts +2 -15
- package/src/__tests__/harness/poison-node-imports.ts +0 -1
- package/src/__tests__/harness/shared-suite.ts +1 -20
- package/src/__tests__/platform-browser.test.ts +5 -10
- package/src/__tests__/platform-node.test.ts +1 -2
- package/src/codec.ts +4 -4
- package/src/codecs.ts +0 -1
- package/src/index.ts +9 -2
- package/src/keystore/node.ts +14 -3
- package/src/preset/common.ts +1 -7
- package/src/preset/node.ts +3 -19
- package/src/preset/test.ts +1 -18
- package/src/storage/node.ts +2 -13
- package/src/storage/sqlite.ts +44 -65
- package/src/transport/types.ts +0 -7
- package/src/types/crypto.ts +5 -2
- package/src/types/identity.ts +6 -1
- package/dist/utils/createLogger.d.ts +0 -6
- package/dist/utils/createLogger.d.ts.map +0 -1
- package/dist/utils/createLogger.js +0 -27
- package/dist/utils/createLogger.js.map +0 -1
- package/src/utils/createLogger.ts +0 -37
package/src/Storage.ts
CHANGED
|
@@ -24,7 +24,7 @@ export interface Storage extends EventEmitter {
|
|
|
24
24
|
/**
|
|
25
25
|
* Deletes history for a direct conversation or group channel.
|
|
26
26
|
*
|
|
27
|
-
* @param channelOrUserID Channel ID or user ID whose history should be deleted.
|
|
27
|
+
* @param channelOrUserID - Channel ID or user ID whose history should be deleted.
|
|
28
28
|
*/
|
|
29
29
|
deleteHistory: (channelOrUserID: string) => Promise<void>;
|
|
30
30
|
/** Deletes one message by `mailID`. */
|
|
@@ -108,8 +108,8 @@ export interface Storage extends EventEmitter {
|
|
|
108
108
|
/**
|
|
109
109
|
* Saves signed prekeys.
|
|
110
110
|
*
|
|
111
|
-
* @param preKeys Prekeys to persist.
|
|
112
|
-
* @param oneTime `true` for one-time keys, `false` for the long-lived signed prekey.
|
|
111
|
+
* @param preKeys - Prekeys to persist.
|
|
112
|
+
* @param oneTime - `true` for one-time keys, `false` for the long-lived signed prekey.
|
|
113
113
|
*/
|
|
114
114
|
savePreKeys: (
|
|
115
115
|
preKeys: UnsavedPreKey[],
|
|
@@ -21,6 +21,28 @@ const hexVar = (min: number, max: number) =>
|
|
|
21
21
|
const rec = (arbs: Record<string, fc.Arbitrary<unknown>>) =>
|
|
22
22
|
fc.record(arbs, { noNullPrototype: true });
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Strip keys that are magic in JS (`__proto__`, `constructor`, `prototype`)
|
|
26
|
+
* from generated JSON values. These can't round-trip through msgpack because
|
|
27
|
+
* the JS runtime intercepts them on plain objects.
|
|
28
|
+
*/
|
|
29
|
+
function stripProtoKeys(val: unknown): unknown {
|
|
30
|
+
if (val === null || typeof val !== "object") return val;
|
|
31
|
+
if (Array.isArray(val)) return val.map(stripProtoKeys);
|
|
32
|
+
const out: Record<string, unknown> = {};
|
|
33
|
+
for (const [k, v] of Object.entries(val)) {
|
|
34
|
+
if (k === "__proto__" || k === "constructor" || k === "prototype")
|
|
35
|
+
continue;
|
|
36
|
+
out[k] = stripProtoKeys(v);
|
|
37
|
+
}
|
|
38
|
+
return out;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const safeJsonValue = (opts?: { maxDepth?: number }) =>
|
|
42
|
+
fc
|
|
43
|
+
.jsonValue(opts)
|
|
44
|
+
.map((v) => stripProtoKeys(JSON.parse(JSON.stringify(v))));
|
|
45
|
+
|
|
24
46
|
// ── Arbitraries ──────────────────────────────────────────────────────────────
|
|
25
47
|
|
|
26
48
|
const arbBaseMsg = rec({
|
|
@@ -29,21 +51,14 @@ const arbBaseMsg = rec({
|
|
|
29
51
|
});
|
|
30
52
|
|
|
31
53
|
const arbSuccessMsg = rec({
|
|
32
|
-
data:
|
|
33
|
-
.jsonValue({ maxDepth: 1 })
|
|
34
|
-
.map((v) => JSON.parse(JSON.stringify(v)) as unknown),
|
|
54
|
+
data: safeJsonValue({ maxDepth: 1 }),
|
|
35
55
|
timestamp: fc.option(fc.string(), { nil: null }),
|
|
36
56
|
transmissionID: fc.uuid({ version: 4 }),
|
|
37
57
|
type: fc.constant("success"),
|
|
38
58
|
});
|
|
39
59
|
|
|
40
60
|
const arbErrMsg = rec({
|
|
41
|
-
data: fc.option(
|
|
42
|
-
fc
|
|
43
|
-
.jsonValue({ maxDepth: 1 })
|
|
44
|
-
.map((v) => JSON.parse(JSON.stringify(v)) as unknown),
|
|
45
|
-
{ nil: null },
|
|
46
|
-
),
|
|
61
|
+
data: fc.option(safeJsonValue({ maxDepth: 1 }), { nil: null }),
|
|
47
62
|
error: fc.string({ minLength: 1 }),
|
|
48
63
|
transmissionID: fc.uuid({ version: 4 }),
|
|
49
64
|
type: fc.constant("error"),
|
|
@@ -51,24 +66,14 @@ const arbErrMsg = rec({
|
|
|
51
66
|
|
|
52
67
|
const arbResourceMsg = rec({
|
|
53
68
|
action: fc.constantFrom("CREATE", "RETRIEVE", "UPDATE", "DELETE"),
|
|
54
|
-
data: fc.option(
|
|
55
|
-
fc
|
|
56
|
-
.jsonValue({ maxDepth: 1 })
|
|
57
|
-
.map((v) => JSON.parse(JSON.stringify(v)) as unknown),
|
|
58
|
-
{ nil: null },
|
|
59
|
-
),
|
|
69
|
+
data: fc.option(safeJsonValue({ maxDepth: 1 }), { nil: null }),
|
|
60
70
|
resourceType: fc.constantFrom("mail", "preKeys", "otk"),
|
|
61
71
|
transmissionID: fc.uuid({ version: 4 }),
|
|
62
72
|
type: fc.constant("resource"),
|
|
63
73
|
});
|
|
64
74
|
|
|
65
75
|
const arbNotifyMsg = rec({
|
|
66
|
-
data: fc.option(
|
|
67
|
-
fc
|
|
68
|
-
.jsonValue({ maxDepth: 1 })
|
|
69
|
-
.map((v) => JSON.parse(JSON.stringify(v)) as unknown),
|
|
70
|
-
{ nil: null },
|
|
71
|
-
),
|
|
76
|
+
data: fc.option(safeJsonValue({ maxDepth: 1 }), { nil: null }),
|
|
72
77
|
event: fc.constantFrom("mail", "serverChange", "permission"),
|
|
73
78
|
transmissionID: fc.uuid({ version: 4 }),
|
|
74
79
|
type: fc.constant("notify"),
|
|
@@ -1,17 +1,4 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Shared test transport utilities — kept as a module boundary for
|
|
3
|
+
* platform-specific test setup.
|
|
3
4
|
*/
|
|
4
|
-
import type { Logger } from "../../transport/types.js";
|
|
5
|
-
|
|
6
|
-
export const testLogger: Logger = {
|
|
7
|
-
debug(_m: string) {},
|
|
8
|
-
error(m: string) {
|
|
9
|
-
console.error(`[test] ${m}`);
|
|
10
|
-
},
|
|
11
|
-
info(m: string) {
|
|
12
|
-
console.log(`[test] ${m}`);
|
|
13
|
-
},
|
|
14
|
-
warn(m: string) {
|
|
15
|
-
console.warn(`[test] ${m}`);
|
|
16
|
-
},
|
|
17
|
-
};
|
|
@@ -97,7 +97,6 @@ function findViolations(code: string): Violation[] {
|
|
|
97
97
|
function isNodeOnlyFile(id: string): boolean {
|
|
98
98
|
// These files are only loaded via dynamic import on the Node path.
|
|
99
99
|
if (id.includes("/storage/node")) return true;
|
|
100
|
-
if (id.includes("/utils/createLogger")) return true;
|
|
101
100
|
return false;
|
|
102
101
|
}
|
|
103
102
|
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
|
|
8
8
|
import type { ClientOptions, Message } from "../../index.js";
|
|
9
9
|
import type { Storage } from "../../Storage.js";
|
|
10
|
-
import type { Logger } from "../../transport/types.js";
|
|
11
10
|
|
|
12
11
|
import { Client } from "../../index.js";
|
|
13
12
|
|
|
@@ -15,7 +14,6 @@ import { testFile, testImage } from "./fixtures.js";
|
|
|
15
14
|
|
|
16
15
|
export function platformSuite(
|
|
17
16
|
platformName: string,
|
|
18
|
-
logger: Logger,
|
|
19
17
|
makeStorage: (SK: string, opts: ClientOptions) => Promise<Storage>,
|
|
20
18
|
) {
|
|
21
19
|
describe.sequential(`platform: ${platformName}`, () => {
|
|
@@ -25,11 +23,9 @@ export function platformSuite(
|
|
|
25
23
|
|
|
26
24
|
beforeAll(async () => {
|
|
27
25
|
const SK = Client.generateSecretKey();
|
|
26
|
+
|
|
28
27
|
const opts: ClientOptions = {
|
|
29
|
-
dbLogLevel: "error",
|
|
30
28
|
inMemoryDb: true,
|
|
31
|
-
logger,
|
|
32
|
-
logLevel: "error",
|
|
33
29
|
...apiUrlOverrideFromEnv(),
|
|
34
30
|
};
|
|
35
31
|
const storage = await makeStorage(SK, opts);
|
|
@@ -73,10 +69,7 @@ export function platformSuite(
|
|
|
73
69
|
test("two-user DM", async () => {
|
|
74
70
|
const SK2 = Client.generateSecretKey();
|
|
75
71
|
const opts2: ClientOptions = {
|
|
76
|
-
dbLogLevel: "error",
|
|
77
72
|
inMemoryDb: true,
|
|
78
|
-
logger,
|
|
79
|
-
logLevel: "error",
|
|
80
73
|
...apiUrlOverrideFromEnv(),
|
|
81
74
|
};
|
|
82
75
|
const storage2 = await makeStorage(SK2, opts2);
|
|
@@ -113,10 +106,7 @@ export function platformSuite(
|
|
|
113
106
|
test("group messaging in channel", async () => {
|
|
114
107
|
const SK2 = Client.generateSecretKey();
|
|
115
108
|
const opts2: ClientOptions = {
|
|
116
|
-
dbLogLevel: "error",
|
|
117
109
|
inMemoryDb: true,
|
|
118
|
-
logger,
|
|
119
|
-
logLevel: "error",
|
|
120
110
|
...apiUrlOverrideFromEnv(),
|
|
121
111
|
};
|
|
122
112
|
const storage2 = await makeStorage(SK2, opts2);
|
|
@@ -174,10 +164,7 @@ export function platformSuite(
|
|
|
174
164
|
const deviceKey = client.getKeys().private;
|
|
175
165
|
const deviceID = client.me.device().deviceID;
|
|
176
166
|
const opts2: ClientOptions = {
|
|
177
|
-
dbLogLevel: "error",
|
|
178
167
|
inMemoryDb: true,
|
|
179
|
-
logger,
|
|
180
|
-
logLevel: "error",
|
|
181
168
|
...apiUrlOverrideFromEnv(),
|
|
182
169
|
};
|
|
183
170
|
const storage2 = await makeStorage(deviceKey, opts2);
|
|
@@ -274,10 +261,7 @@ export function platformSuite(
|
|
|
274
261
|
test.todo("multi-device message sync", async () => {
|
|
275
262
|
const SK2 = Client.generateSecretKey();
|
|
276
263
|
const opts2: ClientOptions = {
|
|
277
|
-
dbLogLevel: "error",
|
|
278
264
|
inMemoryDb: true,
|
|
279
|
-
logger,
|
|
280
|
-
logLevel: "error",
|
|
281
265
|
...apiUrlOverrideFromEnv(),
|
|
282
266
|
};
|
|
283
267
|
const storage2 = await makeStorage(SK2, opts2);
|
|
@@ -286,10 +270,7 @@ export function platformSuite(
|
|
|
286
270
|
// Sender: separate user
|
|
287
271
|
const SK3 = Client.generateSecretKey();
|
|
288
272
|
const opts3: ClientOptions = {
|
|
289
|
-
dbLogLevel: "error",
|
|
290
273
|
inMemoryDb: true,
|
|
291
|
-
logger,
|
|
292
|
-
logLevel: "error",
|
|
293
274
|
...apiUrlOverrideFromEnv(),
|
|
294
275
|
};
|
|
295
276
|
const storage3 = await makeStorage(SK3, opts3);
|
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
import type { ClientOptions } from "../index.js";
|
|
2
2
|
|
|
3
3
|
import { MemoryStorage } from "./harness/memory-storage.js";
|
|
4
|
-
import { browserTestAdapters } from "./harness/platform-transports.js";
|
|
5
4
|
// Browser platform test — covers Tauri, Expo/RN, and web.
|
|
6
5
|
// Runs with the poison plugin (vitest.config.browser.ts) which catches
|
|
7
6
|
// Node builtins and globals at compile time. Uses MemoryStorage (no
|
|
8
7
|
// Node SQLite) and BrowserTestWS (Uint8Array binary).
|
|
9
8
|
import { platformSuite } from "./harness/shared-suite.js";
|
|
10
9
|
|
|
11
|
-
platformSuite(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
await storage.init();
|
|
17
|
-
return storage;
|
|
18
|
-
},
|
|
19
|
-
);
|
|
10
|
+
platformSuite("browser", async (SK: string, _opts: ClientOptions) => {
|
|
11
|
+
const storage = new MemoryStorage(SK);
|
|
12
|
+
await storage.init();
|
|
13
|
+
return storage;
|
|
14
|
+
});
|
|
@@ -2,9 +2,8 @@ import type { ClientOptions } from "../index.js";
|
|
|
2
2
|
|
|
3
3
|
import { createNodeStorage } from "../storage/node.js";
|
|
4
4
|
|
|
5
|
-
import { testLogger } from "./harness/platform-transports.js";
|
|
6
5
|
import { platformSuite } from "./harness/shared-suite.js";
|
|
7
6
|
|
|
8
|
-
platformSuite("node",
|
|
7
|
+
platformSuite("node", (SK: string, _opts: ClientOptions) =>
|
|
9
8
|
Promise.resolve(createNodeStorage(":memory:", SK)),
|
|
10
9
|
);
|
package/src/codec.ts
CHANGED
|
@@ -27,17 +27,17 @@ const _packr = new Packr({ moreTypes: false, useRecords: false });
|
|
|
27
27
|
export function createCodec<T extends z.ZodType>(schema: T) {
|
|
28
28
|
type Msg = z.infer<T>;
|
|
29
29
|
return {
|
|
30
|
-
/** Decode msgpack data
|
|
30
|
+
/** Decode msgpack data and validate against the schema. */
|
|
31
31
|
decode: (data: Uint8Array): Msg => schema.parse(decode(data)) as Msg,
|
|
32
32
|
|
|
33
|
-
/**
|
|
33
|
+
/** Alias for decode — both paths validate. Kept for API compat. */
|
|
34
34
|
decodeSafe: (data: Uint8Array): Msg =>
|
|
35
35
|
schema.parse(decode(data)) as Msg,
|
|
36
36
|
|
|
37
|
-
/** Encode to msgpack
|
|
37
|
+
/** Encode to msgpack. */
|
|
38
38
|
encode: (msg: Msg): Uint8Array => encode(msg),
|
|
39
39
|
|
|
40
|
-
/** Validate
|
|
40
|
+
/** Validate against the schema, then encode to msgpack. */
|
|
41
41
|
encodeSafe: (msg: Msg): Uint8Array => {
|
|
42
42
|
schema.parse(msg);
|
|
43
43
|
return encode(msg);
|
package/src/codecs.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { Client } from "./Client.js";
|
|
|
2
2
|
export type {
|
|
3
3
|
Channel,
|
|
4
4
|
Channels,
|
|
5
|
+
ClientEvents,
|
|
5
6
|
ClientOptions,
|
|
6
7
|
Device,
|
|
7
8
|
Devices,
|
|
@@ -27,7 +28,13 @@ export type {
|
|
|
27
28
|
} from "./Client.js";
|
|
28
29
|
export { createCodec, msgpack } from "./codec.js";
|
|
29
30
|
export type { Storage } from "./Storage.js";
|
|
30
|
-
export type {
|
|
31
|
-
|
|
31
|
+
export type {
|
|
32
|
+
KeyPair,
|
|
33
|
+
KeyStore,
|
|
34
|
+
PreKeysCrypto,
|
|
35
|
+
SessionCrypto,
|
|
36
|
+
StoredCredentials,
|
|
37
|
+
UnsavedPreKey,
|
|
38
|
+
} from "./types/index.js";
|
|
32
39
|
// Re-export app-facing types
|
|
33
40
|
export type { Invite } from "@vex-chat/types";
|
package/src/keystore/node.ts
CHANGED
|
@@ -13,8 +13,16 @@ import { XUtils } from "@vex-chat/crypto";
|
|
|
13
13
|
|
|
14
14
|
export class NodeKeyStore implements KeyStore {
|
|
15
15
|
private readonly dir: string;
|
|
16
|
+
private readonly passphrase: string;
|
|
16
17
|
|
|
17
|
-
constructor(dir: string = ".") {
|
|
18
|
+
constructor(passphrase: string, dir: string = ".") {
|
|
19
|
+
if (!passphrase) {
|
|
20
|
+
throw new Error(
|
|
21
|
+
"NodeKeyStore requires a non-empty passphrase. " +
|
|
22
|
+
"The caller must supply a passphrase sourced from user input, OS keychain, or similar.",
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
this.passphrase = passphrase;
|
|
18
26
|
this.dir = dir;
|
|
19
27
|
}
|
|
20
28
|
|
|
@@ -54,7 +62,7 @@ export class NodeKeyStore implements KeyStore {
|
|
|
54
62
|
|
|
55
63
|
save(creds: StoredCredentials): Promise<void> {
|
|
56
64
|
const data = JSON.stringify(creds);
|
|
57
|
-
const encrypted = XUtils.encryptKeyData(
|
|
65
|
+
const encrypted = XUtils.encryptKeyData(this.passphrase, data);
|
|
58
66
|
fs.writeFileSync(this.filePath(creds.username), encrypted);
|
|
59
67
|
return Promise.resolve();
|
|
60
68
|
}
|
|
@@ -66,7 +74,10 @@ export class NodeKeyStore implements KeyStore {
|
|
|
66
74
|
private readFile(filePath: string): null | StoredCredentials {
|
|
67
75
|
try {
|
|
68
76
|
const data = fs.readFileSync(filePath);
|
|
69
|
-
const decrypted = XUtils.decryptKeyData(
|
|
77
|
+
const decrypted = XUtils.decryptKeyData(
|
|
78
|
+
new Uint8Array(data),
|
|
79
|
+
this.passphrase,
|
|
80
|
+
);
|
|
70
81
|
const parsed: unknown = JSON.parse(decrypted);
|
|
71
82
|
if (isStoredCredentials(parsed)) {
|
|
72
83
|
return parsed;
|
package/src/preset/common.ts
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import type { Storage } from "../Storage.js";
|
|
2
|
-
import type { Logger } from "../transport/types.js";
|
|
3
2
|
|
|
4
3
|
/** Internal preset interface used by nodePreset and testPreset. */
|
|
5
4
|
export interface PlatformPreset {
|
|
6
|
-
createStorage(
|
|
7
|
-
dbName: string,
|
|
8
|
-
privateKey: string,
|
|
9
|
-
logger: Logger,
|
|
10
|
-
): Promise<Storage>;
|
|
5
|
+
createStorage(dbName: string, privateKey: string): Promise<Storage>;
|
|
11
6
|
deviceName: string;
|
|
12
|
-
logger: Logger;
|
|
13
7
|
}
|
package/src/preset/node.ts
CHANGED
|
@@ -1,34 +1,18 @@
|
|
|
1
1
|
import type { Storage } from "../Storage.js";
|
|
2
|
-
import type { Logger } from "../transport/types.js";
|
|
3
2
|
/**
|
|
4
3
|
* Platform preset for Node.js (CLI tools, bots, tests).
|
|
5
4
|
*
|
|
6
5
|
* - WebSocket: native global (Node 22+)
|
|
7
6
|
* - Storage: Kysely + better-sqlite3
|
|
8
|
-
* - Logger: winston (loaded dynamically)
|
|
9
7
|
*/
|
|
10
8
|
import type { PlatformPreset } from "./common.js";
|
|
11
9
|
|
|
12
|
-
export
|
|
13
|
-
const { createLogger } = await import("../utils/createLogger.js");
|
|
14
|
-
const logger: Logger = createLogger("libvex", logLevel);
|
|
15
|
-
|
|
10
|
+
export function nodePreset(): PlatformPreset {
|
|
16
11
|
return {
|
|
17
|
-
async createStorage(
|
|
18
|
-
dbName,
|
|
19
|
-
privateKey,
|
|
20
|
-
storageLogger,
|
|
21
|
-
): Promise<Storage> {
|
|
12
|
+
async createStorage(dbName, privateKey): Promise<Storage> {
|
|
22
13
|
const { createNodeStorage } = await import("../storage/node.js");
|
|
23
|
-
|
|
24
|
-
const storage: Storage = createNodeStorage(
|
|
25
|
-
dbName,
|
|
26
|
-
privateKey,
|
|
27
|
-
storageLogger,
|
|
28
|
-
);
|
|
29
|
-
return storage;
|
|
14
|
+
return createNodeStorage(dbName, privateKey);
|
|
30
15
|
},
|
|
31
16
|
deviceName: process.platform,
|
|
32
|
-
logger,
|
|
33
17
|
};
|
|
34
18
|
}
|
package/src/preset/test.ts
CHANGED
|
@@ -1,30 +1,14 @@
|
|
|
1
|
-
import type { Logger } from "../transport/types.js";
|
|
2
1
|
/**
|
|
3
2
|
* Platform preset for tests — no I/O, no platform dependencies.
|
|
4
3
|
*
|
|
5
4
|
* - WebSocket: native global (Node 22+)
|
|
6
5
|
* - Storage: in-memory (no persistence)
|
|
7
|
-
* - Logger: console
|
|
8
6
|
*/
|
|
9
7
|
import type { PlatformPreset } from "./common.js";
|
|
10
8
|
|
|
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
9
|
export function testPreset(): PlatformPreset {
|
|
25
10
|
return {
|
|
26
|
-
async createStorage(_dbName, privateKey
|
|
27
|
-
// Lazy import to avoid pulling eventemitter3 into the type graph
|
|
11
|
+
async createStorage(_dbName, privateKey) {
|
|
28
12
|
const { MemoryStorage } =
|
|
29
13
|
await import("../__tests__/harness/memory-storage.js");
|
|
30
14
|
const storage = new MemoryStorage(privateKey);
|
|
@@ -32,6 +16,5 @@ export function testPreset(): PlatformPreset {
|
|
|
32
16
|
return storage;
|
|
33
17
|
},
|
|
34
18
|
deviceName: "test",
|
|
35
|
-
logger,
|
|
36
19
|
};
|
|
37
20
|
}
|
package/src/storage/node.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { Storage } from "../Storage.js";
|
|
2
|
-
import type { Logger } from "../transport/types.js";
|
|
3
2
|
import type { ClientDatabase } from "./schema.js";
|
|
4
3
|
|
|
5
4
|
import BetterSqlite3 from "better-sqlite3";
|
|
@@ -11,23 +10,13 @@ import { Kysely, SqliteDialect } from "kysely";
|
|
|
11
10
|
|
|
12
11
|
import { SqliteStorage } from "./sqlite.js";
|
|
13
12
|
|
|
14
|
-
export function createNodeStorage(
|
|
15
|
-
dbPath: string,
|
|
16
|
-
SK: string,
|
|
17
|
-
logger?: Logger,
|
|
18
|
-
): Storage {
|
|
13
|
+
export function createNodeStorage(dbPath: string, SK: string): Storage {
|
|
19
14
|
const db = new Kysely<ClientDatabase>({
|
|
20
15
|
dialect: new SqliteDialect({
|
|
21
16
|
database: new BetterSqlite3(dbPath),
|
|
22
17
|
}),
|
|
23
18
|
});
|
|
24
|
-
const
|
|
25
|
-
debug() {},
|
|
26
|
-
error() {},
|
|
27
|
-
info() {},
|
|
28
|
-
warn() {},
|
|
29
|
-
};
|
|
30
|
-
const storage = new SqliteStorage(db, SK, log);
|
|
19
|
+
const storage = new SqliteStorage(db, SK);
|
|
31
20
|
void storage.init();
|
|
32
21
|
return storage;
|
|
33
22
|
}
|