@massalabs/gossip-sdk 0.0.2-dev.20260220052400 → 0.0.2-dev.20260220053835

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +2 -2
  2. package/dist/config/sdk.js +1 -1
  3. package/dist/contacts.d.ts +11 -17
  4. package/dist/contacts.js +20 -26
  5. package/dist/core/SdkEventEmitter.d.ts +2 -0
  6. package/dist/core/SdkEventEmitter.js +2 -0
  7. package/dist/core/SdkPolling.d.ts +2 -5
  8. package/dist/core/SdkPolling.js +1 -4
  9. package/dist/core/index.d.ts +1 -1
  10. package/dist/core/index.js +1 -0
  11. package/dist/db.d.ts +34 -56
  12. package/dist/db.js +39 -229
  13. package/dist/gossip.d.ts +54 -23
  14. package/dist/gossip.js +149 -120
  15. package/dist/index.d.ts +13 -4
  16. package/dist/index.js +13 -4
  17. package/dist/queries/activeSeekers.d.ts +2 -0
  18. package/dist/queries/activeSeekers.js +18 -0
  19. package/dist/queries/announcementCursors.d.ts +2 -0
  20. package/dist/queries/announcementCursors.js +20 -0
  21. package/dist/queries/contacts.d.ts +13 -0
  22. package/dist/queries/contacts.js +43 -0
  23. package/dist/queries/discussions.d.ts +21 -0
  24. package/dist/queries/discussions.js +73 -0
  25. package/dist/queries/index.d.ts +7 -0
  26. package/dist/queries/index.js +7 -0
  27. package/dist/queries/messages.d.ts +27 -0
  28. package/dist/queries/messages.js +120 -0
  29. package/dist/queries/pendingAnnouncements.d.ts +4 -0
  30. package/dist/queries/pendingAnnouncements.js +11 -0
  31. package/dist/queries/userProfile.d.ts +22 -0
  32. package/dist/queries/userProfile.js +116 -0
  33. package/dist/schema.d.ts +1280 -0
  34. package/dist/schema.js +164 -0
  35. package/dist/services/announcement.d.ts +8 -7
  36. package/dist/services/announcement.js +95 -121
  37. package/dist/services/auth.d.ts +1 -3
  38. package/dist/services/auth.js +4 -11
  39. package/dist/services/discussion.d.ts +8 -15
  40. package/dist/services/discussion.js +62 -62
  41. package/dist/services/message.d.ts +15 -26
  42. package/dist/services/message.js +282 -270
  43. package/dist/services/refresh.d.ts +3 -5
  44. package/dist/services/refresh.js +10 -13
  45. package/dist/sqlite-worker.d.ts +12 -0
  46. package/dist/sqlite-worker.js +106 -0
  47. package/dist/sqlite.d.ts +79 -0
  48. package/dist/sqlite.js +448 -0
  49. package/dist/utils/contacts.d.ts +2 -5
  50. package/dist/utils/contacts.js +23 -39
  51. package/dist/utils/discussions.d.ts +7 -2
  52. package/dist/utils/discussions.js +24 -5
  53. package/dist/utils/logs.js +1 -3
  54. package/dist/utils/validation.d.ts +2 -4
  55. package/dist/utils/validation.js +5 -10
  56. package/package.json +5 -7
  57. package/dist/api/messageProtocol/mock.d.ts +0 -12
  58. package/dist/api/messageProtocol/mock.js +0 -12
  59. package/dist/types/events.d.ts +0 -80
  60. package/dist/types/events.js +0 -7
package/README.md CHANGED
@@ -352,7 +352,7 @@ npm test # Watch mode
352
352
  npm run test:run # Single run
