@nopeek/chat 0.1.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.
@@ -0,0 +1,471 @@
1
+ /** Secrets that can unlock an encrypted history backup. Either one is sufficient. */
2
+ export interface BackupSecrets {
3
+ password?: string;
4
+ recoveryCode?: string;
5
+ /** When rotating the password, the old one — used only to unwrap the existing
6
+ * backup envelope so unrelated wraps (e.g. the recovery code) survive. */
7
+ previousPassword?: string;
8
+ }
9
+ /** Descriptor returned by uploadEncrypted / expected by downloadDecrypt. */
10
+ export interface EncryptedBlobRef {
11
+ blobUrl: string;
12
+ contentKey: string;
13
+ iv: string;
14
+ size: number;
15
+ }
16
+ export interface AttachmentInput {
17
+ /** Raw file bytes. */
18
+ bytes: ArrayBuffer;
19
+ name: string;
20
+ contentType: string;
21
+ width?: number;
22
+ height?: number;
23
+ durationSec?: number;
24
+ /** Optional precomputed thumbnail bytes (e.g. a downscaled image/video frame). */
25
+ thumbnail?: {
26
+ bytes: ArrayBuffer;
27
+ contentType: string;
28
+ };
29
+ }
30
+ /** One tappable action a bot offers (inline under a message, or in its bar). */
31
+ export interface BotAction {
32
+ /** Stable id echoed back verbatim in the action_invoke body. */
33
+ id: string;
34
+ /** Button label shown to humans. */
35
+ label: string;
36
+ /** Optional visual emphasis; clients default to a neutral chip. */
37
+ style?: "default" | "primary" | "danger";
38
+ }
39
+ export interface ConnectOptions {
40
+ apiUrl: string;
41
+ sessionToken: string;
42
+ appId: string;
43
+ userId: string;
44
+ /** Persist device identity + channel keys. Defaults to localStorage when available. */
45
+ storage?: KeyValueStore;
46
+ platform?: "web" | "ios" | "android" | "desktop" | "server";
47
+ autoConnectWs?: boolean;
48
+ /**
49
+ * Don't register a brand-new device during connect() when no local device
50
+ * identity exists yet. Use this on login flows that may RESTORE the user's
51
+ * real device identity from an encrypted backup — registering first would
52
+ * orphan one device per fresh login (device proliferation), and orphan
53
+ * devices poison MLS key-package claims for every peer. After connect():
54
+ * - if a backup exists, call restore() — it adopts the backed-up deviceId
55
+ * and keys, then registers key packages and opens the WebSocket;
56
+ * - otherwise call registerDevice() to create a genuinely new device.
57
+ * When this flag is set and no local device exists, the WebSocket is NOT
58
+ * connected until one of those two completes (it needs a deviceId).
59
+ */
60
+ deferDeviceRegistration?: boolean;
61
+ /**
62
+ * Preshared-key mode. When supplied, the SDK derives each channel's key from
63
+ * this function instead of running the MLS welcome ceremony — every device
64
+ * that can compute the same key can read the channel, with no per-device
65
+ * key distribution. Messages are still encrypted end-to-end and the server
66
+ * still only ever sees ciphertext. Intended for closed groups where all
67
+ * members share a secret out of band (and for the hosted two-user demo).
68
+ */
69
+ deriveChannelKey?: (channelId: string) => Promise<CryptoKey>;
70
+ }
71
+ export interface KeyValueStore {
72
+ get(key: string): string | null | Promise<string | null>;
73
+ set(key: string, value: string): void | Promise<void>;
74
+ }
75
+ export interface DecryptedMessage {
76
+ messageId: string;
77
+ channelId: string;
78
+ senderUserId: string;
79
+ seq: number;
80
+ threadParentId: string | null;
81
+ createdAt: string;
82
+ editedAt: string | null;
83
+ recalledAt: string | null;
84
+ /** Decrypted (E2EE) or plaintext body; null when recalled or undecryptable. */
85
+ body: {
86
+ type: string;
87
+ text?: string;
88
+ [k: string]: unknown;
89
+ } | null;
90
+ encrypted: boolean;
91
+ decryptionFailed?: boolean;
92
+ }
93
+ type Listener = (...args: never[]) => void;
94
+ declare class Emitter {
95
+ private listeners;
96
+ on(event: string, fn: (...args: never[]) => void): () => void;
97
+ off(event: string, fn: Listener): void;
98
+ emit(event: string, ...args: unknown[]): void;
99
+ }
100
+ export declare class NoPeek extends Emitter {
101
+ readonly apiUrl: string;
102
+ readonly appId: string;
103
+ readonly userId: string;
104
+ deviceId: string;
105
+ private token;
106
+ private store;
107
+ private keys;
108
+ private ws;
109
+ private reqCounter;
110
+ private pending;
111
+ private channelKeys;
112
+ private mlsGroupToChannel;
113
+ /** Latest known presence per user, updated on every presence frame (incl. the
114
+ * connect-time snapshot that may arrive before app listeners attach). */
115
+ private presenceState;
116
+ private reconnectDelay;
117
+ private closed;
118
+ /** Set while the app is backgrounded: the WS is intentionally dropped so the
119
+ * server clears presence and delivers pushes instead. Distinct from `closed`
120
+ * (permanent) — a suspended client reconnects on resume(). */
121
+ private suspended;
122
+ private pingTimer;
123
+ private platform;
124
+ private autoWs;
125
+ private deferRegistration;
126
+ /** Set when connect() had to register a brand-new device — restore() revokes it
127
+ * if the backup turns out to hold the user's real device identity. */
128
+ private justRegisteredDeviceId;
129
+ readonly channels: Channels;
130
+ readonly deriveChannelKey?: (channelId: string) => Promise<CryptoKey>;
131
+ static connect(opts: ConnectOptions): Promise<NoPeek>;
132
+ private constructor();
133
+ /** Ensure a channel key exists via the preshared-key hook; returns false if no hook. */
134
+ deriveAndSet(channelId: string): Promise<boolean>;
135
+ api<T = unknown>(method: string, path: string, body?: unknown): Promise<T>;
136
+ private ensureDevice;
137
+ /** Whether this client has a server-registered device identity yet. False only
138
+ * during a deferred connect, before restore()/registerDevice() completes. */
139
+ get deviceRegistered(): boolean;
140
+ /**
141
+ * Complete a deferred connect by registering a brand-new device. Call this
142
+ * only when the user has NO restorable backup (genuine new user/device) —
143
+ * otherwise call restore(), which adopts the backed-up device identity.
144
+ * No-op when a device identity already exists. Publishes key packages and
145
+ * opens the WebSocket (unless autoConnectWs was disabled).
146
+ */
147
+ registerDevice(): Promise<void>;
148
+ /** POST the current keypair as a new device and persist the identity locally. */
149
+ private registerDeviceNow;
150
+ private persistDevice;
151
+ private persistChannelKeys;
152
+ private ensureKeyPackages;
153
+ connectWs(): Promise<void>;
154
+ /** Heartbeat: keep the socket alive while foregrounded so the server's idle
155
+ * timeout only fires once the client actually stops pinging (backgrounded /
156
+ * crashed / lost network), at which point presence clears and pushes resume. */
157
+ private startPing;
158
+ private stopPing;
159
+ /** Drop the WS when the app goes to the background (native): the server clears
160
+ * presence immediately and routes new messages to APNs/FCM push instead of a
161
+ * socket that iOS is about to freeze. Safe to call repeatedly. */
162
+ suspend(): void;
163
+ /** Reconnect when the app returns to the foreground. */
164
+ resume(): void;
165
+ close(): void;
166
+ sendFrame(frame: Record<string, unknown>): Promise<unknown>;
167
+ private handleFrame;
168
+ private handleWelcome;
169
+ /** Fetch any welcomes we missed while offline. */
170
+ syncChannelKey(channelId: string, mlsGroupId: string): Promise<boolean>;
171
+ getChannelKey(channelId: string): CryptoKey | null;
172
+ /** How many channel keys this device currently holds (for backup-freshness checks). */
173
+ get channelKeyCount(): number;
174
+ /** Encrypt bytes under a fresh content key and upload the ciphertext to S3. */
175
+ uploadEncrypted(bytes: ArrayBuffer): Promise<EncryptedBlobRef>;
176
+ /**
177
+ * Enable/refresh an encrypted key backup so the user can restore their chats
178
+ * on a new device. Back up your channel keys + device identity under a key
179
+ * derived from `recoveryCode` (which the user keeps; NoPeek never sees it).
180
+ * Call `generateRecoveryCode()` to make one, show it to the user ONCE, then
181
+ * pass it here. Returns the backupId.
182
+ */
183
+ /**
184
+ * Encrypted history backup. The chat payload is encrypted with a random data
185
+ * key, which is then WRAPPED separately by each provided secret — so the same
186
+ * backup can be unlocked by the account **password** OR the **recovery code**.
187
+ * This is what lets a user restore on a new device by just signing in with
188
+ * their password; the recovery code is only needed as a last resort (e.g. the
189
+ * password was reset). Accepts a string (treated as a recovery code, legacy)
190
+ * or `{ password?, recoveryCode? }`.
191
+ */
192
+ backup(secrets: BackupSecrets | string): Promise<string>;
193
+ /**
194
+ * Restore chats on a NEW device from the latest encrypted backup. Pass the
195
+ * account password (preferred) and/or the recovery code — whichever unlocks
196
+ * the backup is used. Rehydrates channel keys so server-stored history
197
+ * decrypts. Returns the number of channels restored.
198
+ */
199
+ restore(secrets: BackupSecrets | string): Promise<number>;
200
+ /** Cached escrow availability for THIS caller ({enabled, escrowPublicKey}). */
201
+ private escrowCfg;
202
+ /** Set by restoreViaEscrow(): the recovered raw data key (b64), so a follow-up
203
+ * backup() can preserve wraps it can't unlock (e.g. after a password reset). */
204
+ private escrowRestoredDK;
205
+ /** Whether the server escrows backup keys for this user's workspace (cached). */
206
+ private escrowConfig;
207
+ /**
208
+ * Recover chats with NO client-held secret, via server-side key escrow
209
+ * (workspace opt-in). The newest backup's `wraps.escrow` blob — the data key
210
+ * wrapped under the server's escrow PUBLIC key at backup time — is posted to
211
+ * the authenticated escrow-unwrap endpoint; the server decrypts it with the
212
+ * escrow PRIVATE key (Secrets Manager, never the DB) and returns the raw
213
+ * data key. The rest is identical to the password restore path.
214
+ *
215
+ * SECURITY: possession of a valid session is the gate. After a password
216
+ * reset, a session means the user proved email ownership via the emailed
217
+ * reset code — so "email owner → full recovery" is the EXPLICIT tradeoff of
218
+ * escrow mode. Strict (zero-custody) workspaces have no escrow wrap and the
219
+ * endpoint refuses them. Returns the number of channels restored.
220
+ */
221
+ restoreViaEscrow(): Promise<number>;
222
+ /**
223
+ * Adopt the device identity stored in a backup so a returning user on a fresh
224
+ * install ends up with EXACTLY their original deviceId — not a freshly minted
225
+ * one. Only applies when this client has no established local identity (a
226
+ * deferred connect, or an identity registered moments ago during this very
227
+ * connect, which is then revoked as an orphan). A long-standing local device
228
+ * identity is never hijacked — for those, restore() only rehydrates channel
229
+ * keys, exactly as before.
230
+ */
231
+ private adoptBackedUpDevice;
232
+ /** Whether this user has any restorable backup on the server. */
233
+ hasBackup(): Promise<boolean>;
234
+ /** Fetch an encrypted attachment blob and decrypt it back to bytes. */
235
+ downloadDecrypt(ref: {
236
+ blobUrl: string;
237
+ contentKey: string;
238
+ iv: string;
239
+ }): Promise<ArrayBuffer>;
240
+ /** App branding/theme tokens (colors, font, radius…) set by the customer. Null until loaded. */
241
+ branding: Record<string, unknown> | null;
242
+ /** Fetch the app's branding tokens (customer white-label theme). */
243
+ loadBranding(): Promise<Record<string, unknown> | null>;
244
+ /** Current known presence for a user (survives listener-attach timing). */
245
+ getPresence(userId: string): {
246
+ status: "online" | "offline";
247
+ lastSeenAt: string | null;
248
+ } | null;
249
+ isOnline(userId: string): boolean;
250
+ /** pollMessageId -> (userId -> selected optionIds). Latest vote wins. */
251
+ private pollVotes;
252
+ private recordPollVote;
253
+ /** Public entry so Channel.history() can fold in historical votes. */
254
+ applyPollVote(pollMessageId: string, userId: string, optionIds: string[]): void;
255
+ /** Aggregate results for a poll: { optionId -> count } plus total voters. */
256
+ pollResults(pollMessageId: string): {
257
+ counts: Record<string, number>;
258
+ voters: number;
259
+ };
260
+ myPollVote(pollMessageId: string): string[];
261
+ /** eventMessageId -> (userId -> "yes" | "no" | "maybe"). Latest response wins. */
262
+ private rsvps;
263
+ private recordRsvp;
264
+ /** Public entry so Channel.history() can fold in historical RSVPs. */
265
+ applyRsvp(eventMessageId: string, userId: string, response: "yes" | "no" | "maybe"): void;
266
+ /** Tally for an event: counts by response + the responding userIds per bucket. */
267
+ rsvpResults(eventMessageId: string): {
268
+ counts: {
269
+ yes: number;
270
+ no: number;
271
+ maybe: number;
272
+ };
273
+ voters: {
274
+ yes: string[];
275
+ no: string[];
276
+ maybe: string[];
277
+ };
278
+ };
279
+ myRsvp(eventMessageId: string): "yes" | "no" | "maybe" | null;
280
+ setChannelKey(channelId: string, key: CryptoKey): void;
281
+ decryptEnvelope(env: Record<string, unknown>): Promise<DecryptedMessage>;
282
+ }
283
+ export interface ChannelRecord {
284
+ channelId: string;
285
+ channelTypeKey: string;
286
+ kind: string;
287
+ e2ee: boolean;
288
+ name: string;
289
+ mlsGroupId: string | null;
290
+ memberCount: number;
291
+ [k: string]: unknown;
292
+ }
293
+ declare class Channels {
294
+ private np;
295
+ constructor(np: NoPeek);
296
+ list(): Promise<Channel[]>;
297
+ get(channelId: string): Promise<Channel>;
298
+ /**
299
+ * Create a channel. For E2EE channels this performs the full key ceremony:
300
+ * generate channel key → claim key packages for every member device →
301
+ * commit epoch 0→1 → send Welcome with the wrapped key to each device.
302
+ */
303
+ create(opts: {
304
+ channelTypeKey: string;
305
+ name?: string;
306
+ memberIds?: string[];
307
+ metadata?: Record<string, string>;
308
+ }): Promise<Channel>;
309
+ }
310
+ export declare class Channel {
311
+ private np;
312
+ record: ChannelRecord;
313
+ constructor(np: NoPeek, record: ChannelRecord);
314
+ get channelId(): string;
315
+ get e2ee(): boolean;
316
+ /** E2EE key ceremony (creator side). */
317
+ establishKeys(memberIds: string[]): Promise<void>;
318
+ /** Joiner side: derive (preshared mode) or pull the welcome if we lack the key. */
319
+ ensureKey(): Promise<boolean>;
320
+ /** Low-level: send an arbitrary structured payload (image, poll, contact…). */
321
+ sendPayload(payload: Record<string, unknown>, opts?: {
322
+ threadParentId?: string;
323
+ clientMessageId?: string;
324
+ }): Promise<DecryptedMessage>;
325
+ send(body: {
326
+ text?: string;
327
+ type?: string;
328
+ metadata?: Record<string, string>;
329
+ threadParentId?: string;
330
+ linkPreview?: Record<string, unknown>;
331
+ }): Promise<DecryptedMessage>;
332
+ /** Encrypt + upload a file and send it as an image/video/audio/file message. */
333
+ sendAttachment(a: AttachmentInput, opts?: {
334
+ caption?: string;
335
+ threadParentId?: string;
336
+ }): Promise<DecryptedMessage>;
337
+ /** Convenience wrapper for a browser File/Blob (uses .name/.type). */
338
+ sendFile(file: {
339
+ arrayBuffer(): Promise<ArrayBuffer>;
340
+ name?: string;
341
+ type?: string;
342
+ }, opts?: {
343
+ caption?: string;
344
+ thumbnail?: AttachmentInput["thumbnail"];
345
+ width?: number;
346
+ height?: number;
347
+ durationSec?: number;
348
+ }): Promise<DecryptedMessage>;
349
+ /** Download + decrypt an attachment; returns a Blob you can objectURL. */
350
+ fetchAttachment(att: {
351
+ blobUrl: string;
352
+ contentKey: string;
353
+ iv: string;
354
+ contentType?: string;
355
+ }): Promise<Blob>;
356
+ sendPoll(poll: {
357
+ question: string;
358
+ options: string[];
359
+ multiple?: boolean;
360
+ anonymous?: boolean;
361
+ closesAt?: string;
362
+ }): Promise<DecryptedMessage>;
363
+ /** Cast (or, with an empty array, retract) a vote on a poll message. */
364
+ votePoll(pollMessageId: string, optionIds: string[]): Promise<void>;
365
+ sendContact(contact: {
366
+ name: string;
367
+ organization?: string;
368
+ phones?: {
369
+ label?: string;
370
+ value: string;
371
+ }[];
372
+ emails?: {
373
+ label?: string;
374
+ value: string;
375
+ }[];
376
+ url?: string;
377
+ }): Promise<DecryptedMessage>;
378
+ sendCalendarEvent(event: {
379
+ title: string;
380
+ start: string;
381
+ end?: string;
382
+ location?: string;
383
+ description?: string;
384
+ allDay?: boolean;
385
+ url?: string;
386
+ organizer?: string;
387
+ }): Promise<DecryptedMessage>;
388
+ rsvp(eventMessageId: string, response: "yes" | "no" | "maybe"): Promise<void>;
389
+ sendLocation(lat: number, lng: number, label?: string): Promise<DecryptedMessage>;
390
+ /**
391
+ * Bot → humans: a message with tappable action buttons under the text
392
+ * (Telegram-style inline keyboard). Humans respond via invokeAction().
393
+ */
394
+ sendActions(opts: {
395
+ text?: string;
396
+ actions: BotAction[];
397
+ }): Promise<DecryptedMessage>;
398
+ /**
399
+ * Bot → humans: advertise (or replace) the bot's persistent quick-action
400
+ * bar for this chat. Clients render the LATEST action_bar per bot as chips
401
+ * above the composer; sending a new one supersedes the previous.
402
+ */
403
+ sendActionBar(opts: {
404
+ actions: BotAction[];
405
+ }): Promise<DecryptedMessage>;
406
+ /**
407
+ * Human → bot: what a tapped action button sends. `label` is optional
408
+ * display sugar so clients can echo "You ran <label>" without a lookup.
409
+ */
410
+ invokeAction(opts: {
411
+ actionId: string;
412
+ label?: string;
413
+ params?: Record<string, unknown>;
414
+ }): Promise<DecryptedMessage>;
415
+ edit(messageId: string, body: {
416
+ text: string;
417
+ }): Promise<void>;
418
+ recall(messageId: string): Promise<void>;
419
+ react(messageId: string, emoji: string, op?: "add" | "remove"): Promise<void>;
420
+ typing(isTyping: boolean): void;
421
+ markRead(messageId: string): Promise<void>;
422
+ history(opts?: {
423
+ beforeSeq?: number;
424
+ limit?: number;
425
+ }): Promise<DecryptedMessage[]>;
426
+ pollResults(pollMessageId: string): {
427
+ counts: Record<string, number>;
428
+ voters: number;
429
+ };
430
+ myPollVote(pollMessageId: string): string[];
431
+ rsvpResults(eventMessageId: string): {
432
+ counts: {
433
+ yes: number;
434
+ no: number;
435
+ maybe: number;
436
+ };
437
+ voters: {
438
+ yes: string[];
439
+ no: string[];
440
+ maybe: string[];
441
+ };
442
+ };
443
+ myRsvp(eventMessageId: string): "yes" | "no" | "maybe" | null;
444
+ on(event: "message" | "messageUpdated" | "messageRecalled" | "reaction" | "typing" | "receipt" | "pollVote" | "rsvp", fn: (payload: never) => void): () => void;
445
+ }
446
+ export { b64, deriveSharedChannelKey, generateRecoveryCode } from "./crypto.js";
447
+ /** Open the OS file picker. `accept` e.g. "image/*", "video/*", "*​/*". */
448
+ export declare function pickFiles(opts?: {
449
+ accept?: string;
450
+ multiple?: boolean;
451
+ capture?: "user" | "environment";
452
+ }): Promise<File[]>;
453
+ /** Pick images from the gallery. */
454
+ export declare const pickImages: (multiple?: boolean) => Promise<File[]>;
455
+ /** Pick a video. */
456
+ export declare const pickVideo: () => Promise<File[]>;
457
+ /** Open the rear camera to take a photo (mobile web). */
458
+ export declare const capturePhoto: () => Promise<File[]>;
459
+ /**
460
+ * Downscale an image File to a JPEG thumbnail (browser only). Returns bytes +
461
+ * intrinsic dimensions, suitable for channel.sendFile({ thumbnail, width, height }).
462
+ */
463
+ export declare function makeImageThumbnail(file: File, max?: number): Promise<{
464
+ thumbnail: {
465
+ bytes: ArrayBuffer;
466
+ contentType: string;
467
+ };
468
+ width: number;
469
+ height: number;
470
+ }>;
471
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}