@abraca/dabra 1.6.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/abracadabra-provider.cjs +346 -6
- package/dist/abracadabra-provider.cjs.map +1 -1
- package/dist/abracadabra-provider.esm.js +345 -7
- package/dist/abracadabra-provider.esm.js.map +1 -1
- package/dist/index.d.ts +193 -3
- package/package.json +1 -1
- package/src/ChatClient.ts +234 -0
- package/src/IdentityDoc.ts +11 -0
- package/src/NotificationsClient.ts +185 -0
- package/src/index.ts +16 -0
- package/src/types.ts +86 -0
- package/src/webrtc/DevicePairingChannel.ts +18 -6
package/src/index.ts
CHANGED
|
@@ -36,6 +36,22 @@ export type {
|
|
|
36
36
|
DeviceTier,
|
|
37
37
|
} from "./IdentityDoc.ts";
|
|
38
38
|
export { DeviceRegistrationService } from "./DeviceRegistrationService.ts";
|
|
39
|
+
export { ChatClient } from "./ChatClient.ts";
|
|
40
|
+
export type { ChatClientTransport } from "./ChatClient.ts";
|
|
41
|
+
export { NotificationsClient } from "./NotificationsClient.ts";
|
|
42
|
+
export type {
|
|
43
|
+
ChatMessage,
|
|
44
|
+
ChatChannel,
|
|
45
|
+
ChatTypingEvent,
|
|
46
|
+
ChatReadReceipt,
|
|
47
|
+
ChatReadCursor,
|
|
48
|
+
SendChatMessageInput,
|
|
49
|
+
GetChatHistoryInput,
|
|
50
|
+
NotificationRecord,
|
|
51
|
+
NotificationReadUpdate,
|
|
52
|
+
CreateNotificationInput,
|
|
53
|
+
FetchNotificationsInput,
|
|
54
|
+
} from "./types.ts";
|
|
39
55
|
export {
|
|
40
56
|
generateMnemonic,
|
|
41
57
|
validateMnemonic,
|
package/src/types.ts
CHANGED
|
@@ -348,3 +348,89 @@ export interface DocEncryptionInfo {
|
|
|
348
348
|
effective_mode: "none" | "cse" | "e2e";
|
|
349
349
|
inherited_from?: string;
|
|
350
350
|
}
|
|
351
|
+
|
|
352
|
+
// ── Chat (stateless channel) ─────────────────────────────────────────────────
|
|
353
|
+
|
|
354
|
+
export interface ChatMessage {
|
|
355
|
+
id: string;
|
|
356
|
+
channel: string;
|
|
357
|
+
sender_id: string;
|
|
358
|
+
sender_name?: string | null;
|
|
359
|
+
content: string;
|
|
360
|
+
created_at: number;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export interface ChatChannel {
|
|
364
|
+
channel: string;
|
|
365
|
+
label?: string | null;
|
|
366
|
+
last_message: ChatMessage;
|
|
367
|
+
unread_count: number;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
export interface ChatTypingEvent {
|
|
371
|
+
channel: string;
|
|
372
|
+
sender_id: string;
|
|
373
|
+
sender_name?: string | null;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
export interface ChatReadReceipt {
|
|
377
|
+
channel: string;
|
|
378
|
+
user_id: string;
|
|
379
|
+
last_read_at: number;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
export interface ChatReadCursor {
|
|
383
|
+
user_id: string;
|
|
384
|
+
last_read_at: number;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
export interface SendChatMessageInput {
|
|
388
|
+
channel: string;
|
|
389
|
+
content: string;
|
|
390
|
+
sender_name?: string;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
export interface GetChatHistoryInput {
|
|
394
|
+
channel: string;
|
|
395
|
+
before?: number;
|
|
396
|
+
limit?: number;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// ── Notifications (stateless channel) ────────────────────────────────────────
|
|
400
|
+
|
|
401
|
+
export interface NotificationRecord {
|
|
402
|
+
id: string;
|
|
403
|
+
recipient_id: string;
|
|
404
|
+
notification_type: string;
|
|
405
|
+
title: string;
|
|
406
|
+
body: string;
|
|
407
|
+
icon?: string | null;
|
|
408
|
+
link?: string | null;
|
|
409
|
+
source_id?: string | null;
|
|
410
|
+
read: boolean;
|
|
411
|
+
created_at: number;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
export interface NotificationReadUpdate {
|
|
415
|
+
/** Present when a specific set of notifications was marked read. */
|
|
416
|
+
ids?: string[];
|
|
417
|
+
/** Present when mark_all_read was called. */
|
|
418
|
+
all?: boolean;
|
|
419
|
+
recipient_id: string;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
export interface CreateNotificationInput {
|
|
423
|
+
recipient_id: string;
|
|
424
|
+
notification_type?: string;
|
|
425
|
+
title: string;
|
|
426
|
+
body?: string;
|
|
427
|
+
icon?: string;
|
|
428
|
+
link?: string;
|
|
429
|
+
source_id?: string;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
export interface FetchNotificationsInput {
|
|
433
|
+
before?: number;
|
|
434
|
+
limit?: number;
|
|
435
|
+
unread_only?: boolean;
|
|
436
|
+
}
|
|
@@ -77,11 +77,15 @@ interface PairRequestMsg {
|
|
|
77
77
|
|
|
78
78
|
interface PairApprovedMsg {
|
|
79
79
|
type: "pair-approved";
|
|
80
|
+
/** Approver's account-level Ed25519 public key (base64url). */
|
|
81
|
+
masterPublicKey?: string;
|
|
80
82
|
}
|
|
81
83
|
|
|
82
84
|
interface PairInviteCodeMsg {
|
|
83
85
|
type: "pair-invite-code";
|
|
84
86
|
code: string;
|
|
87
|
+
/** Approver's account-level Ed25519 public key (base64url). */
|
|
88
|
+
masterPublicKey?: string;
|
|
85
89
|
}
|
|
86
90
|
|
|
87
91
|
interface PairRejectedMsg {
|
|
@@ -171,8 +175,12 @@ export class DevicePairingChannel extends EventEmitter {
|
|
|
171
175
|
/**
|
|
172
176
|
* Approve the pending pairing request. Calls `client.addKey()` to
|
|
173
177
|
* register Device B's public key, then notifies Device B.
|
|
178
|
+
*
|
|
179
|
+
* @param client Authenticated REST client.
|
|
180
|
+
* @param masterPublicKey Approver's account-level Ed25519 public key (base64url).
|
|
181
|
+
* Sent to Device B so it can adopt the master's identity doc.
|
|
174
182
|
*/
|
|
175
|
-
async approve(client: AbracadabraClient): Promise<PairingResult> {
|
|
183
|
+
async approve(client: AbracadabraClient, masterPublicKey?: string): Promise<PairingResult> {
|
|
176
184
|
if (this.role !== "approver") {
|
|
177
185
|
return { success: false, error: "Only the approver can approve" };
|
|
178
186
|
}
|
|
@@ -192,7 +200,7 @@ export class DevicePairingChannel extends EventEmitter {
|
|
|
192
200
|
x25519Key: req.x25519Key,
|
|
193
201
|
});
|
|
194
202
|
|
|
195
|
-
this.sendMessage({ type: "pair-approved" });
|
|
203
|
+
this.sendMessage({ type: "pair-approved", masterPublicKey });
|
|
196
204
|
this._pendingRequest = null;
|
|
197
205
|
this.emit("pairingComplete", { success: true } as PairingResult);
|
|
198
206
|
return { success: true };
|
|
@@ -210,8 +218,12 @@ export class DevicePairingChannel extends EventEmitter {
|
|
|
210
218
|
* Approve via server-side device invite. Creates a single-use invite code
|
|
211
219
|
* and sends it to Device B over the E2EE channel. Device B redeems it
|
|
212
220
|
* independently via HTTP — Device A can go offline after this.
|
|
221
|
+
*
|
|
222
|
+
* @param client Authenticated REST client.
|
|
223
|
+
* @param masterPublicKey Approver's account-level Ed25519 public key (base64url).
|
|
224
|
+
* Sent to Device B so it can adopt the master's identity doc.
|
|
213
225
|
*/
|
|
214
|
-
async approveWithInvite(client: AbracadabraClient): Promise<PairingResult> {
|
|
226
|
+
async approveWithInvite(client: AbracadabraClient, masterPublicKey?: string): Promise<PairingResult> {
|
|
215
227
|
if (this.role !== "approver") {
|
|
216
228
|
return { success: false, error: "Only the approver can approve" };
|
|
217
229
|
}
|
|
@@ -224,7 +236,7 @@ export class DevicePairingChannel extends EventEmitter {
|
|
|
224
236
|
|
|
225
237
|
try {
|
|
226
238
|
const { code } = await client.createDeviceInvite();
|
|
227
|
-
this.sendMessage({ type: "pair-invite-code", code });
|
|
239
|
+
this.sendMessage({ type: "pair-invite-code", code, masterPublicKey });
|
|
228
240
|
this._pendingRequest = null;
|
|
229
241
|
this.emit("pairingComplete", { success: true } as PairingResult);
|
|
230
242
|
return { success: true };
|
|
@@ -462,7 +474,7 @@ export class DevicePairingChannel extends EventEmitter {
|
|
|
462
474
|
|
|
463
475
|
case "pair-approved":
|
|
464
476
|
if (this.role !== "requester") return;
|
|
465
|
-
this.emit("approved");
|
|
477
|
+
this.emit("approved", { masterPublicKey: msg.masterPublicKey });
|
|
466
478
|
this.emit("pairingComplete", { success: true } as PairingResult);
|
|
467
479
|
break;
|
|
468
480
|
|
|
@@ -477,7 +489,7 @@ export class DevicePairingChannel extends EventEmitter {
|
|
|
477
489
|
|
|
478
490
|
case "pair-invite-code":
|
|
479
491
|
if (this.role !== "requester") return;
|
|
480
|
-
this.emit("inviteCode", msg.code);
|
|
492
|
+
this.emit("inviteCode", msg.code, msg.masterPublicKey);
|
|
481
493
|
break;
|
|
482
494
|
}
|
|
483
495
|
}
|