@massalabs/gossip-sdk 0.0.2-dev.20260220052400 → 0.0.2-dev.20260220075254
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 +2 -2
- package/dist/api/authProtocol.d.ts +19 -0
- package/dist/api/authProtocol.js +37 -0
- package/dist/api/messageProtocol/rest.d.ts +2 -8
- package/dist/api/messageProtocol/rest.js +2 -80
- package/dist/api/messageProtocol/types.d.ts +0 -12
- package/dist/api/restClient.d.ts +16 -0
- package/dist/api/restClient.js +57 -0
- package/dist/config/sdk.js +1 -1
- package/dist/contacts.d.ts +11 -17
- package/dist/contacts.js +20 -26
- package/dist/core/SdkEventEmitter.d.ts +2 -0
- package/dist/core/SdkEventEmitter.js +2 -0
- package/dist/core/SdkPolling.d.ts +2 -5
- package/dist/core/SdkPolling.js +1 -4
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +1 -0
- package/dist/db.d.ts +34 -56
- package/dist/db.js +39 -229
- package/dist/gossip.d.ts +54 -23
- package/dist/gossip.js +151 -121
- package/dist/index.d.ts +13 -4
- package/dist/index.js +13 -4
- package/dist/queries/activeSeekers.d.ts +2 -0
- package/dist/queries/activeSeekers.js +18 -0
- package/dist/queries/announcementCursors.d.ts +2 -0
- package/dist/queries/announcementCursors.js +20 -0
- package/dist/queries/contacts.d.ts +13 -0
- package/dist/queries/contacts.js +43 -0
- package/dist/queries/discussions.d.ts +21 -0
- package/dist/queries/discussions.js +73 -0
- package/dist/queries/index.d.ts +7 -0
- package/dist/queries/index.js +7 -0
- package/dist/queries/messages.d.ts +27 -0
- package/dist/queries/messages.js +120 -0
- package/dist/queries/pendingAnnouncements.d.ts +4 -0
- package/dist/queries/pendingAnnouncements.js +11 -0
- package/dist/queries/userProfile.d.ts +22 -0
- package/dist/queries/userProfile.js +116 -0
- package/dist/schema.d.ts +1280 -0
- package/dist/schema.js +164 -0
- package/dist/services/announcement.d.ts +8 -7
- package/dist/services/announcement.js +95 -121
- package/dist/services/auth.d.ts +4 -7
- package/dist/services/auth.js +12 -27
- package/dist/services/discussion.d.ts +8 -15
- package/dist/services/discussion.js +62 -62
- package/dist/services/message.d.ts +15 -26
- package/dist/services/message.js +282 -270
- package/dist/services/refresh.d.ts +3 -5
- package/dist/services/refresh.js +10 -13
- package/dist/sqlite-worker.d.ts +12 -0
- package/dist/sqlite-worker.js +106 -0
- package/dist/sqlite.d.ts +79 -0
- package/dist/sqlite.js +448 -0
- package/dist/utils/contacts.d.ts +2 -5
- package/dist/utils/contacts.js +23 -39
- package/dist/utils/discussions.d.ts +7 -2
- package/dist/utils/discussions.js +24 -5
- package/dist/utils/logs.js +1 -3
- package/dist/utils/validation.d.ts +2 -4
- package/dist/utils/validation.js +5 -10
- package/package.json +5 -7
- package/dist/api/messageProtocol/mock.d.ts +0 -12
- package/dist/api/messageProtocol/mock.js +0 -12
- package/dist/types/events.d.ts +0 -80
- 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
|
|
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 (
|
|
363
|
+
│ ├── db.ts # Database (SQLite) implementation
|
|
364
364
|
│ ├── contacts.ts # Contact operations
|
|
365
365
|
│ ├── api/
|
|
366
366
|
│ │ └── messageProtocol/ # REST protocol implementation
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Protocol — public key publishing & retrieval
|
|
3
|
+
*/
|
|
4
|
+
import { RestClient } from './restClient';
|
|
5
|
+
export interface IAuthProtocol {
|
|
6
|
+
/** Fetches the base64-encoded public key for the given user ID. */
|
|
7
|
+
fetchPublicKeyByUserId(userId: Uint8Array): Promise<string>;
|
|
8
|
+
/** Publishes the given base64-encoded public key to the server. */
|
|
9
|
+
postPublicKey(base64PublicKeys: string): Promise<string>;
|
|
10
|
+
}
|
|
11
|
+
export declare function createAuthProtocol(config?: Partial<{
|
|
12
|
+
baseUrl: string;
|
|
13
|
+
timeout: number;
|
|
14
|
+
retryAttempts: number;
|
|
15
|
+
}>): IAuthProtocol;
|
|
16
|
+
export declare class RestAuthProtocol extends RestClient implements IAuthProtocol {
|
|
17
|
+
fetchPublicKeyByUserId(userId: Uint8Array): Promise<string>;
|
|
18
|
+
postPublicKey(base64PublicKeys: string): Promise<string>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Protocol — public key publishing & retrieval
|
|
3
|
+
*/
|
|
4
|
+
import { RestClient } from './restClient';
|
|
5
|
+
import { encodeToBase64 } from '../utils/base64';
|
|
6
|
+
import { protocolConfig } from '../config/protocol';
|
|
7
|
+
export function createAuthProtocol(config) {
|
|
8
|
+
return new RestAuthProtocol(config?.baseUrl ?? protocolConfig.baseUrl, config?.timeout ?? protocolConfig.timeout, config?.retryAttempts ?? protocolConfig.retryAttempts);
|
|
9
|
+
}
|
|
10
|
+
export class RestAuthProtocol extends RestClient {
|
|
11
|
+
async fetchPublicKeyByUserId(userId) {
|
|
12
|
+
const response = await this.makeRequest(`${this.baseUrl}/auth/retrieve`, {
|
|
13
|
+
method: 'POST',
|
|
14
|
+
headers: { 'Content-Type': 'application/json' },
|
|
15
|
+
body: JSON.stringify({ key: encodeToBase64(userId) }),
|
|
16
|
+
});
|
|
17
|
+
if (!response.success || !response.data) {
|
|
18
|
+
throw new Error(response.error || 'Failed to fetch public key');
|
|
19
|
+
}
|
|
20
|
+
if (!response.data.value) {
|
|
21
|
+
throw new Error('Public key not found');
|
|
22
|
+
}
|
|
23
|
+
return response.data.value;
|
|
24
|
+
}
|
|
25
|
+
async postPublicKey(base64PublicKeys) {
|
|
26
|
+
const url = `${this.baseUrl}/auth`;
|
|
27
|
+
const response = await this.makeRequest(url, {
|
|
28
|
+
method: 'POST',
|
|
29
|
+
headers: { 'Content-Type': 'application/json' },
|
|
30
|
+
body: JSON.stringify({ value: base64PublicKeys }),
|
|
31
|
+
});
|
|
32
|
+
if (!response.success || !response.data) {
|
|
33
|
+
throw new Error(response.error || 'Failed to store public key');
|
|
34
|
+
}
|
|
35
|
+
return response.data.value;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -2,22 +2,16 @@
|
|
|
2
2
|
* REST API implementation of the message protocol
|
|
3
3
|
*/
|
|
4
4
|
import { BulletinItem, EncryptedMessage, IMessageProtocol, MessageProtocolResponse } from './types';
|
|
5
|
+
import { RestClient } from '../restClient';
|
|
5
6
|
export type BulletinsPage = {
|
|
6
7
|
counter: string;
|
|
7
8
|
data: string;
|
|
8
9
|
}[];
|
|
9
|
-
export declare class RestMessageProtocol implements IMessageProtocol {
|
|
10
|
-
private baseUrl;
|
|
11
|
-
private timeout;
|
|
12
|
-
private retryAttempts;
|
|
13
|
-
constructor(baseUrl: string, timeout?: number, retryAttempts?: number);
|
|
10
|
+
export declare class RestMessageProtocol extends RestClient implements IMessageProtocol {
|
|
14
11
|
fetchMessages(seekers: Uint8Array[]): Promise<EncryptedMessage[]>;
|
|
15
12
|
sendMessage(message: EncryptedMessage): Promise<void>;
|
|
16
13
|
sendAnnouncement(announcement: Uint8Array): Promise<string>;
|
|
17
14
|
fetchAnnouncements(limit?: number, cursor?: string): Promise<BulletinItem[]>;
|
|
18
15
|
fetchBulletinCounter(): Promise<string>;
|
|
19
|
-
fetchPublicKeyByUserId(userId: Uint8Array): Promise<string>;
|
|
20
|
-
postPublicKey(base64PublicKeys: string): Promise<string>;
|
|
21
|
-
private makeRequest;
|
|
22
16
|
changeNode(nodeUrl?: string): Promise<MessageProtocolResponse>;
|
|
23
17
|
}
|
|
@@ -1,30 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* REST API implementation of the message protocol
|
|
3
3
|
*/
|
|
4
|
+
import { RestClient } from '../restClient';
|
|
4
5
|
import { encodeToBase64, decodeFromBase64 } from '../../utils/base64';
|
|
5
6
|
const BULLETIN_ENDPOINT = '/bulletin';
|
|
6
7
|
const MESSAGES_ENDPOINT = '/messages';
|
|
7
|
-
export class RestMessageProtocol {
|
|
8
|
-
constructor(baseUrl, timeout = 10000, retryAttempts = 3) {
|
|
9
|
-
Object.defineProperty(this, "baseUrl", {
|
|
10
|
-
enumerable: true,
|
|
11
|
-
configurable: true,
|
|
12
|
-
writable: true,
|
|
13
|
-
value: baseUrl
|
|
14
|
-
});
|
|
15
|
-
Object.defineProperty(this, "timeout", {
|
|
16
|
-
enumerable: true,
|
|
17
|
-
configurable: true,
|
|
18
|
-
writable: true,
|
|
19
|
-
value: timeout
|
|
20
|
-
});
|
|
21
|
-
Object.defineProperty(this, "retryAttempts", {
|
|
22
|
-
enumerable: true,
|
|
23
|
-
configurable: true,
|
|
24
|
-
writable: true,
|
|
25
|
-
value: retryAttempts
|
|
26
|
-
});
|
|
27
|
-
}
|
|
8
|
+
export class RestMessageProtocol extends RestClient {
|
|
28
9
|
// TODO: Implement a fetch with pagination to avoid fetching all messages at once
|
|
29
10
|
async fetchMessages(seekers) {
|
|
30
11
|
const url = `${this.baseUrl}${MESSAGES_ENDPOINT}/fetch`;
|
|
@@ -101,65 +82,6 @@ export class RestMessageProtocol {
|
|
|
101
82
|
}
|
|
102
83
|
return response.data.counter;
|
|
103
84
|
}
|
|
104
|
-
async fetchPublicKeyByUserId(userId) {
|
|
105
|
-
const response = await this.makeRequest(`${this.baseUrl}/auth/retrieve`, {
|
|
106
|
-
method: 'POST',
|
|
107
|
-
headers: { 'Content-Type': 'application/json' },
|
|
108
|
-
body: JSON.stringify({ key: encodeToBase64(userId) }),
|
|
109
|
-
});
|
|
110
|
-
if (!response.success || !response.data) {
|
|
111
|
-
throw new Error(response.error || 'Failed to fetch public key');
|
|
112
|
-
}
|
|
113
|
-
if (!response.data.value) {
|
|
114
|
-
throw new Error('Public key not found');
|
|
115
|
-
}
|
|
116
|
-
return response.data.value;
|
|
117
|
-
}
|
|
118
|
-
async postPublicKey(base64PublicKeys) {
|
|
119
|
-
const url = `${this.baseUrl}/auth`;
|
|
120
|
-
const response = await this.makeRequest(url, {
|
|
121
|
-
method: 'POST',
|
|
122
|
-
headers: { 'Content-Type': 'application/json' },
|
|
123
|
-
body: JSON.stringify({ value: base64PublicKeys }),
|
|
124
|
-
});
|
|
125
|
-
if (!response.success || !response.data) {
|
|
126
|
-
const errorMessage = response.error || 'Failed to store public key';
|
|
127
|
-
throw new Error(errorMessage);
|
|
128
|
-
}
|
|
129
|
-
return response.data.value;
|
|
130
|
-
}
|
|
131
|
-
async makeRequest(url, options) {
|
|
132
|
-
let lastError = null;
|
|
133
|
-
for (let attempt = 1; attempt <= this.retryAttempts; attempt++) {
|
|
134
|
-
try {
|
|
135
|
-
const controller = new AbortController();
|
|
136
|
-
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
137
|
-
const response = await fetch(url, {
|
|
138
|
-
...options,
|
|
139
|
-
signal: controller.signal,
|
|
140
|
-
});
|
|
141
|
-
clearTimeout(timeoutId);
|
|
142
|
-
if (!response.ok) {
|
|
143
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
144
|
-
}
|
|
145
|
-
const data = await response.json();
|
|
146
|
-
return { success: true, data };
|
|
147
|
-
}
|
|
148
|
-
catch (error) {
|
|
149
|
-
lastError = error;
|
|
150
|
-
console.warn(`Request attempt ${attempt} failed:`, error);
|
|
151
|
-
if (attempt < this.retryAttempts) {
|
|
152
|
-
// Exponential backoff
|
|
153
|
-
const delay = Math.pow(2, attempt) * 1000;
|
|
154
|
-
await new Promise(resolve => setTimeout(resolve, delay));
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
return {
|
|
159
|
-
success: false,
|
|
160
|
-
error: lastError?.message || 'Request failed after all retry attempts',
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
85
|
async changeNode(nodeUrl) {
|
|
164
86
|
return {
|
|
165
87
|
success: true,
|
|
@@ -44,18 +44,6 @@ export interface IMessageProtocol {
|
|
|
44
44
|
* Fetch the latest bulletin counter from the API without downloading announcement data.
|
|
45
45
|
*/
|
|
46
46
|
fetchBulletinCounter(): Promise<string>;
|
|
47
|
-
/**
|
|
48
|
-
* Fetch public key by userId hash (base64 string)
|
|
49
|
-
* @param userId - Decoded userId bytes
|
|
50
|
-
* @returns Base64-encoded public keys
|
|
51
|
-
*/
|
|
52
|
-
fetchPublicKeyByUserId(userId: Uint8Array): Promise<string>;
|
|
53
|
-
/**
|
|
54
|
-
* Store public key in the auth API
|
|
55
|
-
* @param base64PublicKeys - Base64-encoded public keys
|
|
56
|
-
* @returns The hash key (hex string) returned by the API
|
|
57
|
-
*/
|
|
58
|
-
postPublicKey(base64PublicKeys: string): Promise<string>;
|
|
59
47
|
/**
|
|
60
48
|
* Change the current node provider
|
|
61
49
|
* @param nodeUrl - The URL of the new node
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base REST client with retry and timeout support.
|
|
3
|
+
* Shared by RestMessageProtocol and RestAuthProtocol.
|
|
4
|
+
*/
|
|
5
|
+
export interface RestResponse<T = unknown> {
|
|
6
|
+
success: boolean;
|
|
7
|
+
data?: T;
|
|
8
|
+
error?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare class RestClient {
|
|
11
|
+
protected baseUrl: string;
|
|
12
|
+
protected timeout: number;
|
|
13
|
+
protected retryAttempts: number;
|
|
14
|
+
constructor(baseUrl: string, timeout?: number, retryAttempts?: number);
|
|
15
|
+
protected makeRequest<T>(url: string, options: RequestInit): Promise<RestResponse<T>>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base REST client with retry and timeout support.
|
|
3
|
+
* Shared by RestMessageProtocol and RestAuthProtocol.
|
|
4
|
+
*/
|
|
5
|
+
export class RestClient {
|
|
6
|
+
constructor(baseUrl, timeout = 10000, retryAttempts = 3) {
|
|
7
|
+
Object.defineProperty(this, "baseUrl", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
configurable: true,
|
|
10
|
+
writable: true,
|
|
11
|
+
value: baseUrl
|
|
12
|
+
});
|
|
13
|
+
Object.defineProperty(this, "timeout", {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
configurable: true,
|
|
16
|
+
writable: true,
|
|
17
|
+
value: timeout
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(this, "retryAttempts", {
|
|
20
|
+
enumerable: true,
|
|
21
|
+
configurable: true,
|
|
22
|
+
writable: true,
|
|
23
|
+
value: retryAttempts
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
async makeRequest(url, options) {
|
|
27
|
+
let lastError = null;
|
|
28
|
+
for (let attempt = 1; attempt <= this.retryAttempts; attempt++) {
|
|
29
|
+
try {
|
|
30
|
+
const controller = new AbortController();
|
|
31
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
32
|
+
const response = await fetch(url, {
|
|
33
|
+
...options,
|
|
34
|
+
signal: controller.signal,
|
|
35
|
+
});
|
|
36
|
+
clearTimeout(timeoutId);
|
|
37
|
+
if (!response.ok) {
|
|
38
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
39
|
+
}
|
|
40
|
+
const data = await response.json();
|
|
41
|
+
return { success: true, data };
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
lastError = error;
|
|
45
|
+
console.warn(`Request attempt ${attempt} failed:`, error);
|
|
46
|
+
if (attempt < this.retryAttempts) {
|
|
47
|
+
const delay = Math.pow(2, attempt) * 1000;
|
|
48
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
success: false,
|
|
54
|
+
error: lastError?.message || 'Request failed after all retry attempts',
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
package/dist/config/sdk.js
CHANGED
package/dist/contacts.d.ts
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* await deleteContact(userId, contactUserId);
|
|
18
18
|
* ```
|
|
19
19
|
*/
|
|
20
|
-
import { type Contact
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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'
|
|
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
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
34
|
+
export async function getContacts(ownerUserId) {
|
|
35
35
|
try {
|
|
36
|
-
return await
|
|
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
|
|
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
|
|
58
|
+
export async function getContact(ownerUserId, contactUserId) {
|
|
60
59
|
try {
|
|
61
|
-
const contact = await
|
|
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
|
|
92
|
+
export async function addContact(ownerUserId, userId, name, publicKeys) {
|
|
96
93
|
try {
|
|
97
94
|
// Check if contact already exists
|
|
98
|
-
const existing = await
|
|
95
|
+
const existing = await getContactByOwnerAndUser(ownerUserId, userId);
|
|
99
96
|
if (existing) {
|
|
100
97
|
return { success: false, error: 'Contact already exists' };
|
|
101
98
|
}
|
|
102
|
-
|
|
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
|
|
112
|
-
|
|
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'
|
|
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
|
|
143
|
-
return await updateContactNameUtil(ownerUserId, contactUserId, newName
|
|
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,
|
|
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,
|
|
165
|
-
return await deleteContactUtil(ownerUserId, contactUserId,
|
|
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
|
|
15
|
-
handleSessionRefresh: (
|
|
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;
|
package/dist/core/SdkPolling.js
CHANGED
|
@@ -68,10 +68,7 @@ export class SdkPolling {
|
|
|
68
68
|
// Start session refresh polling
|
|
69
69
|
this.timers.sessionRefresh = setInterval(async () => {
|
|
70
70
|
try {
|
|
71
|
-
|
|
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));
|
package/dist/core/index.d.ts
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
* Core SDK components
|
|
3
3
|
*/
|
|
4
4
|
export { SdkEventEmitter } from './SdkEventEmitter';
|
|
5
|
-
export
|
|
5
|
+
export { SdkEventType, type SdkEventHandlers } from './SdkEventEmitter';
|
|
6
6
|
export { SdkPolling } from './SdkPolling';
|
|
7
7
|
export type { PollingCallbacks } from './SdkPolling';
|