@massalabs/gossip-sdk 0.0.2-dev.20260128094509 → 0.0.2-dev.20260128160824
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/dist/api/messageProtocol/index.d.ts +19 -0
- package/dist/api/messageProtocol/index.js +26 -0
- package/dist/api/messageProtocol/mock.d.ts +12 -0
- package/{src/api/messageProtocol/mock.ts → dist/api/messageProtocol/mock.js} +2 -3
- package/dist/api/messageProtocol/rest.d.ts +22 -0
- package/dist/api/messageProtocol/rest.js +161 -0
- package/dist/api/messageProtocol/types.d.ts +61 -0
- package/dist/api/messageProtocol/types.js +6 -0
- package/dist/assets/generated/wasm/README.md +281 -0
- package/dist/assets/generated/wasm/gossip_wasm.d.ts +638 -0
- package/dist/assets/generated/wasm/gossip_wasm.js +1557 -0
- package/dist/assets/generated/wasm/gossip_wasm_bg.wasm +0 -0
- package/dist/assets/generated/wasm/gossip_wasm_bg.wasm.d.ts +164 -0
- package/dist/assets/generated/wasm/package.json +15 -0
- package/dist/assets/generated/wasm-node/README.md +281 -0
- package/dist/assets/generated/wasm-node/gossip_wasm.d.ts +443 -0
- package/dist/assets/generated/wasm-node/gossip_wasm.js +1488 -0
- package/dist/assets/generated/wasm-node/gossip_wasm_bg.wasm +0 -0
- package/dist/assets/generated/wasm-node/gossip_wasm_bg.wasm.d.ts +164 -0
- package/dist/assets/generated/wasm-node/package.json +11 -0
- package/dist/config/protocol.d.ts +36 -0
- package/dist/config/protocol.js +77 -0
- package/dist/config/sdk.d.ts +82 -0
- package/dist/config/sdk.js +55 -0
- package/{src/contacts.ts → dist/contacts.d.ts} +11 -95
- package/dist/contacts.js +166 -0
- package/dist/core/SdkEventEmitter.d.ts +36 -0
- package/dist/core/SdkEventEmitter.js +59 -0
- package/dist/core/SdkPolling.d.ts +35 -0
- package/dist/core/SdkPolling.js +100 -0
- package/{src/core/index.ts → dist/core/index.d.ts} +0 -2
- package/dist/core/index.js +5 -0
- package/dist/crypto/bip39.d.ts +34 -0
- package/dist/crypto/bip39.js +62 -0
- package/dist/crypto/encryption.d.ts +37 -0
- package/dist/crypto/encryption.js +46 -0
- package/dist/db.d.ts +190 -0
- package/dist/db.js +311 -0
- package/dist/gossipSdk.d.ts +274 -0
- package/dist/gossipSdk.js +690 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.js +61 -0
- package/dist/services/announcement.d.ts +43 -0
- package/dist/services/announcement.js +491 -0
- package/dist/services/auth.d.ts +37 -0
- package/dist/services/auth.js +76 -0
- package/dist/services/discussion.d.ts +63 -0
- package/dist/services/discussion.js +297 -0
- package/dist/services/message.d.ts +74 -0
- package/dist/services/message.js +826 -0
- package/dist/services/refresh.d.ts +41 -0
- package/dist/services/refresh.js +205 -0
- package/{src/sw.ts → dist/sw.d.ts} +1 -8
- package/dist/sw.js +10 -0
- package/dist/types/events.d.ts +80 -0
- package/dist/types/events.js +7 -0
- package/dist/types.d.ts +32 -0
- package/dist/types.js +7 -0
- package/dist/utils/base64.d.ts +10 -0
- package/dist/utils/base64.js +30 -0
- package/dist/utils/contacts.d.ts +42 -0
- package/dist/utils/contacts.js +113 -0
- package/dist/utils/discussions.d.ts +24 -0
- package/dist/utils/discussions.js +38 -0
- package/dist/utils/logs.d.ts +19 -0
- package/dist/utils/logs.js +89 -0
- package/dist/utils/messageSerialization.d.ts +64 -0
- package/dist/utils/messageSerialization.js +184 -0
- package/dist/utils/queue.d.ts +50 -0
- package/dist/utils/queue.js +110 -0
- package/dist/utils/type.d.ts +10 -0
- package/dist/utils/type.js +4 -0
- package/dist/utils/userId.d.ts +40 -0
- package/dist/utils/userId.js +90 -0
- package/dist/utils/validation.d.ts +50 -0
- package/dist/utils/validation.js +112 -0
- package/dist/utils.d.ts +30 -0
- package/{src/utils.ts → dist/utils.js} +9 -19
- package/dist/wasm/encryption.d.ts +56 -0
- package/{src/wasm/encryption.ts → dist/wasm/encryption.js} +22 -51
- package/dist/wasm/index.d.ts +10 -0
- package/{src/wasm/index.ts → dist/wasm/index.js} +1 -8
- package/dist/wasm/loader.d.ts +22 -0
- package/dist/wasm/loader.js +78 -0
- package/dist/wasm/session.d.ts +85 -0
- package/dist/wasm/session.js +226 -0
- package/dist/wasm/userKeys.d.ts +17 -0
- package/{src/wasm/userKeys.ts → dist/wasm/userKeys.js} +6 -13
- package/package.json +15 -2
- package/src/api/messageProtocol/index.ts +0 -53
- package/src/api/messageProtocol/rest.ts +0 -209
- package/src/api/messageProtocol/types.ts +0 -70
- package/src/config/protocol.ts +0 -97
- package/src/config/sdk.ts +0 -131
- package/src/core/SdkEventEmitter.ts +0 -91
- package/src/core/SdkPolling.ts +0 -134
- package/src/crypto/bip39.ts +0 -84
- package/src/crypto/encryption.ts +0 -77
- package/src/db.ts +0 -465
- package/src/gossipSdk.ts +0 -994
- package/src/index.ts +0 -211
- package/src/services/announcement.ts +0 -653
- package/src/services/auth.ts +0 -95
- package/src/services/discussion.ts +0 -380
- package/src/services/message.ts +0 -1055
- package/src/services/refresh.ts +0 -234
- package/src/types/events.ts +0 -108
- package/src/types.ts +0 -70
- package/src/utils/base64.ts +0 -39
- package/src/utils/contacts.ts +0 -161
- package/src/utils/discussions.ts +0 -55
- package/src/utils/logs.ts +0 -86
- package/src/utils/messageSerialization.ts +0 -257
- package/src/utils/queue.ts +0 -106
- package/src/utils/type.ts +0 -7
- package/src/utils/userId.ts +0 -114
- package/src/utils/validation.ts +0 -144
- package/src/wasm/loader.ts +0 -123
- package/src/wasm/session.ts +0 -276
- package/test/config/protocol.spec.ts +0 -31
- package/test/config/sdk.spec.ts +0 -163
- package/test/db/helpers.spec.ts +0 -142
- package/test/db/operations.spec.ts +0 -128
- package/test/db/states.spec.ts +0 -535
- package/test/integration/discussion-flow.spec.ts +0 -422
- package/test/integration/messaging-flow.spec.ts +0 -708
- package/test/integration/sdk-lifecycle.spec.ts +0 -325
- package/test/mocks/index.ts +0 -9
- package/test/mocks/mockMessageProtocol.ts +0 -100
- package/test/services/auth.spec.ts +0 -311
- package/test/services/discussion.spec.ts +0 -279
- package/test/services/message-deduplication.spec.ts +0 -299
- package/test/services/message-startup.spec.ts +0 -331
- package/test/services/message.spec.ts +0 -817
- package/test/services/refresh.spec.ts +0 -199
- package/test/services/session-status.spec.ts +0 -349
- package/test/session/wasm.spec.ts +0 -227
- package/test/setup.ts +0 -52
- package/test/utils/contacts.spec.ts +0 -156
- package/test/utils/discussions.spec.ts +0 -66
- package/test/utils/queue.spec.ts +0 -52
- package/test/utils/serialization.spec.ts +0 -120
- package/test/utils/userId.spec.ts +0 -120
- package/test/utils/validation.spec.ts +0 -223
- package/test/utils.ts +0 -212
- package/tsconfig.json +0 -26
- package/tsconfig.tsbuildinfo +0 -1
- package/vitest.config.ts +0 -28
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* UserId utilities tests
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { describe, it, expect, beforeAll } from 'vitest';
|
|
6
|
-
import {
|
|
7
|
-
encodeUserId,
|
|
8
|
-
decodeUserId,
|
|
9
|
-
isValidUserId,
|
|
10
|
-
formatUserId,
|
|
11
|
-
generate as generateUserId,
|
|
12
|
-
} from '../../src/utils/userId';
|
|
13
|
-
import { bech32 } from '@scure/base';
|
|
14
|
-
import { ensureWasmInitialized } from '../../src/wasm/loader';
|
|
15
|
-
|
|
16
|
-
describe('userId utils', () => {
|
|
17
|
-
describe('encodeUserId / decodeUserId', () => {
|
|
18
|
-
it('encodes and decodes a 32-byte userId', () => {
|
|
19
|
-
const bytes = new Uint8Array(32).fill(7);
|
|
20
|
-
const encoded = encodeUserId(bytes);
|
|
21
|
-
const decoded = decodeUserId(encoded);
|
|
22
|
-
expect(decoded).toEqual(bytes);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('throws on invalid length', () => {
|
|
26
|
-
expect(() => encodeUserId(new Uint8Array(31))).toThrow(
|
|
27
|
-
'User ID must be exactly 32 bytes'
|
|
28
|
-
);
|
|
29
|
-
expect(() => encodeUserId(new Uint8Array(64))).toThrow(
|
|
30
|
-
'User ID must be exactly 32 bytes'
|
|
31
|
-
);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('throws on invalid prefix', () => {
|
|
35
|
-
const bytes = new Uint8Array(32).fill(8);
|
|
36
|
-
const invalid = bech32.encode('wrong', bech32.toWords(bytes));
|
|
37
|
-
expect(() => decodeUserId(invalid)).toThrow('Invalid prefix');
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
describe('isValidUserId', () => {
|
|
42
|
-
it('validates userId format', () => {
|
|
43
|
-
const encoded = encodeUserId(new Uint8Array(32).fill(1));
|
|
44
|
-
expect(isValidUserId(encoded)).toBe(true);
|
|
45
|
-
expect(isValidUserId('invalid')).toBe(false);
|
|
46
|
-
expect(isValidUserId('gossip1')).toBe(false);
|
|
47
|
-
expect(isValidUserId('not-a-gossip-id')).toBe(false);
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
describe('formatUserId', () => {
|
|
52
|
-
it('formats userId for display', () => {
|
|
53
|
-
const encoded = encodeUserId(new Uint8Array(32).fill(2));
|
|
54
|
-
const formatted = formatUserId(encoded, 4, 4);
|
|
55
|
-
expect(formatted.startsWith('gossip1')).toBe(true);
|
|
56
|
-
expect(formatted.includes('...')).toBe(true);
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
describe('userId utils (generate)', () => {
|
|
62
|
-
beforeAll(async () => {
|
|
63
|
-
await ensureWasmInitialized();
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('should generate a valid userId without password', async () => {
|
|
67
|
-
const userId = await generateUserId();
|
|
68
|
-
|
|
69
|
-
expect(userId).toBeTruthy();
|
|
70
|
-
expect(typeof userId).toBe('string');
|
|
71
|
-
expect(userId.startsWith('gossip1')).toBe(true);
|
|
72
|
-
expect(isValidUserId(userId)).toBe(true);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('should generate a valid userId with password', async () => {
|
|
76
|
-
const userId = await generateUserId('mypassword123');
|
|
77
|
-
|
|
78
|
-
expect(userId).toBeTruthy();
|
|
79
|
-
expect(typeof userId).toBe('string');
|
|
80
|
-
expect(userId.startsWith('gossip1')).toBe(true);
|
|
81
|
-
expect(isValidUserId(userId)).toBe(true);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it('should generate same userId when called without password (deterministic)', async () => {
|
|
85
|
-
const userId1 = await generateUserId();
|
|
86
|
-
const userId2 = await generateUserId();
|
|
87
|
-
|
|
88
|
-
expect(userId1).toBe(userId2);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('should generate userId that can be decoded', async () => {
|
|
92
|
-
const userId = await generateUserId();
|
|
93
|
-
const decoded = decodeUserId(userId);
|
|
94
|
-
|
|
95
|
-
expect(decoded).toBeInstanceOf(Uint8Array);
|
|
96
|
-
expect(decoded.length).toBe(32);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
it('should generate different userIds with different passwords', async () => {
|
|
100
|
-
const userId1 = await generateUserId('password1');
|
|
101
|
-
const userId2 = await generateUserId('password2');
|
|
102
|
-
|
|
103
|
-
expect(userId1).not.toBe(userId2);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it('should handle empty string password', async () => {
|
|
107
|
-
const userId = await generateUserId('');
|
|
108
|
-
|
|
109
|
-
expect(userId).toBeTruthy();
|
|
110
|
-
expect(isValidUserId(userId)).toBe(true);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it('should generate valid 32-byte decoded ids', async () => {
|
|
114
|
-
for (let i = 0; i < 5; i++) {
|
|
115
|
-
const userId = await generateUserId();
|
|
116
|
-
const decoded = decodeUserId(userId);
|
|
117
|
-
expect(decoded.length).toBe(32);
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
});
|
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Validation utilities tests
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { describe, it, expect, beforeEach } from 'vitest';
|
|
6
|
-
import { db } from '../../src/db';
|
|
7
|
-
import { encodeUserId } from '../../src/utils/userId';
|
|
8
|
-
import {
|
|
9
|
-
validatePassword,
|
|
10
|
-
validateUsernameFormat,
|
|
11
|
-
validateUsernameAvailability,
|
|
12
|
-
validateUsernameFormatAndAvailability,
|
|
13
|
-
validateUserIdFormat,
|
|
14
|
-
} from '../../src/utils/validation';
|
|
15
|
-
|
|
16
|
-
const VALIDATION_OWNER_USER_ID = encodeUserId(new Uint8Array(32).fill(13));
|
|
17
|
-
|
|
18
|
-
describe('validation utilities', () => {
|
|
19
|
-
beforeEach(async () => {
|
|
20
|
-
if (!db.isOpen()) {
|
|
21
|
-
await db.open();
|
|
22
|
-
}
|
|
23
|
-
await Promise.all(db.tables.map(table => table.clear()));
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
describe('validatePassword', () => {
|
|
27
|
-
it('should reject empty password', () => {
|
|
28
|
-
const result = validatePassword('');
|
|
29
|
-
expect(result.valid).toBe(false);
|
|
30
|
-
expect(result.error).toBe('Password is required');
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('should reject password with only whitespace', () => {
|
|
34
|
-
const result = validatePassword(' ');
|
|
35
|
-
expect(result.valid).toBe(false);
|
|
36
|
-
expect(result.error).toBe('Password is required');
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('should reject password shorter than 8 characters', () => {
|
|
40
|
-
const result = validatePassword('short');
|
|
41
|
-
expect(result.valid).toBe(false);
|
|
42
|
-
expect(result.error).toBe('Password must be at least 8 characters long');
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('should accept password with exactly 8 characters', () => {
|
|
46
|
-
const result = validatePassword('12345678');
|
|
47
|
-
expect(result.valid).toBe(true);
|
|
48
|
-
expect(result.error).toBeUndefined();
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('should accept valid password', () => {
|
|
52
|
-
const result = validatePassword('validPassword123');
|
|
53
|
-
expect(result.valid).toBe(true);
|
|
54
|
-
expect(result.error).toBeUndefined();
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('should accept password with special characters', () => {
|
|
58
|
-
const result = validatePassword('P@ssw0rd!#$%');
|
|
59
|
-
expect(result.valid).toBe(true);
|
|
60
|
-
expect(result.error).toBeUndefined();
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it('should accept very long password', () => {
|
|
64
|
-
const result = validatePassword('a'.repeat(100));
|
|
65
|
-
expect(result.valid).toBe(true);
|
|
66
|
-
expect(result.error).toBeUndefined();
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
describe('validateUsernameFormat', () => {
|
|
71
|
-
it('should reject empty username', () => {
|
|
72
|
-
const result = validateUsernameFormat('');
|
|
73
|
-
expect(result.valid).toBe(false);
|
|
74
|
-
expect(result.error).toBe('Username is required');
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('should reject username with only whitespace', () => {
|
|
78
|
-
const result = validateUsernameFormat(' ');
|
|
79
|
-
expect(result.valid).toBe(false);
|
|
80
|
-
expect(result.error).toBe('Username is required');
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it('should reject username shorter than 3 characters', () => {
|
|
84
|
-
const result = validateUsernameFormat('ab');
|
|
85
|
-
expect(result.valid).toBe(false);
|
|
86
|
-
expect(result.error).toBe('Username must be at least 3 characters long');
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it('should reject username shorter than 3 characters after trimming', () => {
|
|
90
|
-
const result = validateUsernameFormat(' ab ');
|
|
91
|
-
expect(result.valid).toBe(false);
|
|
92
|
-
expect(result.error).toBe('Username must be at least 3 characters long');
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it('should accept username with exactly 3 characters', () => {
|
|
96
|
-
const result = validateUsernameFormat('abc');
|
|
97
|
-
expect(result.valid).toBe(true);
|
|
98
|
-
expect(result.error).toBeUndefined();
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it('should accept valid username', () => {
|
|
102
|
-
const result = validateUsernameFormat('validUser');
|
|
103
|
-
expect(result.valid).toBe(true);
|
|
104
|
-
expect(result.error).toBeUndefined();
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it('should accept username with numbers', () => {
|
|
108
|
-
const result = validateUsernameFormat('user123');
|
|
109
|
-
expect(result.valid).toBe(true);
|
|
110
|
-
expect(result.error).toBeUndefined();
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it('should accept username with special characters', () => {
|
|
114
|
-
const result = validateUsernameFormat('user_name-123');
|
|
115
|
-
expect(result.valid).toBe(true);
|
|
116
|
-
expect(result.error).toBeUndefined();
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it('should handle username with leading/trailing whitespace', () => {
|
|
120
|
-
const result = validateUsernameFormat(' user ');
|
|
121
|
-
expect(result.valid).toBe(true);
|
|
122
|
-
expect(result.error).toBeUndefined();
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it('should reject username with internal spaces', () => {
|
|
126
|
-
const result = validateUsernameFormat('user name');
|
|
127
|
-
expect(result.valid).toBe(false);
|
|
128
|
-
expect(result.error).toBe('Username cannot contain spaces');
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
describe('validateUsernameAvailability', () => {
|
|
133
|
-
it('checks username availability case-insensitively', async () => {
|
|
134
|
-
await db.userProfile.put({
|
|
135
|
-
userId: VALIDATION_OWNER_USER_ID,
|
|
136
|
-
username: 'Alice',
|
|
137
|
-
security: {
|
|
138
|
-
encKeySalt: new Uint8Array(),
|
|
139
|
-
authMethod: 'password',
|
|
140
|
-
mnemonicBackup: {
|
|
141
|
-
encryptedMnemonic: new Uint8Array(),
|
|
142
|
-
createdAt: new Date(),
|
|
143
|
-
backedUp: false,
|
|
144
|
-
},
|
|
145
|
-
},
|
|
146
|
-
session: new Uint8Array(),
|
|
147
|
-
status: 'online',
|
|
148
|
-
lastSeen: new Date(),
|
|
149
|
-
createdAt: new Date(),
|
|
150
|
-
updatedAt: new Date(),
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
const result = await validateUsernameAvailability('alice', db);
|
|
154
|
-
expect(result.valid).toBe(false);
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
describe('validateUsernameFormatAndAvailability', () => {
|
|
159
|
-
it('validates username format and availability', async () => {
|
|
160
|
-
const invalid = await validateUsernameFormatAndAvailability('ab', db);
|
|
161
|
-
expect(invalid.valid).toBe(false);
|
|
162
|
-
|
|
163
|
-
const valid = await validateUsernameFormatAndAvailability(
|
|
164
|
-
'validname',
|
|
165
|
-
db
|
|
166
|
-
);
|
|
167
|
-
expect(valid.valid).toBe(true);
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
describe('validateUserIdFormat', () => {
|
|
172
|
-
const invalidUserIdMessage = 'Invalid format — must be a valid user ID';
|
|
173
|
-
|
|
174
|
-
it('should reject empty userId', () => {
|
|
175
|
-
const result = validateUserIdFormat('');
|
|
176
|
-
expect(result.valid).toBe(false);
|
|
177
|
-
expect(result.error).toBe(invalidUserIdMessage);
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it('should reject userId with invalid format', () => {
|
|
181
|
-
const result = validateUserIdFormat('invalid');
|
|
182
|
-
expect(result.valid).toBe(false);
|
|
183
|
-
expect(result.error).toBe(invalidUserIdMessage);
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
it('should reject userId with wrong prefix', () => {
|
|
187
|
-
const result = validateUserIdFormat(
|
|
188
|
-
'bitcoin1qpzry9x8gf2tvdw0s3jn54khce6mua7l'
|
|
189
|
-
);
|
|
190
|
-
expect(result.valid).toBe(false);
|
|
191
|
-
expect(result.error).toBe(invalidUserIdMessage);
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
it('should reject userId with invalid checksum', () => {
|
|
195
|
-
const result = validateUserIdFormat('gossip1invalid');
|
|
196
|
-
expect(result.valid).toBe(false);
|
|
197
|
-
expect(result.error).toBe(invalidUserIdMessage);
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
it('should accept valid userId', () => {
|
|
201
|
-
const validUserId = encodeUserId(new Uint8Array(32).fill(1));
|
|
202
|
-
const result = validateUserIdFormat(validUserId);
|
|
203
|
-
expect(result.valid).toBe(true);
|
|
204
|
-
expect(result.error).toBeUndefined();
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
it('should handle userId with whitespace', () => {
|
|
208
|
-
const validUserId = encodeUserId(new Uint8Array(32).fill(1));
|
|
209
|
-
const result = validateUserIdFormat(` ${validUserId} `);
|
|
210
|
-
expect(result.valid).toBe(true);
|
|
211
|
-
expect(result.error).toBeUndefined();
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
it('should accept multiple different valid userIds', () => {
|
|
215
|
-
for (let i = 0; i < 5; i++) {
|
|
216
|
-
const userId = encodeUserId(new Uint8Array(32).fill(i));
|
|
217
|
-
const result = validateUserIdFormat(userId);
|
|
218
|
-
expect(result.valid).toBe(true);
|
|
219
|
-
expect(result.error).toBeUndefined();
|
|
220
|
-
}
|
|
221
|
-
});
|
|
222
|
-
});
|
|
223
|
-
});
|
package/test/utils.ts
DELETED
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SDK Test Utilities
|
|
3
|
-
*
|
|
4
|
-
* Helper functions for creating test data and utilities.
|
|
5
|
-
* Uses real WASM SessionModule - no mocks needed.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type { Contact, Discussion, Message, UserProfile } from '../src/db';
|
|
9
|
-
import {
|
|
10
|
-
UserPublicKeys,
|
|
11
|
-
UserKeys,
|
|
12
|
-
} from '../src/assets/generated/wasm/gossip_wasm';
|
|
13
|
-
import { generateUserKeys } from '../src/wasm/userKeys';
|
|
14
|
-
import { SessionModule } from '../src/wasm/session';
|
|
15
|
-
import {
|
|
16
|
-
MessageType,
|
|
17
|
-
MessageDirection,
|
|
18
|
-
MessageStatus,
|
|
19
|
-
DiscussionStatus,
|
|
20
|
-
DiscussionDirection,
|
|
21
|
-
} from '../src/db';
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Create a test contact object (without id).
|
|
25
|
-
*/
|
|
26
|
-
export function createTestContact(
|
|
27
|
-
ownerUserId: string,
|
|
28
|
-
userId: string,
|
|
29
|
-
name: string,
|
|
30
|
-
publicKeys: UserPublicKeys
|
|
31
|
-
): Omit<Contact, 'id'> {
|
|
32
|
-
return {
|
|
33
|
-
ownerUserId,
|
|
34
|
-
userId,
|
|
35
|
-
name,
|
|
36
|
-
publicKeys: publicKeys.to_bytes(),
|
|
37
|
-
isOnline: false,
|
|
38
|
-
lastSeen: new Date(),
|
|
39
|
-
createdAt: new Date(),
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Create a test discussion object (without id).
|
|
45
|
-
*/
|
|
46
|
-
export function createTestDiscussion(
|
|
47
|
-
ownerUserId: string,
|
|
48
|
-
contactUserId: string,
|
|
49
|
-
status: DiscussionStatus = DiscussionStatus.ACTIVE,
|
|
50
|
-
direction: DiscussionDirection = DiscussionDirection.INITIATED
|
|
51
|
-
): Omit<Discussion, 'id'> {
|
|
52
|
-
return {
|
|
53
|
-
ownerUserId,
|
|
54
|
-
contactUserId,
|
|
55
|
-
direction,
|
|
56
|
-
status,
|
|
57
|
-
unreadCount: 0,
|
|
58
|
-
createdAt: new Date(),
|
|
59
|
-
updatedAt: new Date(),
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Create a test message object (without id).
|
|
65
|
-
*/
|
|
66
|
-
export function createTestMessage(
|
|
67
|
-
ownerUserId: string,
|
|
68
|
-
contactUserId: string,
|
|
69
|
-
content: string,
|
|
70
|
-
direction: MessageDirection = MessageDirection.OUTGOING,
|
|
71
|
-
status: MessageStatus = MessageStatus.SENT
|
|
72
|
-
): Omit<Message, 'id'> {
|
|
73
|
-
return {
|
|
74
|
-
ownerUserId,
|
|
75
|
-
contactUserId,
|
|
76
|
-
content,
|
|
77
|
-
type: MessageType.TEXT,
|
|
78
|
-
direction,
|
|
79
|
-
status,
|
|
80
|
-
timestamp: new Date(),
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Create a test user profile object (without session).
|
|
86
|
-
*/
|
|
87
|
-
export function createTestUserProfile(
|
|
88
|
-
userId: string,
|
|
89
|
-
username: string
|
|
90
|
-
): Omit<UserProfile, 'session'> {
|
|
91
|
-
return {
|
|
92
|
-
userId,
|
|
93
|
-
username,
|
|
94
|
-
security: {
|
|
95
|
-
encKeySalt: new Uint8Array(32),
|
|
96
|
-
authMethod: 'password',
|
|
97
|
-
mnemonicBackup: {
|
|
98
|
-
encryptedMnemonic: new Uint8Array(64),
|
|
99
|
-
createdAt: new Date(),
|
|
100
|
-
backedUp: false,
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
status: 'online',
|
|
104
|
-
lastSeen: new Date(),
|
|
105
|
-
createdAt: new Date(),
|
|
106
|
-
updatedAt: new Date(),
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Wait for a condition to be true.
|
|
112
|
-
*/
|
|
113
|
-
export function waitFor(
|
|
114
|
-
condition: () => boolean,
|
|
115
|
-
timeout = 5000,
|
|
116
|
-
interval = 100
|
|
117
|
-
): Promise<void> {
|
|
118
|
-
return new Promise((resolve, reject) => {
|
|
119
|
-
const startTime = Date.now();
|
|
120
|
-
const check = () => {
|
|
121
|
-
if (condition()) {
|
|
122
|
-
resolve();
|
|
123
|
-
} else if (Date.now() - startTime > timeout) {
|
|
124
|
-
reject(new Error('Timeout waiting for condition'));
|
|
125
|
-
} else {
|
|
126
|
-
setTimeout(check, interval);
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
check();
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Wait for a specified number of milliseconds.
|
|
135
|
-
*/
|
|
136
|
-
export function sleep(ms: number): Promise<void> {
|
|
137
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Test session data structure returned by createTestSession.
|
|
142
|
-
*/
|
|
143
|
-
export interface TestSessionData {
|
|
144
|
-
session: SessionModule;
|
|
145
|
-
userKeys: UserKeys;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Create a real SessionModule using WASM.
|
|
150
|
-
* This creates a fully functional session with real crypto.
|
|
151
|
-
*
|
|
152
|
-
* @param passphrase - Optional passphrase for key generation (defaults to random)
|
|
153
|
-
* @param onPersist - Optional persistence callback
|
|
154
|
-
* @returns Object containing session and userKeys (remember to call cleanupTestSession when done)
|
|
155
|
-
*/
|
|
156
|
-
export async function createTestSession(
|
|
157
|
-
passphrase?: string,
|
|
158
|
-
onPersist?: () => Promise<void>
|
|
159
|
-
): Promise<TestSessionData> {
|
|
160
|
-
const finalPassphrase =
|
|
161
|
-
passphrase ?? `test-passphrase-${Date.now()}-${Math.random()}`;
|
|
162
|
-
const userKeys = await generateUserKeys(finalPassphrase);
|
|
163
|
-
|
|
164
|
-
if (!userKeys) {
|
|
165
|
-
throw new Error('Failed to generate user keys for test session');
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const session = new SessionModule(userKeys, onPersist);
|
|
169
|
-
return { session, userKeys };
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Create a pair of test sessions (e.g., Alice and Bob) for e2e testing.
|
|
174
|
-
* Both sessions use real WASM crypto.
|
|
175
|
-
*
|
|
176
|
-
* @returns Object containing both sessions and their keys
|
|
177
|
-
*/
|
|
178
|
-
export async function createTestSessionPair(): Promise<{
|
|
179
|
-
alice: TestSessionData;
|
|
180
|
-
bob: TestSessionData;
|
|
181
|
-
}> {
|
|
182
|
-
const [alice, bob] = await Promise.all([
|
|
183
|
-
createTestSession(`alice-test-key-${Date.now()}`),
|
|
184
|
-
createTestSession(`bob-test-key-${Date.now()}`),
|
|
185
|
-
]);
|
|
186
|
-
|
|
187
|
-
return { alice, bob };
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Helper to cleanup test sessions and free WASM memory.
|
|
192
|
-
* Call this in afterEach/afterAll.
|
|
193
|
-
*/
|
|
194
|
-
export function cleanupTestSession(sessionData: TestSessionData): void {
|
|
195
|
-
try {
|
|
196
|
-
sessionData.session.cleanup();
|
|
197
|
-
} catch {
|
|
198
|
-
// Session might already be cleaned up
|
|
199
|
-
}
|
|
200
|
-
try {
|
|
201
|
-
sessionData.userKeys.free();
|
|
202
|
-
} catch {
|
|
203
|
-
// Keys might already be freed
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Helper to cleanup multiple test sessions.
|
|
209
|
-
*/
|
|
210
|
-
export function cleanupTestSessions(sessions: TestSessionData[]): void {
|
|
211
|
-
sessions.forEach(cleanupTestSession);
|
|
212
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"useDefineForClassFields": true,
|
|
5
|
-
"lib": ["ES2020", "DOM"],
|
|
6
|
-
"module": "ESNext",
|
|
7
|
-
"skipLibCheck": true,
|
|
8
|
-
"moduleResolution": "bundler",
|
|
9
|
-
"isolatedModules": true,
|
|
10
|
-
"moduleDetection": "force",
|
|
11
|
-
"noEmit": false,
|
|
12
|
-
"declaration": true,
|
|
13
|
-
"outDir": "dist",
|
|
14
|
-
"rootDir": "src",
|
|
15
|
-
"strict": true,
|
|
16
|
-
"noUnusedLocals": true,
|
|
17
|
-
"noUnusedParameters": true,
|
|
18
|
-
"noFallthroughCasesInSwitch": true,
|
|
19
|
-
"noUncheckedSideEffectImports": true,
|
|
20
|
-
"resolveJsonModule": true,
|
|
21
|
-
"esModuleInterop": true,
|
|
22
|
-
"allowSyntheticDefaultImports": true,
|
|
23
|
-
"types": ["vite/client"]
|
|
24
|
-
},
|
|
25
|
-
"include": ["src"]
|
|
26
|
-
}
|
package/tsconfig.tsbuildinfo
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"root":["./src/contacts.ts","./src/db.ts","./src/gossipsdk.ts","./src/index.ts","./src/types.ts","./src/utils.ts","./src/api/messageprotocol/index.ts","./src/api/messageprotocol/mock.ts","./src/api/messageprotocol/rest.ts","./src/api/messageprotocol/types.ts","./src/assets/generated/wasm/gossip_wasm.d.ts","./src/assets/generated/wasm/gossip_wasm_bg.wasm.d.ts","./src/config/protocol.ts","./src/config/sdk.ts","./src/core/sdkeventemitter.ts","./src/core/sdkpolling.ts","./src/core/index.ts","./src/crypto/bip39.ts","./src/crypto/encryption.ts","./src/services/announcement.ts","./src/services/auth.ts","./src/services/discussion.ts","./src/services/message.ts","./src/services/refresh.ts","./src/types/events.ts","./src/utils/base64.ts","./src/utils/contacts.ts","./src/utils/discussions.ts","./src/utils/logs.ts","./src/utils/messageserialization.ts","./src/utils/queue.ts","./src/utils/type.ts","./src/utils/userid.ts","./src/utils/validation.ts","./src/wasm/encryption.ts","./src/wasm/index.ts","./src/wasm/loader.ts","./src/wasm/session.ts","./src/wasm/userkeys.ts","./test/announcement-service.test.ts","./test/auth-service.test.ts","./test/auto-accept.test.ts","./test/contacts-utils.test.ts","./test/db-helpers.test.ts","./test/db-operations.test.ts","./test/db-simple.test.ts","./test/discussion-service.test.ts","./test/discussions-utils.test.ts","./test/edge-cases.test.ts","./test/gossip-sdk-lifecycle.test.ts","./test/helpers.ts","./test/high-priority-gaps.test.ts","./test/index.test.ts","./test/message-deduplication.test.ts","./test/message-serialization.test.ts","./test/message-service.test.ts","./test/protocol-config.test.ts","./test/queue-utils.test.ts","./test/refresh-service.test.ts","./test/sdk-config.test.ts","./test/sending-reset.test.ts","./test/session-persistence.test.ts","./test/setup.ts","./test/startup-recovery.test.ts","./test/user-id-utils.test.ts","./test/validation-utils.test.ts","./test/waiting-session-after-accept.test.ts","../src/vite-env.d.ts"],"errors":true,"version":"5.9.3"}
|
package/vitest.config.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vitest/config';
|
|
2
|
-
import { fileURLToPath } from 'url';
|
|
3
|
-
import { dirname, resolve } from 'path';
|
|
4
|
-
|
|
5
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
-
const __dirname = dirname(__filename);
|
|
7
|
-
|
|
8
|
-
export default defineConfig({
|
|
9
|
-
test: {
|
|
10
|
-
globals: true,
|
|
11
|
-
environment: 'node',
|
|
12
|
-
setupFiles: [resolve(__dirname, 'test/setup.ts')],
|
|
13
|
-
include: ['test/**/*.{test,spec}.{js,ts}'],
|
|
14
|
-
// Run tests sequentially to avoid database conflicts
|
|
15
|
-
isolate: false,
|
|
16
|
-
fileParallelism: false,
|
|
17
|
-
coverage: {
|
|
18
|
-
provider: 'v8',
|
|
19
|
-
reporter: ['text', 'json', 'html'],
|
|
20
|
-
exclude: ['node_modules/', 'test/', '**/*.d.ts', '**/*.config.*'],
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
resolve: {
|
|
24
|
-
alias: {
|
|
25
|
-
'@': resolve(__dirname, 'src'),
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
});
|