@massalabs/gossip-sdk 0.0.2-dev.20260211140005 → 0.0.2-dev.20260212071538
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 +110 -207
- package/dist/db.d.ts +2 -13
- package/dist/db.js +4 -45
- package/dist/gossipSdk.d.ts +23 -34
- package/dist/gossipSdk.js +103 -103
- package/dist/index.d.ts +21 -52
- package/dist/index.js +34 -52
- package/dist/services/announcement.d.ts +1 -4
- package/dist/services/announcement.js +1 -12
- package/dist/services/discussion.d.ts +1 -4
- package/dist/services/discussion.js +2 -27
- package/dist/services/message.d.ts +1 -4
- package/dist/services/message.js +1 -16
- package/dist/wasm/session.d.ts +1 -2
- package/dist/wasm/session.js +8 -2
- package/package.json +1 -1
- package/dist/types.d.ts +0 -32
- package/dist/types.js +0 -7
- package/dist/utils.d.ts +0 -30
- package/dist/utils.js +0 -37
package/README.md
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
# Gossip SDK
|
|
2
2
|
|
|
3
|
-
A platform-agnostic SDK for the Gossip messenger app.
|
|
3
|
+
A platform-agnostic SDK for the Gossip messenger app. Enables automation, chatbot integrations, and programmatic access to Gossip functionality.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
7
|
The Gossip SDK provides a clean, typed interface for:
|
|
8
8
|
|
|
9
|
-
- **Account Management** - Create, load, restore, and manage user accounts
|
|
10
9
|
- **Contact Management** - Add, update, and delete contacts
|
|
11
10
|
- **Discussion Management** - Initialize and manage encrypted discussions
|
|
12
11
|
- **Message Operations** - Send and receive encrypted messages
|
|
@@ -16,74 +15,53 @@ The Gossip SDK provides a clean, typed interface for:
|
|
|
16
15
|
## Installation
|
|
17
16
|
|
|
18
17
|
```bash
|
|
19
|
-
|
|
20
|
-
npm install
|
|
18
|
+
npm install @massalabs/gossip-sdk
|
|
21
19
|
```
|
|
22
20
|
|
|
23
|
-
### Peer Dependencies
|
|
24
|
-
|
|
25
|
-
The SDK requires these peer dependencies (provided by the host project):
|
|
26
|
-
|
|
27
|
-
- `dexie` ^4.0.0 - IndexedDB wrapper for local storage
|
|
28
|
-
|
|
29
21
|
## Quick Start
|
|
30
22
|
|
|
31
|
-
The SDK uses a
|
|
23
|
+
The SDK uses a factory pattern — each call to `createGossipSdk()` returns a new instance:
|
|
32
24
|
|
|
33
25
|
```typescript
|
|
34
|
-
import {
|
|
26
|
+
import { createGossipSdk } from '@massalabs/gossip-sdk';
|
|
35
27
|
|
|
36
|
-
|
|
37
|
-
const db = new GossipDatabase();
|
|
38
|
-
await db.open();
|
|
28
|
+
const sdk = createGossipSdk();
|
|
39
29
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
protocolBaseUrl: 'https://api.example.com',
|
|
43
|
-
});
|
|
30
|
+
// 1. Initialize (optional config)
|
|
31
|
+
await sdk.init();
|
|
44
32
|
|
|
45
33
|
// 2. Open session (login)
|
|
46
|
-
await
|
|
34
|
+
await sdk.openSession({
|
|
47
35
|
mnemonic: 'word1 word2 word3 ... word12',
|
|
48
|
-
// For existing session:
|
|
49
|
-
encryptedSession: savedBlob,
|
|
50
|
-
encryptionKey: savedKey,
|
|
51
|
-
// For persistence:
|
|
52
|
-
persistEncryptionKey: encryptionKey,
|
|
53
|
-
onPersist: async (blob, key) => {
|
|
54
|
-
await saveToStorage(blob, key);
|
|
55
|
-
},
|
|
56
36
|
});
|
|
57
37
|
|
|
58
38
|
// 3. Use the SDK
|
|
59
|
-
const contacts = await
|
|
60
|
-
await
|
|
61
|
-
await
|
|
39
|
+
const contacts = await sdk.contacts.list(sdk.userId);
|
|
40
|
+
await sdk.discussions.start(contact);
|
|
41
|
+
await sdk.messages.send(message);
|
|
62
42
|
|
|
63
43
|
// 4. Listen to events
|
|
64
|
-
|
|
65
|
-
console.log('New message:', msg
|
|
44
|
+
sdk.on(SdkEventType.MESSAGE_RECEIVED, msg => {
|
|
45
|
+
console.log('New message:', msg);
|
|
66
46
|
});
|
|
67
47
|
|
|
68
48
|
// 5. Logout
|
|
69
|
-
await
|
|
49
|
+
await sdk.closeSession();
|
|
70
50
|
```
|
|
71
51
|
|
|
72
52
|
## Lifecycle
|
|
73
53
|
|
|
74
54
|
### 1. Initialize
|
|
75
55
|
|
|
76
|
-
Call `init()` once at app startup
|
|
56
|
+
Call `init()` once at app startup. All options are optional:
|
|
77
57
|
|
|
78
58
|
```typescript
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
db: new GossipDatabase(),
|
|
59
|
+
// Uses GOSSIP_API_URL / VITE_GOSSIP_API_URL env var, or defaults to api.usegossip.com
|
|
60
|
+
await sdk.init();
|
|
82
61
|
|
|
83
|
-
|
|
62
|
+
// Or with explicit config
|
|
63
|
+
await sdk.init({
|
|
84
64
|
protocolBaseUrl: 'https://api.usegossip.com',
|
|
85
|
-
|
|
86
|
-
// Optional: Configuration overrides
|
|
87
65
|
config: {
|
|
88
66
|
polling: {
|
|
89
67
|
enabled: true,
|
|
@@ -99,23 +77,23 @@ Call `openSession()` to authenticate and create a cryptographic session:
|
|
|
99
77
|
|
|
100
78
|
```typescript
|
|
101
79
|
// New account (no existing session)
|
|
102
|
-
await
|
|
80
|
+
await sdk.openSession({
|
|
103
81
|
mnemonic: 'word1 word2 word3 ... word12',
|
|
104
82
|
});
|
|
105
83
|
|
|
106
84
|
// Restore existing session
|
|
107
|
-
await
|
|
85
|
+
await sdk.openSession({
|
|
108
86
|
mnemonic: 'word1 word2 word3 ... word12',
|
|
109
87
|
encryptedSession: savedBlob,
|
|
110
88
|
encryptionKey: savedKey,
|
|
111
89
|
});
|
|
112
90
|
|
|
113
91
|
// With persistence (saves session on changes)
|
|
114
|
-
await
|
|
92
|
+
await sdk.openSession({
|
|
115
93
|
mnemonic: 'word1 word2 word3 ... word12',
|
|
116
|
-
|
|
94
|
+
encryptionKey,
|
|
117
95
|
onPersist: async (blob, key) => {
|
|
118
|
-
await
|
|
96
|
+
await storage.save({ session: blob });
|
|
119
97
|
},
|
|
120
98
|
});
|
|
121
99
|
```
|
|
@@ -123,7 +101,7 @@ await gossipSdk.openSession({
|
|
|
123
101
|
### 3. Close Session (Logout)
|
|
124
102
|
|
|
125
103
|
```typescript
|
|
126
|
-
await
|
|
104
|
+
await sdk.closeSession();
|
|
127
105
|
```
|
|
128
106
|
|
|
129
107
|
## Service APIs
|
|
@@ -134,8 +112,8 @@ All services are available after `openSession()` is called.
|
|
|
134
112
|
|
|
135
113
|
```typescript
|
|
136
114
|
// Send a message
|
|
137
|
-
const result = await
|
|
138
|
-
ownerUserId:
|
|
115
|
+
const result = await sdk.messages.send({
|
|
116
|
+
ownerUserId: sdk.userId,
|
|
139
117
|
contactUserId: contactId,
|
|
140
118
|
content: 'Hello!',
|
|
141
119
|
type: MessageType.TEXT,
|
|
@@ -145,51 +123,48 @@ const result = await gossipSdk.messages.send({
|
|
|
145
123
|
});
|
|
146
124
|
|
|
147
125
|
// Fetch new messages from server
|
|
148
|
-
const fetchResult = await
|
|
149
|
-
|
|
150
|
-
// Resend failed messages
|
|
151
|
-
await gossipSdk.messages.resend(failedMessagesMap);
|
|
126
|
+
const fetchResult = await sdk.messages.fetch();
|
|
152
127
|
|
|
153
128
|
// Find message by seeker
|
|
154
|
-
const msg = await
|
|
129
|
+
const msg = await sdk.messages.findBySeeker(seeker, ownerUserId);
|
|
130
|
+
|
|
131
|
+
// Mark as read
|
|
132
|
+
await sdk.messages.markAsRead(messageId);
|
|
155
133
|
```
|
|
156
134
|
|
|
157
135
|
### Discussions
|
|
158
136
|
|
|
159
137
|
```typescript
|
|
160
138
|
// Start a new discussion
|
|
161
|
-
const
|
|
139
|
+
const result = await sdk.discussions.start(contact);
|
|
162
140
|
|
|
163
141
|
// Accept an incoming discussion request
|
|
164
|
-
await
|
|
142
|
+
await sdk.discussions.accept(discussion);
|
|
165
143
|
|
|
166
144
|
// Renew a broken session
|
|
167
|
-
await
|
|
145
|
+
await sdk.discussions.renew(contactUserId);
|
|
168
146
|
|
|
169
|
-
//
|
|
170
|
-
const
|
|
171
|
-
ownerUserId,
|
|
172
|
-
contactUserId
|
|
173
|
-
);
|
|
147
|
+
// Get session status for a contact
|
|
148
|
+
const status = sdk.discussions.getStatus(contactUserId);
|
|
174
149
|
|
|
175
150
|
// List all discussions
|
|
176
|
-
const discussions = await
|
|
151
|
+
const discussions = await sdk.discussions.list(ownerUserId);
|
|
177
152
|
|
|
178
153
|
// Get a specific discussion
|
|
179
|
-
const discussion = await
|
|
154
|
+
const discussion = await sdk.discussions.get(ownerUserId, contactUserId);
|
|
180
155
|
```
|
|
181
156
|
|
|
182
157
|
### Contacts
|
|
183
158
|
|
|
184
159
|
```typescript
|
|
185
160
|
// List all contacts
|
|
186
|
-
const contacts = await
|
|
161
|
+
const contacts = await sdk.contacts.list(ownerUserId);
|
|
187
162
|
|
|
188
163
|
// Get a specific contact
|
|
189
|
-
const contact = await
|
|
164
|
+
const contact = await sdk.contacts.get(ownerUserId, contactUserId);
|
|
190
165
|
|
|
191
166
|
// Add a new contact
|
|
192
|
-
const result = await
|
|
167
|
+
const result = await sdk.contacts.add(
|
|
193
168
|
ownerUserId,
|
|
194
169
|
contactUserId,
|
|
195
170
|
'Alice',
|
|
@@ -197,100 +172,54 @@ const result = await gossipSdk.contacts.add(
|
|
|
197
172
|
);
|
|
198
173
|
|
|
199
174
|
// Update contact name
|
|
200
|
-
await
|
|
175
|
+
await sdk.contacts.updateName(ownerUserId, contactUserId, 'Alice Smith');
|
|
201
176
|
|
|
202
177
|
// Delete contact and all associated data
|
|
203
|
-
await
|
|
178
|
+
await sdk.contacts.delete(ownerUserId, contactUserId);
|
|
204
179
|
```
|
|
205
180
|
|
|
206
181
|
### Announcements
|
|
207
182
|
|
|
208
183
|
```typescript
|
|
209
184
|
// Fetch and process announcements from server
|
|
210
|
-
const result = await
|
|
211
|
-
|
|
212
|
-
// Resend failed announcements
|
|
213
|
-
await gossipSdk.announcements.resend(failedDiscussions);
|
|
185
|
+
const result = await sdk.announcements.fetch();
|
|
214
186
|
```
|
|
215
187
|
|
|
216
|
-
### Auth (Available before session)
|
|
188
|
+
### Auth (Available after init, before session)
|
|
217
189
|
|
|
218
190
|
```typescript
|
|
219
|
-
//
|
|
220
|
-
|
|
221
|
-
username,
|
|
222
|
-
mnemonic,
|
|
223
|
-
encryptionKey
|
|
224
|
-
);
|
|
225
|
-
|
|
226
|
-
// Restore account from mnemonic
|
|
227
|
-
const result = await gossipSdk.auth.restoreAccount(
|
|
228
|
-
username,
|
|
229
|
-
mnemonic,
|
|
230
|
-
encryptionKey
|
|
231
|
-
);
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
### Refresh
|
|
235
|
-
|
|
236
|
-
```typescript
|
|
237
|
-
// Handle session refresh for active discussions
|
|
238
|
-
await gossipSdk.refresh.handleSessionRefresh(activeDiscussions);
|
|
191
|
+
// Publish public key so the user is discoverable
|
|
192
|
+
await sdk.auth.ensurePublicKeyPublished(publicKey, userId);
|
|
239
193
|
```
|
|
240
194
|
|
|
241
195
|
## Events
|
|
242
196
|
|
|
243
|
-
Subscribe to SDK events
|
|
197
|
+
Subscribe to SDK events using `SdkEventType`:
|
|
244
198
|
|
|
245
199
|
```typescript
|
|
246
|
-
|
|
247
|
-
gossipSdk.on('message', message => {
|
|
248
|
-
// New message received
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
gossipSdk.on('messageSent', message => {
|
|
252
|
-
// Message sent successfully
|
|
253
|
-
});
|
|
200
|
+
import { SdkEventType } from '@massalabs/gossip-sdk';
|
|
254
201
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
});
|
|
202
|
+
// Message events
|
|
203
|
+
sdk.on(SdkEventType.MESSAGE_RECEIVED, message => { ... });
|
|
204
|
+
sdk.on(SdkEventType.MESSAGE_SENT, message => { ... });
|
|
258
205
|
|
|
259
206
|
// Discussion events
|
|
260
|
-
|
|
261
|
-
// Incoming discussion request
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
gossipSdk.on('discussionStatusChanged', discussion => {
|
|
265
|
-
// Discussion status changed
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
// Session events
|
|
269
|
-
gossipSdk.on('sessionBroken', discussion => {
|
|
270
|
-
// Session broken (deprecated - use auto-renewal)
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
gossipSdk.on('sessionRenewed', discussion => {
|
|
274
|
-
// Session successfully renewed
|
|
275
|
-
});
|
|
207
|
+
sdk.on(SdkEventType.SESSION_REQUESTED, (discussion, contact) => { ... });
|
|
276
208
|
|
|
277
209
|
// Error handling
|
|
278
|
-
|
|
210
|
+
sdk.on(SdkEventType.ERROR, (error, context) => {
|
|
279
211
|
console.error(`Error in ${context}:`, error);
|
|
280
212
|
});
|
|
281
213
|
|
|
282
214
|
// Unsubscribe
|
|
283
|
-
|
|
215
|
+
sdk.off(SdkEventType.MESSAGE_RECEIVED, handler);
|
|
284
216
|
```
|
|
285
217
|
|
|
286
218
|
## Polling
|
|
287
219
|
|
|
288
|
-
The SDK can automatically poll for messages, announcements, and session refresh:
|
|
289
|
-
|
|
290
220
|
```typescript
|
|
291
221
|
// Enable via config
|
|
292
|
-
await
|
|
293
|
-
db,
|
|
222
|
+
await sdk.init({
|
|
294
223
|
config: {
|
|
295
224
|
polling: {
|
|
296
225
|
enabled: true,
|
|
@@ -302,76 +231,37 @@ await gossipSdk.init({
|
|
|
302
231
|
});
|
|
303
232
|
|
|
304
233
|
// Or control manually
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
console.log(
|
|
234
|
+
sdk.polling.start();
|
|
235
|
+
sdk.polling.stop();
|
|
236
|
+
console.log(sdk.polling.isRunning);
|
|
308
237
|
```
|
|
309
238
|
|
|
310
239
|
## Session Info
|
|
311
240
|
|
|
312
|
-
Access session information after `openSession()`:
|
|
313
|
-
|
|
314
241
|
```typescript
|
|
315
|
-
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
// User ID (raw bytes)
|
|
319
|
-
const userIdBytes = gossipSdk.userIdBytes;
|
|
242
|
+
const userId = sdk.userId; // Encoded string
|
|
243
|
+
const userIdBytes = sdk.userIdBytes; // Raw bytes
|
|
244
|
+
const publicKeys = sdk.publicKeys;
|
|
320
245
|
|
|
321
|
-
//
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
// Check session state
|
|
325
|
-
console.log(gossipSdk.isInitialized); // true after init()
|
|
326
|
-
console.log(gossipSdk.isSessionOpen); // true after openSession()
|
|
246
|
+
console.log(sdk.isInitialized); // true after init()
|
|
247
|
+
console.log(sdk.isSessionOpen); // true after openSession()
|
|
327
248
|
|
|
328
249
|
// Get encrypted session for manual persistence
|
|
329
|
-
const blob =
|
|
250
|
+
const blob = sdk.getEncryptedSession();
|
|
330
251
|
```
|
|
331
252
|
|
|
332
|
-
##
|
|
253
|
+
## State Update
|
|
333
254
|
|
|
334
|
-
|
|
255
|
+
Trigger a full state refresh for all discussions (session renewal, queued messages, keep-alives):
|
|
335
256
|
|
|
336
257
|
```typescript
|
|
337
|
-
await
|
|
338
|
-
db,
|
|
339
|
-
config: {
|
|
340
|
-
// Network settings
|
|
341
|
-
protocol: {
|
|
342
|
-
baseUrl: 'https://api.usegossip.com', // API endpoint
|
|
343
|
-
timeout: 10000, // Request timeout (ms)
|
|
344
|
-
retryAttempts: 3, // Retry count
|
|
345
|
-
},
|
|
346
|
-
|
|
347
|
-
// Polling settings
|
|
348
|
-
polling: {
|
|
349
|
-
enabled: false, // Auto-start polling
|
|
350
|
-
messagesIntervalMs: 5000, // Message fetch interval
|
|
351
|
-
announcementsIntervalMs: 10000, // Announcement fetch interval
|
|
352
|
-
sessionRefreshIntervalMs: 30000, // Session refresh interval
|
|
353
|
-
},
|
|
354
|
-
|
|
355
|
-
// Message settings
|
|
356
|
-
messages: {
|
|
357
|
-
fetchDelayMs: 100, // Delay between fetch iterations
|
|
358
|
-
maxFetchIterations: 30, // Max iterations per fetch call
|
|
359
|
-
deduplicationWindowMs: 30000, // Duplicate detection window
|
|
360
|
-
},
|
|
361
|
-
|
|
362
|
-
// Announcement settings
|
|
363
|
-
announcements: {
|
|
364
|
-
fetchLimit: 500, // Max announcements per request
|
|
365
|
-
brokenThresholdMs: 3600000, // Time before marking broken (1 hour)
|
|
366
|
-
},
|
|
367
|
-
},
|
|
368
|
-
});
|
|
258
|
+
await sdk.updateState();
|
|
369
259
|
```
|
|
370
260
|
|
|
371
261
|
## Utilities
|
|
372
262
|
|
|
373
263
|
```typescript
|
|
374
|
-
const utils =
|
|
264
|
+
const utils = sdk.utils;
|
|
375
265
|
|
|
376
266
|
// Validate user ID format
|
|
377
267
|
const result = utils.validateUserId(userId);
|
|
@@ -385,27 +275,49 @@ const encoded = utils.encodeUserId(rawBytes);
|
|
|
385
275
|
const decoded = utils.decodeUserId(encodedString);
|
|
386
276
|
```
|
|
387
277
|
|
|
278
|
+
## Configuration
|
|
279
|
+
|
|
280
|
+
Full configuration options with defaults:
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
await sdk.init({
|
|
284
|
+
config: {
|
|
285
|
+
protocol: {
|
|
286
|
+
baseUrl: 'https://api.usegossip.com',
|
|
287
|
+
timeout: 10000,
|
|
288
|
+
retryAttempts: 3,
|
|
289
|
+
},
|
|
290
|
+
polling: {
|
|
291
|
+
enabled: false,
|
|
292
|
+
messagesIntervalMs: 5000,
|
|
293
|
+
announcementsIntervalMs: 10000,
|
|
294
|
+
sessionRefreshIntervalMs: 30000,
|
|
295
|
+
},
|
|
296
|
+
messages: {
|
|
297
|
+
fetchDelayMs: 100,
|
|
298
|
+
maxFetchIterations: 30,
|
|
299
|
+
deduplicationWindowMs: 30000,
|
|
300
|
+
},
|
|
301
|
+
announcements: {
|
|
302
|
+
fetchLimit: 500,
|
|
303
|
+
brokenThresholdMs: 3600000,
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
});
|
|
307
|
+
```
|
|
308
|
+
|
|
388
309
|
## Session Persistence
|
|
389
310
|
|
|
390
311
|
For restoring sessions across app restarts:
|
|
391
312
|
|
|
392
313
|
```typescript
|
|
393
|
-
|
|
394
|
-
await gossipSdk.openSession({
|
|
314
|
+
await sdk.openSession({
|
|
395
315
|
mnemonic,
|
|
396
|
-
|
|
316
|
+
encryptionKey,
|
|
397
317
|
onPersist: async (blob, key) => {
|
|
398
|
-
|
|
399
|
-
await db.userProfile.update(userId, { session: blob });
|
|
318
|
+
await storage.save({ session: blob });
|
|
400
319
|
},
|
|
401
320
|
});
|
|
402
|
-
|
|
403
|
-
// Option 2: Configure persistence after account creation
|
|
404
|
-
await gossipSdk.openSession({ mnemonic });
|
|
405
|
-
// ... create account, get encryption key ...
|
|
406
|
-
gossipSdk.configurePersistence(encryptionKey, async (blob, key) => {
|
|
407
|
-
await db.userProfile.update(userId, { session: blob });
|
|
408
|
-
});
|
|
409
321
|
```
|
|
410
322
|
|
|
411
323
|
## Auto-Renewal Behavior
|
|
@@ -417,24 +329,20 @@ The SDK automatically handles session recovery:
|
|
|
417
329
|
3. **Auto-Accept** - When peer sends announcement, SDK auto-accepts for existing contacts
|
|
418
330
|
4. **Message Processing** - After session becomes active, queued messages are sent automatically
|
|
419
331
|
|
|
420
|
-
See [STATUS-REFERENCE.md](./docs/STATUS-REFERENCE.md) for detailed status documentation.
|
|
421
|
-
|
|
422
332
|
## Types
|
|
423
333
|
|
|
424
|
-
Import types from the SDK:
|
|
425
|
-
|
|
426
334
|
```typescript
|
|
427
335
|
import type {
|
|
428
336
|
UserProfile,
|
|
429
337
|
Contact,
|
|
430
338
|
Discussion,
|
|
431
339
|
Message,
|
|
432
|
-
DiscussionStatus,
|
|
433
|
-
DiscussionDirection,
|
|
434
340
|
MessageStatus,
|
|
435
341
|
MessageDirection,
|
|
436
342
|
MessageType,
|
|
437
|
-
} from 'gossip-sdk';
|
|
343
|
+
} from '@massalabs/gossip-sdk';
|
|
344
|
+
|
|
345
|
+
import { SessionStatus, SdkEventType } from '@massalabs/gossip-sdk';
|
|
438
346
|
```
|
|
439
347
|
|
|
440
348
|
## Testing
|
|
@@ -442,7 +350,6 @@ import type {
|
|
|
442
350
|
```bash
|
|
443
351
|
npm test # Watch mode
|
|
444
352
|
npm run test:run # Single run
|
|
445
|
-
npm run test:coverage # With coverage report
|
|
446
353
|
```
|
|
447
354
|
|
|
448
355
|
Tests use `fake-indexeddb` to simulate IndexedDB in Node.js environment.
|
|
@@ -452,7 +359,7 @@ Tests use `fake-indexeddb` to simulate IndexedDB in Node.js environment.
|
|
|
452
359
|
```
|
|
453
360
|
gossip-sdk/
|
|
454
361
|
├── src/
|
|
455
|
-
│ ├── gossipSdk.ts #
|
|
362
|
+
│ ├── gossipSdk.ts # SDK class & factory
|
|
456
363
|
│ ├── db.ts # Database (Dexie) implementation
|
|
457
364
|
│ ├── contacts.ts # Contact operations
|
|
458
365
|
│ ├── api/
|
|
@@ -469,14 +376,10 @@ gossip-sdk/
|
|
|
469
376
|
│ │ ├── discussion.ts # Discussion service
|
|
470
377
|
│ │ ├── announcement.ts # Announcement service
|
|
471
378
|
│ │ └── refresh.ts # Session refresh service
|
|
472
|
-
│ ├── types/
|
|
473
|
-
│ │ └── events.ts # Event type definitions
|
|
379
|
+
│ ├── types/ # Type definitions
|
|
474
380
|
│ ├── utils/ # Utility modules
|
|
475
381
|
│ └── wasm/ # WASM module wrappers
|
|
476
|
-
|
|
477
|
-
├── docs/
|
|
478
|
-
│ └── STATUS-REFERENCE.md # Status documentation
|
|
479
|
-
└── README.md
|
|
382
|
+
└── test/ # Test files
|
|
480
383
|
```
|
|
481
384
|
|
|
482
385
|
## License
|
package/dist/db.d.ts
CHANGED
|
@@ -166,17 +166,6 @@ export declare class GossipDatabase extends Dexie {
|
|
|
166
166
|
getActiveSeekers(): Promise<Uint8Array[]>;
|
|
167
167
|
}
|
|
168
168
|
/**
|
|
169
|
-
* Get the database instance.
|
|
170
|
-
* Creates a default instance if none was set via setDb().
|
|
169
|
+
* Get the database instance. Creates a default instance on first call.
|
|
171
170
|
*/
|
|
172
|
-
export declare function
|
|
173
|
-
/**
|
|
174
|
-
* Set the database instance.
|
|
175
|
-
* Call this before using any SDK functions if you need a custom db instance.
|
|
176
|
-
*/
|
|
177
|
-
export declare function setDb(database: GossipDatabase): void;
|
|
178
|
-
/**
|
|
179
|
-
* Get the database instance.
|
|
180
|
-
* Creates a default instance if none was set via setDb().
|
|
181
|
-
*/
|
|
182
|
-
export declare const db: GossipDatabase;
|
|
171
|
+
export declare function gossipDb(): GossipDatabase;
|
package/dist/db.js
CHANGED
|
@@ -245,55 +245,14 @@ export class GossipDatabase extends Dexie {
|
|
|
245
245
|
return activeSeekers.map(item => item.seeker);
|
|
246
246
|
}
|
|
247
247
|
}
|
|
248
|
-
// Database instance -
|
|
248
|
+
// Database instance - lazily initialized singleton
|
|
249
249
|
let _db = null;
|
|
250
|
-
let _warnedGlobalDbAccess = false;
|
|
251
|
-
// Store a reference to the Proxy to detect it
|
|
252
|
-
let _proxyDb = null;
|
|
253
250
|
/**
|
|
254
|
-
* Get the database instance.
|
|
255
|
-
* Creates a default instance if none was set via setDb().
|
|
251
|
+
* Get the database instance. Creates a default instance on first call.
|
|
256
252
|
*/
|
|
257
|
-
export function
|
|
258
|
-
|
|
259
|
-
if (!_db || _db === _proxyDb || !(_db instanceof GossipDatabase)) {
|
|
253
|
+
export function gossipDb() {
|
|
254
|
+
if (!_db || !(_db instanceof GossipDatabase)) {
|
|
260
255
|
_db = new GossipDatabase();
|
|
261
256
|
}
|
|
262
257
|
return _db;
|
|
263
258
|
}
|
|
264
|
-
/**
|
|
265
|
-
* Set the database instance.
|
|
266
|
-
* Call this before using any SDK functions if you need a custom db instance.
|
|
267
|
-
*/
|
|
268
|
-
export function setDb(database) {
|
|
269
|
-
// Prevent setting the Proxy itself to avoid infinite recursion
|
|
270
|
-
// The Proxy is not an instance of GossipDatabase, so we can detect it that way
|
|
271
|
-
if (!(database instanceof GossipDatabase) || database === _proxyDb) {
|
|
272
|
-
// If Proxy is passed, ensure _db exists by calling getDb()
|
|
273
|
-
// This will reuse existing _db if it was already created (e.g., by db.open())
|
|
274
|
-
// or create a new one if needed. This ensures we always use the same instance.
|
|
275
|
-
getDb();
|
|
276
|
-
// Don't overwrite _db - just ensure it exists and is consistent
|
|
277
|
-
}
|
|
278
|
-
else {
|
|
279
|
-
_db = database;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
/**
|
|
283
|
-
* Get the database instance.
|
|
284
|
-
* Creates a default instance if none was set via setDb().
|
|
285
|
-
*/
|
|
286
|
-
export const db = (_proxyDb = new Proxy({}, {
|
|
287
|
-
get(_target, prop) {
|
|
288
|
-
if (!_warnedGlobalDbAccess) {
|
|
289
|
-
_warnedGlobalDbAccess = true;
|
|
290
|
-
console.warn('[GossipSdk] Global db access is deprecated. Use createGossipSdk() or setDb().');
|
|
291
|
-
}
|
|
292
|
-
const target = getDb();
|
|
293
|
-
const value = Reflect.get(target, prop);
|
|
294
|
-
if (typeof value === 'function') {
|
|
295
|
-
return value.bind(target);
|
|
296
|
-
}
|
|
297
|
-
return value;
|
|
298
|
-
},
|
|
299
|
-
}));
|