@massalabs/gossip-sdk 0.0.2-dev.20260211110128 → 0.0.2-dev.20260211172752
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 +4 -14
- package/dist/config/protocol.d.ts +1 -1
- package/dist/config/protocol.js +1 -1
- package/dist/config/sdk.d.ts +4 -0
- package/dist/config/sdk.js +3 -1
- package/dist/contacts.d.ts +1 -1
- package/dist/contacts.js +1 -1
- package/dist/core/SdkEventEmitter.d.ts +21 -12
- package/dist/core/SdkEventEmitter.js +22 -8
- package/dist/core/SdkPolling.d.ts +3 -3
- package/dist/core/SdkPolling.js +16 -7
- package/dist/db.d.ts +16 -24
- package/dist/db.js +25 -37
- package/dist/gossipSdk.d.ts +35 -74
- package/dist/gossipSdk.js +100 -264
- package/dist/index.d.ts +4 -2
- package/dist/index.js +2 -1
- package/dist/services/announcement.d.ts +9 -9
- package/dist/services/announcement.js +133 -156
- package/dist/services/discussion.d.ts +31 -23
- package/dist/services/discussion.js +153 -172
- package/dist/services/message.d.ts +23 -12
- package/dist/services/message.js +392 -429
- package/dist/services/refresh.d.ts +24 -16
- package/dist/services/refresh.js +134 -141
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/utils/contacts.js +13 -10
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +1 -1
- package/dist/wasm/session.d.ts +1 -2
- package/dist/wasm/session.js +8 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,9 +47,8 @@ await gossipSdk.openSession({
|
|
|
47
47
|
mnemonic: 'word1 word2 word3 ... word12',
|
|
48
48
|
// For existing session:
|
|
49
49
|
encryptedSession: savedBlob,
|
|
50
|
-
encryptionKey
|
|
50
|
+
encryptionKey,
|
|
51
51
|
// For persistence:
|
|
52
|
-
persistEncryptionKey: encryptionKey,
|
|
53
52
|
onPersist: async (blob, key) => {
|
|
54
53
|
await saveToStorage(blob, key);
|
|
55
54
|
},
|
|
@@ -113,7 +112,7 @@ await gossipSdk.openSession({
|
|
|
113
112
|
// With persistence (saves session on changes)
|
|
114
113
|
await gossipSdk.openSession({
|
|
115
114
|
mnemonic: 'word1 word2 word3 ... word12',
|
|
116
|
-
|
|
115
|
+
encryptionKey,
|
|
117
116
|
onPersist: async (blob, key) => {
|
|
118
117
|
await db.userProfile.update(userId, { session: blob });
|
|
119
118
|
},
|
|
@@ -387,25 +386,16 @@ const decoded = utils.decodeUserId(encodedString);
|
|
|
387
386
|
|
|
388
387
|
## Session Persistence
|
|
389
388
|
|
|
390
|
-
For restoring sessions across app restarts:
|
|
389
|
+
For restoring sessions across app restarts, pass `encryptionKey` and `onPersist` when opening the session:
|
|
391
390
|
|
|
392
391
|
```typescript
|
|
393
|
-
// Option 1: Provide persistence config in openSession
|
|
394
392
|
await gossipSdk.openSession({
|
|
395
393
|
mnemonic,
|
|
396
|
-
|
|
394
|
+
encryptionKey,
|
|
397
395
|
onPersist: async (blob, key) => {
|
|
398
|
-
// Save blob to your storage
|
|
399
396
|
await db.userProfile.update(userId, { session: blob });
|
|
400
397
|
},
|
|
401
398
|
});
|
|
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
399
|
```
|
|
410
400
|
|
|
411
401
|
## Auto-Renewal Behavior
|
|
@@ -23,7 +23,7 @@ export declare const defaultMessageProtocol: MessageProtocolType;
|
|
|
23
23
|
*
|
|
24
24
|
* @example
|
|
25
25
|
* ```typescript
|
|
26
|
-
* import { setProtocolBaseUrl } from 'gossip-sdk';
|
|
26
|
+
* import { setProtocolBaseUrl } from '@massalabs/gossip-sdk';
|
|
27
27
|
*
|
|
28
28
|
* // Set custom API endpoint
|
|
29
29
|
* setProtocolBaseUrl('https://my-server.com/api');
|
package/dist/config/protocol.js
CHANGED
|
@@ -66,7 +66,7 @@ export const defaultMessageProtocol = MessageProtocolType.REST;
|
|
|
66
66
|
*
|
|
67
67
|
* @example
|
|
68
68
|
* ```typescript
|
|
69
|
-
* import { setProtocolBaseUrl } from 'gossip-sdk';
|
|
69
|
+
* import { setProtocolBaseUrl } from '@massalabs/gossip-sdk';
|
|
70
70
|
*
|
|
71
71
|
* // Set custom API endpoint
|
|
72
72
|
* setProtocolBaseUrl('https://my-server.com/api');
|
package/dist/config/sdk.d.ts
CHANGED
|
@@ -43,6 +43,8 @@ export interface MessagesConfig {
|
|
|
43
43
|
* resulting in message being re-sent on restart.
|
|
44
44
|
*/
|
|
45
45
|
deduplicationWindowMs: number;
|
|
46
|
+
/** Delay before retrying a failed message send in ms (default: 5000 = 5 seconds) */
|
|
47
|
+
retryDelayMs: number;
|
|
46
48
|
}
|
|
47
49
|
/**
|
|
48
50
|
* Announcement configuration
|
|
@@ -52,6 +54,8 @@ export interface AnnouncementsConfig {
|
|
|
52
54
|
fetchLimit: number;
|
|
53
55
|
/** Time before marking failed announcements as broken in ms (default: 3600000 = 1 hour) */
|
|
54
56
|
brokenThresholdMs: number;
|
|
57
|
+
/** Delay before retrying a failed announcement send in ms (default: 15000 = 15 seconds) */
|
|
58
|
+
retryDelayMs: number;
|
|
55
59
|
}
|
|
56
60
|
/**
|
|
57
61
|
* Complete SDK configuration
|
package/dist/config/sdk.js
CHANGED
|
@@ -16,16 +16,18 @@ export const defaultSdkConfig = {
|
|
|
16
16
|
enabled: false,
|
|
17
17
|
messagesIntervalMs: 5000,
|
|
18
18
|
announcementsIntervalMs: 10000,
|
|
19
|
-
sessionRefreshIntervalMs: 30000,
|
|
19
|
+
sessionRefreshIntervalMs: 10000, //30000,
|
|
20
20
|
},
|
|
21
21
|
messages: {
|
|
22
22
|
fetchDelayMs: 100,
|
|
23
23
|
maxFetchIterations: 30,
|
|
24
24
|
deduplicationWindowMs: 30000, // 30 seconds
|
|
25
|
+
retryDelayMs: 5000, // 5 seconds
|
|
25
26
|
},
|
|
26
27
|
announcements: {
|
|
27
28
|
fetchLimit: 500,
|
|
28
29
|
brokenThresholdMs: 60 * 60 * 1000, // 1 hour
|
|
30
|
+
retryDelayMs: 15000, // 15 seconds
|
|
29
31
|
},
|
|
30
32
|
};
|
|
31
33
|
/**
|
package/dist/contacts.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @example
|
|
7
7
|
* ```typescript
|
|
8
|
-
* import { getContacts, addContact, deleteContact } from 'gossip-sdk';
|
|
8
|
+
* import { getContacts, addContact, deleteContact } from '@massalabs/gossip-sdk';
|
|
9
9
|
*
|
|
10
10
|
* // Get all contacts
|
|
11
11
|
* const contacts = await getContacts(userId);
|
package/dist/contacts.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @example
|
|
7
7
|
* ```typescript
|
|
8
|
-
* import { getContacts, addContact, deleteContact } from 'gossip-sdk';
|
|
8
|
+
* import { getContacts, addContact, deleteContact } from '@massalabs/gossip-sdk';
|
|
9
9
|
*
|
|
10
10
|
* // Get all contacts
|
|
11
11
|
* const contacts = await getContacts(userId);
|
|
@@ -4,31 +4,40 @@
|
|
|
4
4
|
* Type-safe event emitter for SDK events.
|
|
5
5
|
*/
|
|
6
6
|
import type { Message, Discussion, Contact } from '../db';
|
|
7
|
-
export
|
|
7
|
+
export declare enum SdkEventType {
|
|
8
|
+
MESSAGE_RECEIVED = "messageReceived",
|
|
9
|
+
MESSAGE_SENT = "messageSent",
|
|
10
|
+
MESSAGE_FAILED = "messageFailed",
|
|
11
|
+
SESSION_REQUESTED = "sessionRequested",
|
|
12
|
+
SESSION_CREATED = "sessionCreated",
|
|
13
|
+
SESSION_RENEWED = "sessionRenewed",
|
|
14
|
+
SESSION_ACCEPTED = "sessionAccepted",
|
|
15
|
+
ERROR = "error"
|
|
16
|
+
}
|
|
8
17
|
export interface SdkEventHandlers {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
[SdkEventType.MESSAGE_RECEIVED]: (message: Message) => void;
|
|
19
|
+
[SdkEventType.MESSAGE_SENT]: (message: Message) => void;
|
|
20
|
+
[SdkEventType.MESSAGE_FAILED]: (message: Message, error: Error) => void;
|
|
21
|
+
[SdkEventType.SESSION_REQUESTED]: (discussion: Discussion, contact: Contact) => void;
|
|
22
|
+
[SdkEventType.SESSION_CREATED]: (discussion: Discussion) => void;
|
|
23
|
+
[SdkEventType.SESSION_RENEWED]: (discussion: Discussion) => void;
|
|
24
|
+
[SdkEventType.SESSION_ACCEPTED]: (contactUserId: string) => void;
|
|
25
|
+
[SdkEventType.ERROR]: (error: Error, context: string) => void;
|
|
17
26
|
}
|
|
18
27
|
export declare class SdkEventEmitter {
|
|
19
28
|
private handlers;
|
|
20
29
|
/**
|
|
21
30
|
* Register an event handler
|
|
22
31
|
*/
|
|
23
|
-
on<K extends
|
|
32
|
+
on<K extends keyof SdkEventHandlers>(event: K, handler: SdkEventHandlers[K]): void;
|
|
24
33
|
/**
|
|
25
34
|
* Remove an event handler
|
|
26
35
|
*/
|
|
27
|
-
off<K extends
|
|
36
|
+
off<K extends keyof SdkEventHandlers>(event: K, handler: SdkEventHandlers[K]): void;
|
|
28
37
|
/**
|
|
29
38
|
* Emit an event to all registered handlers
|
|
30
39
|
*/
|
|
31
|
-
emit<K extends
|
|
40
|
+
emit<K extends keyof SdkEventHandlers>(event: K, ...args: Parameters<SdkEventHandlers[K]>): void;
|
|
32
41
|
/**
|
|
33
42
|
* Remove all handlers for all events
|
|
34
43
|
*/
|
|
@@ -4,6 +4,20 @@
|
|
|
4
4
|
* Type-safe event emitter for SDK events.
|
|
5
5
|
*/
|
|
6
6
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
7
|
+
// Event Types
|
|
8
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
9
|
+
export var SdkEventType;
|
|
10
|
+
(function (SdkEventType) {
|
|
11
|
+
SdkEventType["MESSAGE_RECEIVED"] = "messageReceived";
|
|
12
|
+
SdkEventType["MESSAGE_SENT"] = "messageSent";
|
|
13
|
+
SdkEventType["MESSAGE_FAILED"] = "messageFailed";
|
|
14
|
+
SdkEventType["SESSION_REQUESTED"] = "sessionRequested";
|
|
15
|
+
SdkEventType["SESSION_CREATED"] = "sessionCreated";
|
|
16
|
+
SdkEventType["SESSION_RENEWED"] = "sessionRenewed";
|
|
17
|
+
SdkEventType["SESSION_ACCEPTED"] = "sessionAccepted";
|
|
18
|
+
SdkEventType["ERROR"] = "error";
|
|
19
|
+
})(SdkEventType || (SdkEventType = {}));
|
|
20
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
7
21
|
// Event Emitter Class
|
|
8
22
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
9
23
|
export class SdkEventEmitter {
|
|
@@ -13,14 +27,14 @@ export class SdkEventEmitter {
|
|
|
13
27
|
configurable: true,
|
|
14
28
|
writable: true,
|
|
15
29
|
value: {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
30
|
+
[SdkEventType.MESSAGE_RECEIVED]: new Set(),
|
|
31
|
+
[SdkEventType.MESSAGE_SENT]: new Set(),
|
|
32
|
+
[SdkEventType.MESSAGE_FAILED]: new Set(),
|
|
33
|
+
[SdkEventType.SESSION_REQUESTED]: new Set(),
|
|
34
|
+
[SdkEventType.SESSION_CREATED]: new Set(),
|
|
35
|
+
[SdkEventType.SESSION_RENEWED]: new Set(),
|
|
36
|
+
[SdkEventType.SESSION_ACCEPTED]: new Set(),
|
|
37
|
+
[SdkEventType.ERROR]: new Set(),
|
|
24
38
|
}
|
|
25
39
|
});
|
|
26
40
|
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { SdkConfig } from '../config/sdk';
|
|
7
7
|
import type { Discussion } from '../db';
|
|
8
|
+
import { SdkEventEmitter } from './SdkEventEmitter';
|
|
8
9
|
export interface PollingCallbacks {
|
|
9
10
|
/** Fetch messages from protocol */
|
|
10
11
|
fetchMessages: () => Promise<void>;
|
|
@@ -14,16 +15,15 @@ export interface PollingCallbacks {
|
|
|
14
15
|
handleSessionRefresh: (discussions: Discussion[]) => Promise<void>;
|
|
15
16
|
/** Get active discussions for session refresh */
|
|
16
17
|
getActiveDiscussions: () => Promise<Discussion[]>;
|
|
17
|
-
/** Called when a polling error occurs */
|
|
18
|
-
onError: (error: Error, context: string) => void;
|
|
19
18
|
}
|
|
20
19
|
export declare class SdkPolling {
|
|
21
20
|
private timers;
|
|
22
21
|
private callbacks;
|
|
22
|
+
private eventEmitter;
|
|
23
23
|
/**
|
|
24
24
|
* Start polling with the given configuration and callbacks.
|
|
25
25
|
*/
|
|
26
|
-
start(config: SdkConfig, callbacks: PollingCallbacks): void;
|
|
26
|
+
start(config: SdkConfig, callbacks: PollingCallbacks, eventEmitter: SdkEventEmitter): void;
|
|
27
27
|
/**
|
|
28
28
|
* Stop all polling timers.
|
|
29
29
|
*/
|
package/dist/core/SdkPolling.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Manages polling timers for messages, announcements, and session refresh.
|
|
5
5
|
*/
|
|
6
|
+
import { SdkEventType } from './SdkEventEmitter';
|
|
6
7
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
7
8
|
// Polling Manager Class
|
|
8
9
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -24,14 +25,21 @@ export class SdkPolling {
|
|
|
24
25
|
writable: true,
|
|
25
26
|
value: null
|
|
26
27
|
});
|
|
28
|
+
Object.defineProperty(this, "eventEmitter", {
|
|
29
|
+
enumerable: true,
|
|
30
|
+
configurable: true,
|
|
31
|
+
writable: true,
|
|
32
|
+
value: null
|
|
33
|
+
});
|
|
27
34
|
}
|
|
28
35
|
/**
|
|
29
36
|
* Start polling with the given configuration and callbacks.
|
|
30
37
|
*/
|
|
31
|
-
start(config, callbacks) {
|
|
38
|
+
start(config, callbacks, eventEmitter) {
|
|
32
39
|
// Stop any existing timers first
|
|
33
40
|
this.stop();
|
|
34
41
|
this.callbacks = callbacks;
|
|
42
|
+
this.eventEmitter = eventEmitter;
|
|
35
43
|
console.log('[SdkPolling] Starting polling', {
|
|
36
44
|
messagesIntervalMs: config.polling.messagesIntervalMs,
|
|
37
45
|
announcementsIntervalMs: config.polling.announcementsIntervalMs,
|
|
@@ -43,8 +51,8 @@ export class SdkPolling {
|
|
|
43
51
|
await this.callbacks?.fetchMessages();
|
|
44
52
|
}
|
|
45
53
|
catch (error) {
|
|
46
|
-
|
|
47
|
-
this.
|
|
54
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
55
|
+
this.eventEmitter?.emit(SdkEventType.ERROR, err, 'message_polling');
|
|
48
56
|
}
|
|
49
57
|
}, config.polling.messagesIntervalMs);
|
|
50
58
|
// Start announcement polling
|
|
@@ -53,8 +61,8 @@ export class SdkPolling {
|
|
|
53
61
|
await this.callbacks?.fetchAnnouncements();
|
|
54
62
|
}
|
|
55
63
|
catch (error) {
|
|
56
|
-
|
|
57
|
-
this.
|
|
64
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
65
|
+
this.eventEmitter?.emit(SdkEventType.ERROR, err, 'announcement_polling');
|
|
58
66
|
}
|
|
59
67
|
}, config.polling.announcementsIntervalMs);
|
|
60
68
|
// Start session refresh polling
|
|
@@ -66,8 +74,8 @@ export class SdkPolling {
|
|
|
66
74
|
}
|
|
67
75
|
}
|
|
68
76
|
catch (error) {
|
|
69
|
-
|
|
70
|
-
this.
|
|
77
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
78
|
+
this.eventEmitter?.emit(SdkEventType.ERROR, err, 'session_update');
|
|
71
79
|
}
|
|
72
80
|
}, config.polling.sessionRefreshIntervalMs);
|
|
73
81
|
}
|
|
@@ -88,6 +96,7 @@ export class SdkPolling {
|
|
|
88
96
|
this.timers.sessionRefresh = null;
|
|
89
97
|
}
|
|
90
98
|
this.callbacks = null;
|
|
99
|
+
this.eventEmitter = null;
|
|
91
100
|
}
|
|
92
101
|
/**
|
|
93
102
|
* Check if polling is currently running.
|
package/dist/db.d.ts
CHANGED
|
@@ -23,6 +23,8 @@ export interface Message {
|
|
|
23
23
|
contactUserId: string;
|
|
24
24
|
content: string;
|
|
25
25
|
serializedContent?: Uint8Array;
|
|
26
|
+
encryptedMessage?: Uint8Array;
|
|
27
|
+
whenToSend?: Date;
|
|
26
28
|
type: MessageType;
|
|
27
29
|
direction: MessageDirection;
|
|
28
30
|
status: MessageStatus;
|
|
@@ -37,7 +39,6 @@ export interface Message {
|
|
|
37
39
|
originalContent?: string;
|
|
38
40
|
originalSeeker: Uint8Array;
|
|
39
41
|
};
|
|
40
|
-
encryptedMessage?: Uint8Array;
|
|
41
42
|
}
|
|
42
43
|
export interface UserProfile {
|
|
43
44
|
userId: string;
|
|
@@ -65,13 +66,9 @@ export interface UserProfile {
|
|
|
65
66
|
lastPublicKeyPush?: Date;
|
|
66
67
|
lastBulletinCounter?: string;
|
|
67
68
|
}
|
|
68
|
-
export declare enum
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
CLOSED = "closed",// closed by the user
|
|
72
|
-
BROKEN = "broken",// The session is killed. Need to be reinitiated
|
|
73
|
-
SEND_FAILED = "sendFailed",// The discussion was initiated by the session manager but could not be broadcasted on network
|
|
74
|
-
RECONNECTING = "reconnecting"
|
|
69
|
+
export declare enum DiscussionDirection {
|
|
70
|
+
RECEIVED = "received",
|
|
71
|
+
INITIATED = "initiated"
|
|
75
72
|
}
|
|
76
73
|
export declare enum MessageDirection {
|
|
77
74
|
INCOMING = "incoming",
|
|
@@ -79,35 +76,35 @@ export declare enum MessageDirection {
|
|
|
79
76
|
}
|
|
80
77
|
export declare enum MessageStatus {
|
|
81
78
|
WAITING_SESSION = "waiting_session",// Waiting for active session with peer
|
|
82
|
-
|
|
79
|
+
READY = "ready",
|
|
83
80
|
SENT = "sent",
|
|
84
81
|
DELIVERED = "delivered",
|
|
85
|
-
READ = "read"
|
|
86
|
-
FAILED = "failed"
|
|
87
|
-
}
|
|
88
|
-
export declare enum DiscussionDirection {
|
|
89
|
-
INITIATED = "initiated",
|
|
90
|
-
RECEIVED = "received"
|
|
82
|
+
READ = "read"
|
|
91
83
|
}
|
|
92
84
|
export declare enum MessageType {
|
|
93
85
|
TEXT = "text",
|
|
86
|
+
ANNOUNCEMENT = "announcement",
|
|
94
87
|
KEEP_ALIVE = "keep_alive",
|
|
95
88
|
IMAGE = "image",
|
|
96
89
|
FILE = "file",
|
|
97
90
|
AUDIO = "audio",
|
|
98
91
|
VIDEO = "video"
|
|
99
92
|
}
|
|
93
|
+
export interface readyAnnouncement {
|
|
94
|
+
announcement_bytes: Uint8Array;
|
|
95
|
+
when_to_send: Date;
|
|
96
|
+
}
|
|
97
|
+
export type SendAnnouncement = null | readyAnnouncement;
|
|
100
98
|
export interface Discussion {
|
|
101
99
|
id?: number;
|
|
102
100
|
ownerUserId: string;
|
|
103
101
|
contactUserId: string;
|
|
102
|
+
weAccepted: boolean;
|
|
103
|
+
sendAnnouncement: SendAnnouncement;
|
|
104
104
|
direction: DiscussionDirection;
|
|
105
|
-
status: DiscussionStatus;
|
|
106
|
-
nextSeeker?: Uint8Array;
|
|
107
|
-
initiationAnnouncement?: Uint8Array;
|
|
108
|
-
announcementMessage?: string;
|
|
109
105
|
lastSyncTimestamp?: Date;
|
|
110
106
|
customName?: string;
|
|
107
|
+
lastAnnouncementMessage?: string;
|
|
111
108
|
lastMessageId?: number;
|
|
112
109
|
lastMessageContent?: string;
|
|
113
110
|
lastMessageTimestamp?: Date;
|
|
@@ -147,11 +144,6 @@ export declare class GossipDatabase extends Dexie {
|
|
|
147
144
|
getDiscussionsByOwner(ownerUserId: string): Promise<Discussion[]>;
|
|
148
145
|
getUnreadCountByOwner(ownerUserId: string): Promise<number>;
|
|
149
146
|
getDiscussionByOwnerAndContact(ownerUserId: string, contactUserId: string): Promise<Discussion | undefined>;
|
|
150
|
-
/**
|
|
151
|
-
* Get all active discussions with their sync status
|
|
152
|
-
* @returns Array of active discussions
|
|
153
|
-
*/
|
|
154
|
-
getActiveDiscussionsByOwner(ownerUserId: string): Promise<Discussion[]>;
|
|
155
147
|
markMessagesAsRead(ownerUserId: string, contactUserId: string): Promise<void>;
|
|
156
148
|
getMessagesForContactByOwner(ownerUserId: string, contactUserId: string, limit?: number): Promise<Message[]>;
|
|
157
149
|
addMessage(message: Omit<Message, 'id'>): Promise<number>;
|
package/dist/db.js
CHANGED
|
@@ -5,16 +5,11 @@
|
|
|
5
5
|
* Provides tables for contacts, messages, discussions, user profiles, and more.
|
|
6
6
|
*/
|
|
7
7
|
import Dexie from 'dexie';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
DiscussionStatus["CLOSED"] = "closed";
|
|
14
|
-
DiscussionStatus["BROKEN"] = "broken";
|
|
15
|
-
DiscussionStatus["SEND_FAILED"] = "sendFailed";
|
|
16
|
-
DiscussionStatus["RECONNECTING"] = "reconnecting";
|
|
17
|
-
})(DiscussionStatus || (DiscussionStatus = {}));
|
|
8
|
+
export var DiscussionDirection;
|
|
9
|
+
(function (DiscussionDirection) {
|
|
10
|
+
DiscussionDirection["RECEIVED"] = "received";
|
|
11
|
+
DiscussionDirection["INITIATED"] = "initiated";
|
|
12
|
+
})(DiscussionDirection || (DiscussionDirection = {}));
|
|
18
13
|
export var MessageDirection;
|
|
19
14
|
(function (MessageDirection) {
|
|
20
15
|
MessageDirection["INCOMING"] = "incoming";
|
|
@@ -23,20 +18,15 @@ export var MessageDirection;
|
|
|
23
18
|
export var MessageStatus;
|
|
24
19
|
(function (MessageStatus) {
|
|
25
20
|
MessageStatus["WAITING_SESSION"] = "waiting_session";
|
|
26
|
-
MessageStatus["
|
|
21
|
+
MessageStatus["READY"] = "ready";
|
|
27
22
|
MessageStatus["SENT"] = "sent";
|
|
28
23
|
MessageStatus["DELIVERED"] = "delivered";
|
|
29
24
|
MessageStatus["READ"] = "read";
|
|
30
|
-
MessageStatus["FAILED"] = "failed";
|
|
31
25
|
})(MessageStatus || (MessageStatus = {}));
|
|
32
|
-
export var DiscussionDirection;
|
|
33
|
-
(function (DiscussionDirection) {
|
|
34
|
-
DiscussionDirection["INITIATED"] = "initiated";
|
|
35
|
-
DiscussionDirection["RECEIVED"] = "received";
|
|
36
|
-
})(DiscussionDirection || (DiscussionDirection = {}));
|
|
37
26
|
export var MessageType;
|
|
38
27
|
(function (MessageType) {
|
|
39
28
|
MessageType["TEXT"] = "text";
|
|
29
|
+
MessageType["ANNOUNCEMENT"] = "announcement";
|
|
40
30
|
MessageType["KEEP_ALIVE"] = "keep_alive";
|
|
41
31
|
MessageType["IMAGE"] = "image";
|
|
42
32
|
MessageType["FILE"] = "file";
|
|
@@ -165,16 +155,6 @@ export class GossipDatabase extends Dexie {
|
|
|
165
155
|
.equals([ownerUserId, contactUserId])
|
|
166
156
|
.first();
|
|
167
157
|
}
|
|
168
|
-
/**
|
|
169
|
-
* Get all active discussions with their sync status
|
|
170
|
-
* @returns Array of active discussions
|
|
171
|
-
*/
|
|
172
|
-
async getActiveDiscussionsByOwner(ownerUserId) {
|
|
173
|
-
return await this.discussions
|
|
174
|
-
.where('[ownerUserId+status]')
|
|
175
|
-
.equals([ownerUserId, DiscussionStatus.ACTIVE])
|
|
176
|
-
.toArray();
|
|
177
|
-
}
|
|
178
158
|
async markMessagesAsRead(ownerUserId, contactUserId) {
|
|
179
159
|
await this.messages
|
|
180
160
|
.where('[ownerUserId+contactUserId+status]')
|
|
@@ -216,16 +196,10 @@ export class GossipDatabase extends Dexie {
|
|
|
216
196
|
await this.discussions.put({
|
|
217
197
|
ownerUserId: message.ownerUserId,
|
|
218
198
|
contactUserId: message.contactUserId,
|
|
219
|
-
direction: message.direction === MessageDirection.INCOMING
|
|
220
|
-
? DiscussionDirection.RECEIVED
|
|
221
|
-
: DiscussionDirection.INITIATED,
|
|
222
|
-
status: DiscussionStatus.PENDING,
|
|
223
|
-
nextSeeker: undefined,
|
|
224
199
|
lastMessageId: messageId,
|
|
225
200
|
lastMessageContent: message.content,
|
|
226
201
|
lastMessageTimestamp: message.timestamp,
|
|
227
202
|
unreadCount: message.direction === MessageDirection.INCOMING ? 1 : 0,
|
|
228
|
-
createdAt: new Date(),
|
|
229
203
|
updatedAt: new Date(),
|
|
230
204
|
});
|
|
231
205
|
}
|
|
@@ -274,12 +248,15 @@ export class GossipDatabase extends Dexie {
|
|
|
274
248
|
// Database instance - initialized lazily or via setDb()
|
|
275
249
|
let _db = null;
|
|
276
250
|
let _warnedGlobalDbAccess = false;
|
|
251
|
+
// Store a reference to the Proxy to detect it
|
|
252
|
+
let _proxyDb = null;
|
|
277
253
|
/**
|
|
278
254
|
* Get the database instance.
|
|
279
255
|
* Creates a default instance if none was set via setDb().
|
|
280
256
|
*/
|
|
281
257
|
export function getDb() {
|
|
282
|
-
if
|
|
258
|
+
// Prevent infinite recursion: if _db is the Proxy itself or not a real instance, create a new instance
|
|
259
|
+
if (!_db || _db === _proxyDb || !(_db instanceof GossipDatabase)) {
|
|
283
260
|
_db = new GossipDatabase();
|
|
284
261
|
}
|
|
285
262
|
return _db;
|
|
@@ -289,13 +266,24 @@ export function getDb() {
|
|
|
289
266
|
* Call this before using any SDK functions if you need a custom db instance.
|
|
290
267
|
*/
|
|
291
268
|
export function setDb(database) {
|
|
292
|
-
|
|
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
|
+
}
|
|
293
281
|
}
|
|
294
282
|
/**
|
|
295
283
|
* Get the database instance.
|
|
296
284
|
* Creates a default instance if none was set via setDb().
|
|
297
285
|
*/
|
|
298
|
-
export const db = new Proxy({}, {
|
|
286
|
+
export const db = (_proxyDb = new Proxy({}, {
|
|
299
287
|
get(_target, prop) {
|
|
300
288
|
if (!_warnedGlobalDbAccess) {
|
|
301
289
|
_warnedGlobalDbAccess = true;
|
|
@@ -308,4 +296,4 @@ export const db = new Proxy({}, {
|
|
|
308
296
|
}
|
|
309
297
|
return value;
|
|
310
298
|
},
|
|
311
|
-
});
|
|
299
|
+
}));
|