353
353
  ```
354
354
 
355
- Tests use `fake-indexeddb` to simulate IndexedDB in Node.js environment.
355
+ Tests use wa-sqlite with in-memory databases for fast, isolated execution.
356
356
 
357
357
  ## Architecture
358
358
 
@@ -360,7 +360,7 @@ Tests use `fake-indexeddb` to simulate IndexedDB in Node.js environment.
360
360
  gossip-sdk/
361
361
  ├── src/
362
362
  │ ├── gossipSdk.ts # SDK class & factory
363
- │ ├── db.ts # Database (Dexie) implementation
363
+ │ ├── db.ts # Database (SQLite) implementation
364
364
  │ ├── contacts.ts # Contact operations
365
365
  │ ├── api/
366
366
  │ │ └── messageProtocol/ # REST protocol implementation
@@ -16,7 +16,7 @@ export const defaultSdkConfig = {
16
16
  enabled: false,
17
17
  messagesIntervalMs: 5000,
18
18
  announcementsIntervalMs: 10000,
19
- sessionRefreshIntervalMs: 10000, //30000,
19
+ sessionRefreshIntervalMs: 10000,
20
20
  },
21
21
  messages: {
22
22
  fetchDelayMs: 100,
@@ -17,7 +17,7 @@
17
17
  * await deleteContact(userId, contactUserId);
18
18
  * ```
19
19
  */
20
- import { type Contact, type GossipDatabase } from './db';
20
+ import { type Contact } from './db';
21
21
  import type { UpdateContactNameResult, DeleteContactResult } from './utils/contacts';
22
22
  import type { UserPublicKeys } from './wasm/bindings';
23
23
  import type { SessionModule } from './wasm/session';
@@ -26,33 +26,31 @@ export type { UpdateContactNameResult, DeleteContactResult };
26
26
  * Get all contacts for an owner.
27
27
  *
28
28
  * @param ownerUserId - The user ID of the contact owner
29
- * @param db - Database instance
30
29
  * @returns Array of contacts
31
30
  *
32
31
  * @example
33
32
  * ```typescript
34
- * const contacts = await getContacts(myUserId, db);
33
+ * const contacts = await getContacts(myUserId);
35
34
  * contacts.forEach(c => console.log(c.name, c.userId));
36
35
  * ```
37
36
  */
38
- export declare function getContacts(ownerUserId: string, db: GossipDatabase): Promise<Contact[]>;
37
+ export declare function getContacts(ownerUserId: string): Promise<Contact[]>;
39
38
  /**
40
39
  * Get a specific contact by owner and contact user IDs.
41
40
  *
42
41
  * @param ownerUserId - The user ID of the contact owner
43
42
  * @param contactUserId - The user ID of the contact
44
- * @param db - Database instance
45
43
  * @returns Contact or null if not found
46
44
  *
47
45
  * @example
48
46
  * ```typescript
49
- * const contact = await getContact(myUserId, theirUserId, db);
47
+ * const contact = await getContact(myUserId, theirUserId);
50
48
  * if (contact) {
51
49
  * console.log('Found contact:', contact.name);
52
50
  * }
53
51
  * ```
54
52
  */
55
- export declare function getContact(ownerUserId: string, contactUserId: string, db: GossipDatabase): Promise<Contact | null>;
53
+ export declare function getContact(ownerUserId: string, contactUserId: string): Promise<Contact | null>;
56
54
  /**
57
55
  * Add a new contact.
58
56
  *
@@ -60,7 +58,6 @@ export declare function getContact(ownerUserId: string, contactUserId: string, d
60
58
  * @param userId - The user ID of the contact (Bech32-encoded)
61
59
  * @param name - Display name for the contact
62
60
  * @param publicKeys - The contact's public keys
63
- * @param db - Database instance
64
61
  * @returns Result with success status and optional contact
65
62
  *
66
63
  * @example
@@ -69,8 +66,7 @@ export declare function getContact(ownerUserId: string, contactUserId: string, d
69
66
  * myUserId,
70
67
  * 'gossip1abc...',
71
68
  * 'Alice',
72
- * alicePublicKeys,
73
- * db
69
+ * alicePublicKeys
74
70
  * );
75
71
  * if (result.success) {
76
72
  * console.log('Contact added:', result.contact?.name);
@@ -79,7 +75,7 @@ export declare function getContact(ownerUserId: string, contactUserId: string, d
79
75
  * }
80
76
  * ```
81
77
  */
82
- export declare function addContact(ownerUserId: string, userId: string, name: string, publicKeys: UserPublicKeys, db: GossipDatabase): Promise<{
78
+ export declare function addContact(ownerUserId: string, userId: string, name: string, publicKeys: UserPublicKeys): Promise<{
83
79
  success: boolean;
84
80
  error?: string;
85
81
  contact?: Contact;
@@ -90,12 +86,11 @@ export declare function addContact(ownerUserId: string, userId: string, name: st
90
86
  * @param ownerUserId - The user ID of the contact owner
91
87
  * @param contactUserId - The user ID of the contact
92
88
  * @param newName - New name for the contact
93
- * @param db - Database instance
94
89
  * @returns Result with success status and trimmed name
95
90
  *
96
91
  * @example
97
92
  * ```typescript
98
- * const result = await updateContactName(myUserId, theirUserId, 'Alice Smith', db);
93
+ * const result = await updateContactName(myUserId, theirUserId, 'Alice Smith');
99
94
  * if (result.ok) {
100
95
  * console.log('Updated to:', result.trimmedName);
101
96
  * } else {
@@ -103,19 +98,18 @@ export declare function addContact(ownerUserId: string, userId: string, name: st
103
98
  * }
104
99
  * ```
105
100
  */
106
- export declare function updateContactName(ownerUserId: string, contactUserId: string, newName: string, db: GossipDatabase): Promise<UpdateContactNameResult>;
101
+ export declare function updateContactName(ownerUserId: string, contactUserId: string, newName: string): Promise<UpdateContactNameResult>;
107
102
  /**
108
103
  * Delete a contact and all associated discussions and messages.
109
104
  *
110
105
  * @param ownerUserId - The user ID of the contact owner
111
106
  * @param contactUserId - The user ID of the contact to delete
112
- * @param db - Database instance
113
107
  * @param session - Session module for peer management
114
108
  * @returns Result with success status
115
109
  *
116
110
  * @example
117
111
  * ```typescript
118
- * const result = await deleteContact(myUserId, theirUserId, db, session);
112
+ * const result = await deleteContact(myUserId, theirUserId, session);
119
113
  * if (result.ok) {
120
114
  * console.log('Contact deleted');
121
115
  * } else {
@@ -123,4 +117,4 @@ export declare function updateContactName(ownerUserId: string, contactUserId: st
123
117
  * }
124
118
  * ```
125
119
  */
126
- export declare function deleteContact(ownerUserId: string, contactUserId: string, db: GossipDatabase, session: SessionModule): Promise<DeleteContactResult>;
120
+ export declare function deleteContact(ownerUserId: string, contactUserId: string, session: SessionModule): Promise<DeleteContactResult>;
package/dist/contacts.js CHANGED
@@ -18,22 +18,22 @@
18
18
  * ```
19
19
  */
20
20
  import { updateContactName as updateContactNameUtil, deleteContact as deleteContactUtil, } from './utils/contacts';
21
+ import { getContactsByOwner, getContactByOwnerAndUser, insertContact as queryInsertContact, } from './queries';
21
22
  /**
22
23
  * Get all contacts for an owner.
23
24
  *
24
25
  * @param ownerUserId - The user ID of the contact owner
25
- * @param db - Database instance
26
26
  * @returns Array of contacts
27
27
  *
28
28
  * @example
29
29
  * ```typescript
30
- * const contacts = await getContacts(myUserId, db);
30
+ * const contacts = await getContacts(myUserId);
31
31
  * contacts.forEach(c => console.log(c.name, c.userId));
32
32
  * ```
33
33
  */
34
- export async function getContacts(ownerUserId, db) {
34
+ export async function getContacts(ownerUserId) {
35
35
  try {
36
- return await db.getContactsByOwner(ownerUserId);
36
+ return await getContactsByOwner(ownerUserId);
37
37
  }
38
38
  catch (error) {
39
39
  console.error('Error getting contacts:', error);
@@ -45,20 +45,19 @@ export async function getContacts(ownerUserId, db) {
45
45
  *
46
46
  * @param ownerUserId - The user ID of the contact owner
47
47
  * @param contactUserId - The user ID of the contact
48
- * @param db - Database instance
49
48
  * @returns Contact or null if not found
50
49
  *
51
50
  * @example
52
51
  * ```typescript
53
- * const contact = await getContact(myUserId, theirUserId, db);
52
+ * const contact = await getContact(myUserId, theirUserId);
54
53
  * if (contact) {
55
54
  * console.log('Found contact:', contact.name);
56
55
  * }
57
56
  * ```
58
57
  */
59
- export async function getContact(ownerUserId, contactUserId, db) {
58
+ export async function getContact(ownerUserId, contactUserId) {
60
59
  try {
61
- const contact = await db.getContactByOwnerAndUserId(ownerUserId, contactUserId);
60
+ const contact = await getContactByOwnerAndUser(ownerUserId, contactUserId);
62
61
  return contact ?? null;
63
62
  }
64
63
  catch (error) {
@@ -73,7 +72,6 @@ export async function getContact(ownerUserId, contactUserId, db) {
73
72
  * @param userId - The user ID of the contact (Bech32-encoded)
74
73
  * @param name - Display name for the contact
75
74
  * @param publicKeys - The contact's public keys
76
- * @param db - Database instance
77
75
  * @returns Result with success status and optional contact
78
76
  *
79
77
  * @example
@@ -82,8 +80,7 @@ export async function getContact(ownerUserId, contactUserId, db) {
82
80
  * myUserId,
83
81
  * 'gossip1abc...',
84
82
  * 'Alice',
85
- * alicePublicKeys,
86
- * db
83
+ * alicePublicKeys
87
84
  * );
88
85
  * if (result.success) {
89
86
  * console.log('Contact added:', result.contact?.name);
@@ -92,14 +89,14 @@ export async function getContact(ownerUserId, contactUserId, db) {
92
89
  * }
93
90
  * ```
94
91
  */
95
- export async function addContact(ownerUserId, userId, name, publicKeys, db) {
92
+ export async function addContact(ownerUserId, userId, name, publicKeys) {
96
93
  try {
97
94
  // Check if contact already exists
98
- const existing = await db.getContactByOwnerAndUserId(ownerUserId, userId);
95
+ const existing = await getContactByOwnerAndUser(ownerUserId, userId);
99
96
  if (existing) {
100
97
  return { success: false, error: 'Contact already exists' };
101
98
  }
102
- const contact = {
99
+ await queryInsertContact({
103
100
  ownerUserId,
104
101
  userId,
105
102
  name,
@@ -107,10 +104,9 @@ export async function addContact(ownerUserId, userId, name, publicKeys, db) {
107
104
  isOnline: false,
108
105
  lastSeen: new Date(),
109
106
  createdAt: new Date(),
110
- };
111
- const id = await db.contacts.add(contact);
112
- const newContact = await db.contacts.get(id);
113
- return { success: true, contact: newContact };
107
+ });
108
+ const newContact = await getContactByOwnerAndUser(ownerUserId, userId);
109
+ return { success: true, contact: newContact ?? undefined };
114
110
  }
115
111
  catch (error) {
116
112
  console.error('Error adding contact:', error);
@@ -126,12 +122,11 @@ export async function addContact(ownerUserId, userId, name, publicKeys, db) {
126
122
  * @param ownerUserId - The user ID of the contact owner
127
123
  * @param contactUserId - The user ID of the contact
128
124
  * @param newName - New name for the contact
129
- * @param db - Database instance
130
125
  * @returns Result with success status and trimmed name
131
126
  *
132
127
  * @example
133
128
  * ```typescript
134
- * const result = await updateContactName(myUserId, theirUserId, 'Alice Smith', db);
129
+ * const result = await updateContactName(myUserId, theirUserId, 'Alice Smith');
135
130
  * if (result.ok) {
136
131
  * console.log('Updated to:', result.trimmedName);
137
132
  * } else {
@@ -139,21 +134,20 @@ export async function addContact(ownerUserId, userId, name, publicKeys, db) {
139
134
  * }
140
135
  * ```
141
136
  */
142
- export async function updateContactName(ownerUserId, contactUserId, newName, db) {
143
- return await updateContactNameUtil(ownerUserId, contactUserId, newName, db);
137
+ export async function updateContactName(ownerUserId, contactUserId, newName) {
138
+ return await updateContactNameUtil(ownerUserId, contactUserId, newName);
144
139
  }
145
140
  /**
146
141
  * Delete a contact and all associated discussions and messages.
147
142
  *
148
143
  * @param ownerUserId - The user ID of the contact owner
149
144
  * @param contactUserId - The user ID of the contact to delete
150
- * @param db - Database instance
151
145
  * @param session - Session module for peer management
152
146
  * @returns Result with success status
153
147
  *
154
148
  * @example
155
149
  * ```typescript
156
- * const result = await deleteContact(myUserId, theirUserId, db, session);
150
+ * const result = await deleteContact(myUserId, theirUserId, session);
157
151
  * if (result.ok) {
158
152
  * console.log('Contact deleted');
159
153
  * } else {
@@ -161,6 +155,6 @@ export async function updateContactName(ownerUserId, contactUserId, newName, db)
161
155
  * }
162
156
  * ```
163
157
  */
164
- export async function deleteContact(ownerUserId, contactUserId, db, session) {
165
- return await deleteContactUtil(ownerUserId, contactUserId, db, session);
158
+ export async function deleteContact(ownerUserId, contactUserId, session) {
159
+ return await deleteContactUtil(ownerUserId, contactUserId, session);
166
160
  }
@@ -7,6 +7,7 @@ import type { Message, Discussion, Contact } from '../db';
7
7
  export declare enum SdkEventType {
8
8
  MESSAGE_RECEIVED = "messageReceived",
9
9
  MESSAGE_SENT = "messageSent",
10
+ MESSAGE_READ = "messageRead",
10
11
  MESSAGE_FAILED = "messageFailed",
11
12
  SESSION_REQUESTED = "sessionRequested",
12
13
  SESSION_CREATED = "sessionCreated",
@@ -17,6 +18,7 @@ export declare enum SdkEventType {
17
18
  export interface SdkEventHandlers {
18
19
  [SdkEventType.MESSAGE_RECEIVED]: (message: Message) => void;
19
20
  [SdkEventType.MESSAGE_SENT]: (message: Message) => void;
21
+ [SdkEventType.MESSAGE_READ]: (messageId: number) => void;
20
22
  [SdkEventType.MESSAGE_FAILED]: (message: Message, error: Error) => void;
21
23
  [SdkEventType.SESSION_REQUESTED]: (discussion: Discussion, contact: Contact) => void;
22
24
  [SdkEventType.SESSION_CREATED]: (discussion: Discussion) => void;
@@ -10,6 +10,7 @@ export var SdkEventType;
10
10
  (function (SdkEventType) {
11
11
  SdkEventType["MESSAGE_RECEIVED"] = "messageReceived";
12
12
  SdkEventType["MESSAGE_SENT"] = "messageSent";
13
+ SdkEventType["MESSAGE_READ"] = "messageRead";
13
14
  SdkEventType["MESSAGE_FAILED"] = "messageFailed";
14
15
  SdkEventType["SESSION_REQUESTED"] = "sessionRequested";
15
16
  SdkEventType["SESSION_CREATED"] = "sessionCreated";
@@ -29,6 +30,7 @@ export class SdkEventEmitter {
29
30
  value: {
30
31
  [SdkEventType.MESSAGE_RECEIVED]: new Set(),
31
32
  [SdkEventType.MESSAGE_SENT]: new Set(),
33
+ [SdkEventType.MESSAGE_READ]: new Set(),
32
34
  [SdkEventType.MESSAGE_FAILED]: new Set(),
33
35
  [SdkEventType.SESSION_REQUESTED]: new Set(),
34
36
  [SdkEventType.SESSION_CREATED]: new Set(),
@@ -4,17 +4,14 @@
4
4
  * Manages polling timers for messages, announcements, and session refresh.
5
5
  */
6
6
  import type { SdkConfig } from '../config/sdk';
7
- import type { Discussion } from '../db';
8
7
  import { SdkEventEmitter } from './SdkEventEmitter';
9
8
  export interface PollingCallbacks {
10
9
  /** Fetch messages from protocol */
11
10
  fetchMessages: () => Promise<void>;
12
11
  /** Fetch and process announcements */
13
12
  fetchAnnouncements: () => Promise<void>;
14
- /** Handle session refresh for active discussions */
15
- handleSessionRefresh: (discussions: Discussion[]) => Promise<void>;
16
- /** Get active discussions for session refresh */
17
- getActiveDiscussions: () => Promise<Discussion[]>;
13
+ /** Handle session refresh (state update) */
14
+ handleSessionRefresh: () => Promise<void>;
18
15
  }
19
16
  export declare class SdkPolling {
20
17
  private timers;
@@ -68,10 +68,7 @@ export class SdkPolling {
68
68
  // Start session refresh polling
69
69
  this.timers.sessionRefresh = setInterval(async () => {
70
70
  try {
71
- const discussions = await this.callbacks?.getActiveDiscussions();
72
- if (discussions && discussions.length > 0) {
73
- await this.callbacks?.handleSessionRefresh(discussions);
74
- }
71
+ await this.callbacks?.handleSessionRefresh();
75
72
  }
76
73
  catch (error) {
77
74
  const err = error instanceof Error ? error : new Error(String(error));
@@ -2,6 +2,6 @@
2
2
  * Core SDK components
3
3
  */
4
4
  export { SdkEventEmitter } from './SdkEventEmitter';
5
- export type { SdkEventType, SdkEventHandlers } from './SdkEventEmitter';
5
+ export { SdkEventType, type SdkEventHandlers } from './SdkEventEmitter';
6
6
  export { SdkPolling } from './SdkPolling';
7
7
  export type { PollingCallbacks } from './SdkPolling';
@@ -2,4 +2,5 @@
2
2
  * Core SDK components
3
3
  */
4
4
  export { SdkEventEmitter } from './SdkEventEmitter';
5
+ export { SdkEventType } from './SdkEventEmitter';
5
6
  export { SdkPolling } from './SdkPolling';
package/dist/db.d.ts CHANGED
@@ -1,10 +1,9 @@
1
1
  /**
2
- * Gossip Database
2
+ * Gossip Database Types
3
3
  *
4
- * IndexedDB database implementation using Dexie for the Gossip messenger.
5
- * Provides tables for contacts, messages, discussions, user profiles, and more.
4
+ * Type definitions for the Gossip messenger data models.
5
+ * Database operations use SQLite via Drizzle ORM (see sqlite.ts and schema.ts).
6
6
  */
7
- import Dexie, { Table } from 'dexie';
8
7
  export type AuthMethod = 'capacitor' | 'webauthn' | 'password';
9
8
  export declare const MESSAGE_ID_SIZE = 12;
10
9
  export interface Contact {
@@ -12,7 +11,7 @@ export interface Contact {
12
11
  ownerUserId: string;
13
12
  userId: string;
14
13
  name: string;
15
- avatar?: string;
14
+ avatar?: string | null;
16
15
  publicKeys: Uint8Array;
17
16
  isOnline: boolean;
18
17
  lastSeen: Date;
@@ -44,7 +43,7 @@ export interface Message {
44
43
  export interface UserProfile {
45
44
  userId: string;
46
45
  username: string;
47
- avatar?: string;
46
+ avatar?: string | null;
48
47
  security: {
49
48
  encKeySalt: Uint8Array;
50
49
  authMethod: AuthMethod;
@@ -65,7 +64,14 @@ export interface UserProfile {
65
64
  createdAt: Date;
66
65
  updatedAt: Date;
67
66
  lastPublicKeyPush?: Date;
68
- lastBulletinCounter?: string;
67
+ }
68
+ export declare enum DiscussionStatus {
69
+ PENDING = "pending",
70
+ ACTIVE = "active",
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
75
  }
70
76
  export declare enum DiscussionDirection {
71
77
  RECEIVED = "received",
@@ -78,9 +84,11 @@ export declare enum MessageDirection {
78
84
  export declare enum MessageStatus {
79
85
  WAITING_SESSION = "waiting_session",// Waiting for active session with peer
80
86
  READY = "ready",
87
+ SENDING = "sending",
81
88
  SENT = "sent",
82
89
  DELIVERED = "delivered",
83
- READ = "read"
90
+ READ = "read",
91
+ FAILED = "failed"
84
92
  }
85
93
  export declare enum MessageType {
86
94
  TEXT = "text",
@@ -91,11 +99,18 @@ export declare enum MessageType {
91
99
  AUDIO = "audio",
92
100
  VIDEO = "video"
93
101
  }
94
- export interface readyAnnouncement {
102
+ export interface ReadyAnnouncement {
95
103
  announcement_bytes: Uint8Array;
96
104
  when_to_send: Date;
97
105
  }
98
- export type SendAnnouncement = null | readyAnnouncement;
106
+ export type SendAnnouncement = null | ReadyAnnouncement;
107
+ /** Serialize a SendAnnouncement to a JSON string for SQLite text column */
108
+ export declare function serializeSendAnnouncement(announcement: ReadyAnnouncement): string;
109
+ /** Deserialize a SendAnnouncement JSON string from SQLite back to an object */
110
+ export declare function deserializeSendAnnouncement(json: string): ReadyAnnouncement;
111
+ /** Convert a raw SQLite discussion row to a Discussion object.
112
+ * Deserializes sendAnnouncement from JSON text to SendAnnouncement. */
113
+ export declare function rowToDiscussion(row: Record<string, unknown>): Discussion;
99
114
  export interface Discussion {
100
115
  id?: number;
101
116
  ownerUserId: string;
@@ -103,12 +118,16 @@ export interface Discussion {
103
118
  weAccepted: boolean;
104
119
  sendAnnouncement: SendAnnouncement;
105
120
  direction: DiscussionDirection;
106
- lastSyncTimestamp?: Date;
107
- customName?: string;
121
+ status: DiscussionStatus;
122
+ nextSeeker: Uint8Array | null;
123
+ initiationAnnouncement: Uint8Array | null;
124
+ announcementMessage: string | null;
125
+ lastSyncTimestamp: Date | null;
126
+ customName: string | null;
108
127
  lastAnnouncementMessage?: string;
109
- lastMessageId?: number;
110
- lastMessageContent?: string;
111
- lastMessageTimestamp?: Date;
128
+ lastMessageId: number | null;
129
+ lastMessageContent: string | null;
130
+ lastMessageTimestamp: Date | null;
112
131
  unreadCount: number;
113
132
  createdAt: Date;
114
133
  updatedAt: Date;
@@ -129,44 +148,3 @@ export interface ActiveSeeker {
129
148
  id?: number;
130
149
  seeker: Uint8Array;
131
150
  }
132
- export declare class GossipDatabase extends Dexie {
133
- contacts: Table<Contact>;
134
- messages: Table<Message>;
135
- userProfile: Table<UserProfile>;
136
- discussions: Table<Discussion>;
137
- pendingEncryptedMessages: Table<PendingEncryptedMessage>;
138
- pendingAnnouncements: Table<PendingAnnouncement>;
139
- activeSeekers: Table<ActiveSeeker>;
140
- constructor();
141
- /** CONTACTS */
142
- getContactsByOwner(ownerUserId: string): Promise<Contact[]>;
143
- getContactByOwnerAndUserId(ownerUserId: string, userId: string): Promise<Contact | undefined>;
144
- /** DISCUSSIONS */
145
- getDiscussionsByOwner(ownerUserId: string): Promise<Discussion[]>;
146
- getUnreadCountByOwner(ownerUserId: string): Promise<number>;
147
- getDiscussionByOwnerAndContact(ownerUserId: string, contactUserId: string): Promise<Discussion | undefined>;
148
- markMessagesAsRead(ownerUserId: string, contactUserId: string): Promise<void>;
149
- getMessagesForContactByOwner(ownerUserId: string, contactUserId: string, limit?: number): Promise<Message[]>;
150
- addMessage(message: Omit<Message, 'id'>): Promise<number>;
151
- /**
152
- * Update the last sync timestamp for a discussion
153
- * @param discussionId - The discussion ID
154
- * @param timestamp - The sync timestamp
155
- */
156
- updateLastSyncTimestamp(discussionId: number, timestamp: Date): Promise<void>;
157
- deleteDb(): Promise<void>;
158
- /**
159
- * Set all active seekers, replacing any existing ones
160
- * @param seekers - Array of seeker Uint8Arrays to store
161
- */
162
- setActiveSeekers(seekers: Uint8Array[]): Promise<void>;
163
- /**
164
- * Get all active seekers from the database
165
- * @returns Array of seeker Uint8Arrays
166
- */
167
- getActiveSeekers(): Promise<Uint8Array[]>;
168
- }
169
- /**
170
- * Get the database instance. Creates a default instance on first call.
171
- */
172
- export declare function gossipDb(): GossipDatabase;