@palbase/web 1.0.0 → 1.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.
- package/dist/analytics-facade-CAKBIH_U.d.cts +1302 -0
- package/dist/analytics-facade-DLH-KivI.d.ts +1302 -0
- package/dist/chunk-XVLR3HGD.js +6843 -0
- package/dist/chunk-XVLR3HGD.js.map +1 -0
- package/dist/index.cjs +3617 -187
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +208 -7
- package/dist/index.d.ts +208 -7
- package/dist/index.js +7 -1
- package/dist/internal.cjs +3613 -167
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.cts +5 -6
- package/dist/internal.d.ts +5 -6
- package/dist/internal.js +1 -1
- package/dist/next/client.cjs +3611 -177
- package/dist/next/client.cjs.map +1 -1
- package/dist/next/client.js +1 -1
- package/dist/next/index.cjs +3616 -170
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.d.cts +4 -11
- package/dist/next/index.d.ts +4 -11
- package/dist/next/index.js +14 -5
- package/dist/next/index.js.map +1 -1
- package/dist/{pb-Cudze7Kb.d.cts → pb-DioxNuEV.d.cts} +3 -1
- package/dist/{pb-BmgkAe97.d.ts → pb-HegMSSk-.d.ts} +3 -1
- package/dist/pkg/palbe_mls_bg.wasm +0 -0
- package/dist/react/index.cjs +97 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +30 -6
- package/dist/react/index.d.ts +30 -6
- package/dist/react/index.js +86 -1
- package/dist/react/index.js.map +1 -1
- package/package.json +8 -7
- package/dist/analytics-facade-DkOwkEpi.d.ts +0 -454
- package/dist/analytics-facade-t6UrFdn7.d.cts +0 -454
- package/dist/chunk-JVT65V4E.js +0 -3384
- package/dist/chunk-JVT65V4E.js.map +0 -1
|
@@ -0,0 +1,1302 @@
|
|
|
1
|
+
import { Room, ExternalE2EEKeyProvider } from 'livekit-client';
|
|
2
|
+
import { S as SessionStorageAdapter } from './storage-BPaeSG8K.js';
|
|
3
|
+
import { F } from './pooled-flags-Bwq4usn0.js';
|
|
4
|
+
|
|
5
|
+
declare class PalbaseError$1 extends Error {
|
|
6
|
+
readonly code: string;
|
|
7
|
+
readonly status: number;
|
|
8
|
+
readonly details?: unknown;
|
|
9
|
+
constructor(code: string, message: string, status: number, details?: unknown);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface PalbaseResponse$1<T> {
|
|
13
|
+
data: T | null;
|
|
14
|
+
error: PalbaseError$1 | null;
|
|
15
|
+
count?: number;
|
|
16
|
+
status: number;
|
|
17
|
+
}
|
|
18
|
+
interface HttpClientOptions$1 {
|
|
19
|
+
url?: string;
|
|
20
|
+
headers?: Record<string, string>;
|
|
21
|
+
}
|
|
22
|
+
interface RequestOptions$1 {
|
|
23
|
+
headers?: Record<string, string>;
|
|
24
|
+
body?: unknown;
|
|
25
|
+
signal?: AbortSignal;
|
|
26
|
+
}
|
|
27
|
+
interface Session$1 {
|
|
28
|
+
accessToken: string;
|
|
29
|
+
refreshToken: string;
|
|
30
|
+
expiresAt: number;
|
|
31
|
+
}
|
|
32
|
+
type AuthStateEvent$1 = 'SESSION_SET' | 'SESSION_CLEARED';
|
|
33
|
+
type AuthStateCallback$1 = (event: AuthStateEvent$1, session: Session$1 | null) => void;
|
|
34
|
+
type Unsubscribe$3 = () => void;
|
|
35
|
+
|
|
36
|
+
declare class TokenManager$1 {
|
|
37
|
+
private session;
|
|
38
|
+
private listeners;
|
|
39
|
+
private refreshPromise;
|
|
40
|
+
private refreshing;
|
|
41
|
+
refreshFunction: ((refreshToken: string) => Promise<Session$1>) | null;
|
|
42
|
+
setSession(session: Session$1): void;
|
|
43
|
+
getAccessToken(): string | null;
|
|
44
|
+
getRefreshToken(): string | null;
|
|
45
|
+
clearSession(): void;
|
|
46
|
+
isExpired(): boolean;
|
|
47
|
+
refreshSession(): Promise<void>;
|
|
48
|
+
onAuthStateChange(callback: AuthStateCallback$1): Unsubscribe$3;
|
|
49
|
+
private executeRefresh;
|
|
50
|
+
private notify;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Request interceptor. Runs before every HTTP request.
|
|
55
|
+
* Can modify headers, body, or reject the request.
|
|
56
|
+
*/
|
|
57
|
+
type RequestInterceptor$1 = (request: {
|
|
58
|
+
headers: Record<string, string>;
|
|
59
|
+
method: string;
|
|
60
|
+
path: string;
|
|
61
|
+
}) => void | Promise<void>;
|
|
62
|
+
declare class HttpClient$1 {
|
|
63
|
+
protected readonly apiKey: string;
|
|
64
|
+
protected readonly options?: HttpClientOptions$1;
|
|
65
|
+
tokenManager: TokenManager$1 | null;
|
|
66
|
+
/**
|
|
67
|
+
* Admin JWT used for platform admin endpoints (/admin/*).
|
|
68
|
+
* When set, takes precedence over tokenManager access token in the
|
|
69
|
+
* Authorization header.
|
|
70
|
+
*/
|
|
71
|
+
adminToken: string | null;
|
|
72
|
+
private readonly interceptors;
|
|
73
|
+
constructor(apiKey: string, options?: HttpClientOptions$1);
|
|
74
|
+
/** Set (or clear) the admin JWT used on admin endpoints. */
|
|
75
|
+
setAdminToken(token: string | null): void;
|
|
76
|
+
/**
|
|
77
|
+
* Create a scoped HttpClient that adds the given extra headers to every
|
|
78
|
+
* request. The returned client shares the admin token and token manager
|
|
79
|
+
* with the parent at runtime — later changes on the parent propagate to
|
|
80
|
+
* the scope and vice versa.
|
|
81
|
+
*
|
|
82
|
+
* Typical use: tagging admin calls with `x-palbase-project: <ref>` so the
|
|
83
|
+
* gateway can route them to the correct project's data plane.
|
|
84
|
+
*/
|
|
85
|
+
withHeaders(extra: Record<string, string>): HttpClient$1;
|
|
86
|
+
/** Add a request interceptor. Runs before every request. */
|
|
87
|
+
addInterceptor(interceptor: RequestInterceptor$1): void;
|
|
88
|
+
request<T>(method: string, path: string, options?: RequestOptions$1): Promise<PalbaseResponse$1<T>>;
|
|
89
|
+
private getBaseUrl;
|
|
90
|
+
private buildHeaders;
|
|
91
|
+
private executeWithRetry;
|
|
92
|
+
private delay;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
declare class PalbaseError extends Error {
|
|
96
|
+
readonly code: string;
|
|
97
|
+
readonly status: number;
|
|
98
|
+
readonly details?: unknown;
|
|
99
|
+
constructor(code: string, message: string, status: number, details?: unknown);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
interface PalbaseResponse<T> {
|
|
103
|
+
data: T | null;
|
|
104
|
+
error: PalbaseError | null;
|
|
105
|
+
count?: number;
|
|
106
|
+
status: number;
|
|
107
|
+
}
|
|
108
|
+
interface HttpClientOptions {
|
|
109
|
+
url?: string;
|
|
110
|
+
headers?: Record<string, string>;
|
|
111
|
+
}
|
|
112
|
+
interface RequestOptions {
|
|
113
|
+
headers?: Record<string, string>;
|
|
114
|
+
body?: unknown;
|
|
115
|
+
signal?: AbortSignal;
|
|
116
|
+
}
|
|
117
|
+
interface Session {
|
|
118
|
+
accessToken: string;
|
|
119
|
+
refreshToken: string;
|
|
120
|
+
expiresAt: number;
|
|
121
|
+
}
|
|
122
|
+
type AuthStateEvent = 'SESSION_SET' | 'SESSION_CLEARED';
|
|
123
|
+
type AuthStateCallback = (event: AuthStateEvent, session: Session | null) => void;
|
|
124
|
+
type Unsubscribe$2 = () => void;
|
|
125
|
+
|
|
126
|
+
declare class TokenManager {
|
|
127
|
+
private session;
|
|
128
|
+
private listeners;
|
|
129
|
+
private refreshPromise;
|
|
130
|
+
private refreshing;
|
|
131
|
+
refreshFunction: ((refreshToken: string) => Promise<Session>) | null;
|
|
132
|
+
setSession(session: Session): void;
|
|
133
|
+
getAccessToken(): string | null;
|
|
134
|
+
getRefreshToken(): string | null;
|
|
135
|
+
clearSession(): void;
|
|
136
|
+
isExpired(): boolean;
|
|
137
|
+
refreshSession(): Promise<void>;
|
|
138
|
+
onAuthStateChange(callback: AuthStateCallback): Unsubscribe$2;
|
|
139
|
+
private executeRefresh;
|
|
140
|
+
private notify;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Request interceptor. Runs before every HTTP request.
|
|
145
|
+
* Can modify headers, body, or reject the request.
|
|
146
|
+
*/
|
|
147
|
+
type RequestInterceptor = (request: {
|
|
148
|
+
headers: Record<string, string>;
|
|
149
|
+
method: string;
|
|
150
|
+
path: string;
|
|
151
|
+
}) => void | Promise<void>;
|
|
152
|
+
declare class HttpClient {
|
|
153
|
+
protected readonly apiKey: string;
|
|
154
|
+
protected readonly options?: HttpClientOptions;
|
|
155
|
+
tokenManager: TokenManager | null;
|
|
156
|
+
/**
|
|
157
|
+
* Admin JWT used for platform admin endpoints (/admin/*).
|
|
158
|
+
* When set, takes precedence over tokenManager access token in the
|
|
159
|
+
* Authorization header.
|
|
160
|
+
*/
|
|
161
|
+
adminToken: string | null;
|
|
162
|
+
private readonly interceptors;
|
|
163
|
+
constructor(apiKey: string, options?: HttpClientOptions);
|
|
164
|
+
/** Set (or clear) the admin JWT used on admin endpoints. */
|
|
165
|
+
setAdminToken(token: string | null): void;
|
|
166
|
+
/**
|
|
167
|
+
* Create a scoped HttpClient that adds the given extra headers to every
|
|
168
|
+
* request. The returned client shares the admin token and token manager
|
|
169
|
+
* with the parent at runtime — later changes on the parent propagate to
|
|
170
|
+
* the scope and vice versa.
|
|
171
|
+
*
|
|
172
|
+
* Typical use: tagging admin calls with `x-palbase-project: <ref>` so the
|
|
173
|
+
* gateway can route them to the correct project's data plane.
|
|
174
|
+
*/
|
|
175
|
+
withHeaders(extra: Record<string, string>): HttpClient;
|
|
176
|
+
/** Add a request interceptor. Runs before every request. */
|
|
177
|
+
addInterceptor(interceptor: RequestInterceptor): void;
|
|
178
|
+
request<T>(method: string, path: string, options?: RequestOptions): Promise<PalbaseResponse<T>>;
|
|
179
|
+
private getBaseUrl;
|
|
180
|
+
private buildHeaders;
|
|
181
|
+
private executeWithRetry;
|
|
182
|
+
private delay;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
interface User {
|
|
186
|
+
id: string;
|
|
187
|
+
email: string;
|
|
188
|
+
emailVerified: boolean;
|
|
189
|
+
createdAt: string;
|
|
190
|
+
updatedAt: string;
|
|
191
|
+
metadata?: Record<string, unknown>;
|
|
192
|
+
}
|
|
193
|
+
interface TokenResponse {
|
|
194
|
+
access_token: string;
|
|
195
|
+
refresh_token: string;
|
|
196
|
+
token_type: string;
|
|
197
|
+
expires_in: number;
|
|
198
|
+
}
|
|
199
|
+
interface AuthSession {
|
|
200
|
+
id: string;
|
|
201
|
+
ip?: string;
|
|
202
|
+
user_agent?: string;
|
|
203
|
+
acr: string;
|
|
204
|
+
amr: string[];
|
|
205
|
+
last_activity: string;
|
|
206
|
+
created_at: string;
|
|
207
|
+
current: boolean;
|
|
208
|
+
}
|
|
209
|
+
interface SignUpCredentials {
|
|
210
|
+
email: string;
|
|
211
|
+
password: string;
|
|
212
|
+
}
|
|
213
|
+
interface SignInCredentials {
|
|
214
|
+
email: string;
|
|
215
|
+
password: string;
|
|
216
|
+
}
|
|
217
|
+
interface VerifyEmailParams {
|
|
218
|
+
token?: string;
|
|
219
|
+
code?: string;
|
|
220
|
+
email?: string;
|
|
221
|
+
}
|
|
222
|
+
interface PasswordResetParams {
|
|
223
|
+
email: string;
|
|
224
|
+
}
|
|
225
|
+
interface PasswordResetConfirmParams {
|
|
226
|
+
token: string;
|
|
227
|
+
new_password: string;
|
|
228
|
+
}
|
|
229
|
+
interface PasswordChangeParams {
|
|
230
|
+
current_password: string;
|
|
231
|
+
new_password: string;
|
|
232
|
+
}
|
|
233
|
+
interface MFAEnrollParams {
|
|
234
|
+
type: 'totp' | 'email';
|
|
235
|
+
}
|
|
236
|
+
interface MFAEnrollResult {
|
|
237
|
+
enrollment_id?: string;
|
|
238
|
+
secret?: string;
|
|
239
|
+
otp_url?: string;
|
|
240
|
+
qr_code?: string;
|
|
241
|
+
recovery_codes?: string[];
|
|
242
|
+
status?: string;
|
|
243
|
+
}
|
|
244
|
+
interface MFAChallengeParams {
|
|
245
|
+
mfa_token: string;
|
|
246
|
+
type: 'totp' | 'email';
|
|
247
|
+
code: string;
|
|
248
|
+
}
|
|
249
|
+
interface MFARecoveryParams {
|
|
250
|
+
mfa_token: string;
|
|
251
|
+
code: string;
|
|
252
|
+
}
|
|
253
|
+
interface MFAFactor {
|
|
254
|
+
id: string;
|
|
255
|
+
type: string;
|
|
256
|
+
verified: boolean;
|
|
257
|
+
created_at: string;
|
|
258
|
+
}
|
|
259
|
+
interface MFAEmailChallengeParams {
|
|
260
|
+
mfa_token: string;
|
|
261
|
+
}
|
|
262
|
+
interface MFAEmailVerifyParams {
|
|
263
|
+
mfa_token: string;
|
|
264
|
+
code: string;
|
|
265
|
+
}
|
|
266
|
+
interface OAuthOptions {
|
|
267
|
+
provider: string;
|
|
268
|
+
redirectTo?: string;
|
|
269
|
+
}
|
|
270
|
+
interface Identity {
|
|
271
|
+
id: string;
|
|
272
|
+
provider: string;
|
|
273
|
+
provider_user_id: string;
|
|
274
|
+
created_at: string;
|
|
275
|
+
}
|
|
276
|
+
interface CredentialExchangeParams {
|
|
277
|
+
provider: string;
|
|
278
|
+
credential: string;
|
|
279
|
+
}
|
|
280
|
+
interface LinkIdentityParams {
|
|
281
|
+
provider: string;
|
|
282
|
+
credential: string;
|
|
283
|
+
}
|
|
284
|
+
interface MagicLinkParams {
|
|
285
|
+
email: string;
|
|
286
|
+
}
|
|
287
|
+
interface MagicLinkVerifyParams {
|
|
288
|
+
token: string;
|
|
289
|
+
fingerprint_hash?: string;
|
|
290
|
+
}
|
|
291
|
+
interface RegisterTrustedDeviceParams {
|
|
292
|
+
fingerprint_hash: string;
|
|
293
|
+
device_name?: string;
|
|
294
|
+
}
|
|
295
|
+
interface TrustedDevice {
|
|
296
|
+
id: string;
|
|
297
|
+
device_name?: string;
|
|
298
|
+
created_at: string;
|
|
299
|
+
last_used_at: string;
|
|
300
|
+
expires_at: string;
|
|
301
|
+
}
|
|
302
|
+
interface DeviceInfo {
|
|
303
|
+
id: string;
|
|
304
|
+
platform: string;
|
|
305
|
+
attestation_status: string;
|
|
306
|
+
bound: boolean;
|
|
307
|
+
created_at: string;
|
|
308
|
+
}
|
|
309
|
+
interface AttestAndroidParams {
|
|
310
|
+
verdict_token: string;
|
|
311
|
+
}
|
|
312
|
+
interface AttestAndroidResult {
|
|
313
|
+
device_id: string;
|
|
314
|
+
attestation_status: string;
|
|
315
|
+
device_integrity?: string;
|
|
316
|
+
}
|
|
317
|
+
interface AttestiOSParams {
|
|
318
|
+
attestation_object: string;
|
|
319
|
+
key_id: string;
|
|
320
|
+
challenge: string;
|
|
321
|
+
}
|
|
322
|
+
interface AttestiOSResult {
|
|
323
|
+
device_id: string;
|
|
324
|
+
attestation_status: string;
|
|
325
|
+
}
|
|
326
|
+
interface BindDeviceParams {
|
|
327
|
+
device_id: string;
|
|
328
|
+
public_key: string;
|
|
329
|
+
platform_attestation?: string;
|
|
330
|
+
}
|
|
331
|
+
interface VerifyRequestSignatureParams {
|
|
332
|
+
payload: string;
|
|
333
|
+
signature: string;
|
|
334
|
+
}
|
|
335
|
+
type AuthEvent = 'SIGNED_IN' | 'SIGNED_OUT' | 'TOKEN_REFRESHED';
|
|
336
|
+
type AuthStateChangeCallback = (event: AuthEvent, session: Session | null) => void;
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Device attestation client.
|
|
340
|
+
* Handles device challenge/attestation/bind and App Check JWT cache.
|
|
341
|
+
*/
|
|
342
|
+
declare class DeviceClient {
|
|
343
|
+
private readonly httpClient;
|
|
344
|
+
private cachedToken;
|
|
345
|
+
private refreshTimer;
|
|
346
|
+
constructor(httpClient: HttpClient);
|
|
347
|
+
/** Generate a device attestation challenge. */
|
|
348
|
+
generateChallenge(): Promise<PalbaseResponse<{
|
|
349
|
+
challenge: string;
|
|
350
|
+
}>>;
|
|
351
|
+
/** Attest an Android device with a Play Integrity verdict token. */
|
|
352
|
+
attestAndroid(params: AttestAndroidParams): Promise<PalbaseResponse<AttestAndroidResult>>;
|
|
353
|
+
/** Attest an iOS device with App Attest attestation data. */
|
|
354
|
+
attestiOS(params: AttestiOSParams): Promise<PalbaseResponse<AttestiOSResult>>;
|
|
355
|
+
/** Bind a verified device with a public key for request signing. */
|
|
356
|
+
bind(params: BindDeviceParams): Promise<PalbaseResponse<{
|
|
357
|
+
success: boolean;
|
|
358
|
+
}>>;
|
|
359
|
+
/** List all devices for the current user. */
|
|
360
|
+
list(): Promise<PalbaseResponse<{
|
|
361
|
+
devices: DeviceInfo[];
|
|
362
|
+
}>>;
|
|
363
|
+
/** Delete a device by ID. */
|
|
364
|
+
delete(deviceId: string): Promise<PalbaseResponse<{
|
|
365
|
+
success: boolean;
|
|
366
|
+
}>>;
|
|
367
|
+
/**
|
|
368
|
+
* Verify a request signature from a device (server-only).
|
|
369
|
+
* Should NOT be exposed in client SDK.
|
|
370
|
+
*/
|
|
371
|
+
verifyRequestSignature(deviceId: string, params: VerifyRequestSignatureParams): Promise<PalbaseResponse<{
|
|
372
|
+
verified: boolean;
|
|
373
|
+
}>>;
|
|
374
|
+
/** Get the cached App Check token, or null if not available / expired. */
|
|
375
|
+
getToken(): string | null;
|
|
376
|
+
/** Whether App Check is active (token cached and not expired). */
|
|
377
|
+
get isActive(): boolean;
|
|
378
|
+
/** Set a cached App Check token manually (e.g. after attest flow). */
|
|
379
|
+
setCachedToken(token: string, expiresInMs: number): void;
|
|
380
|
+
/** Clean up timers and cached state. */
|
|
381
|
+
dispose(): void;
|
|
382
|
+
private scheduleRefresh;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/** Reserved for future user-scope options. Admin surface is in @palbase/server. */
|
|
386
|
+
type AuthClientOptions = Record<string, never>;
|
|
387
|
+
declare class AuthClient {
|
|
388
|
+
private readonly httpClient;
|
|
389
|
+
private readonly tokenManager;
|
|
390
|
+
private readonly apiKey;
|
|
391
|
+
private readonly baseUrl;
|
|
392
|
+
private currentSession;
|
|
393
|
+
private hasSession;
|
|
394
|
+
private _mfa;
|
|
395
|
+
/** Device attestation */
|
|
396
|
+
readonly device: DeviceClient;
|
|
397
|
+
constructor(httpClient: HttpClient, tokenManager: TokenManager, apiKey?: string, baseUrl?: string, _options?: AuthClientOptions);
|
|
398
|
+
signUp(credentials: SignUpCredentials): Promise<PalbaseResponse<{
|
|
399
|
+
user: User;
|
|
400
|
+
session: Session;
|
|
401
|
+
}>>;
|
|
402
|
+
signIn(credentials: SignInCredentials): Promise<PalbaseResponse<{
|
|
403
|
+
user: User;
|
|
404
|
+
session: Session;
|
|
405
|
+
}>>;
|
|
406
|
+
signOut(): Promise<PalbaseResponse<void>>;
|
|
407
|
+
verifyEmail(params: VerifyEmailParams): Promise<PalbaseResponse<{
|
|
408
|
+
status: string;
|
|
409
|
+
}>>;
|
|
410
|
+
resendVerification(email: string): Promise<PalbaseResponse<{
|
|
411
|
+
verification_token?: string;
|
|
412
|
+
verification_code?: string;
|
|
413
|
+
}>>;
|
|
414
|
+
requestPasswordReset(params: PasswordResetParams): Promise<PalbaseResponse<{
|
|
415
|
+
success: boolean;
|
|
416
|
+
}>>;
|
|
417
|
+
confirmPasswordReset(params: PasswordResetConfirmParams): Promise<PalbaseResponse<{
|
|
418
|
+
success: boolean;
|
|
419
|
+
}>>;
|
|
420
|
+
changePassword(params: PasswordChangeParams): Promise<PalbaseResponse<{
|
|
421
|
+
success: boolean;
|
|
422
|
+
}>>;
|
|
423
|
+
refresh(): Promise<PalbaseResponse<TokenResponse>>;
|
|
424
|
+
getAccessToken(): string | null;
|
|
425
|
+
onTokenChange(callback: (tokens: {
|
|
426
|
+
accessToken: string | null;
|
|
427
|
+
refreshToken: string | null;
|
|
428
|
+
}) => void): () => void;
|
|
429
|
+
setTokens(accessToken: string, refreshToken: string, expiresIn?: number): void;
|
|
430
|
+
listSessions(): Promise<PalbaseResponse<AuthSession[]>>;
|
|
431
|
+
revokeSession(sessionId: string): Promise<PalbaseResponse<void>>;
|
|
432
|
+
revokeAllSessions(): Promise<PalbaseResponse<void>>;
|
|
433
|
+
get mfa(): {
|
|
434
|
+
enroll: (params: MFAEnrollParams) => Promise<PalbaseResponse<MFAEnrollResult>>;
|
|
435
|
+
verifyEnrollment: (code: string) => Promise<PalbaseResponse<{
|
|
436
|
+
status: string;
|
|
437
|
+
}>>;
|
|
438
|
+
challenge: (params: MFAChallengeParams) => Promise<PalbaseResponse<TokenResponse>>;
|
|
439
|
+
recovery: (params: MFARecoveryParams) => Promise<PalbaseResponse<TokenResponse>>;
|
|
440
|
+
listFactors: () => Promise<PalbaseResponse<{
|
|
441
|
+
factors: MFAFactor[];
|
|
442
|
+
}>>;
|
|
443
|
+
removeFactor: (factorId: string, currentPassword: string) => Promise<PalbaseResponse<{
|
|
444
|
+
status: string;
|
|
445
|
+
}>>;
|
|
446
|
+
regenerateRecoveryCodes: () => Promise<PalbaseResponse<{
|
|
447
|
+
recovery_codes: string[];
|
|
448
|
+
}>>;
|
|
449
|
+
emailEnroll: () => Promise<PalbaseResponse<{
|
|
450
|
+
status: string;
|
|
451
|
+
}>>;
|
|
452
|
+
emailChallenge: (params: MFAEmailChallengeParams) => Promise<PalbaseResponse<{
|
|
453
|
+
status: string;
|
|
454
|
+
}>>;
|
|
455
|
+
emailVerify: (params: MFAEmailVerifyParams) => Promise<PalbaseResponse<TokenResponse>>;
|
|
456
|
+
};
|
|
457
|
+
private buildMfa;
|
|
458
|
+
getOAuthURL(options: OAuthOptions): Promise<PalbaseResponse<{
|
|
459
|
+
url: string;
|
|
460
|
+
}>>;
|
|
461
|
+
signInWithCredential(params: CredentialExchangeParams): Promise<PalbaseResponse<{
|
|
462
|
+
user: User;
|
|
463
|
+
session: Session;
|
|
464
|
+
}>>;
|
|
465
|
+
listIdentities(): Promise<PalbaseResponse<{
|
|
466
|
+
identities: Identity[];
|
|
467
|
+
}>>;
|
|
468
|
+
linkIdentity(params: LinkIdentityParams): Promise<PalbaseResponse<{
|
|
469
|
+
success: boolean;
|
|
470
|
+
}>>;
|
|
471
|
+
unlinkIdentity(identityId: string): Promise<PalbaseResponse<{
|
|
472
|
+
success: boolean;
|
|
473
|
+
}>>;
|
|
474
|
+
requestMagicLink(params: MagicLinkParams): Promise<PalbaseResponse<{
|
|
475
|
+
success: boolean;
|
|
476
|
+
}>>;
|
|
477
|
+
verifyMagicLink(params: MagicLinkVerifyParams): Promise<PalbaseResponse<{
|
|
478
|
+
user: User;
|
|
479
|
+
session: Session;
|
|
480
|
+
}>>;
|
|
481
|
+
listTrustedDevices(): Promise<PalbaseResponse<{
|
|
482
|
+
trusted_devices: TrustedDevice[];
|
|
483
|
+
}>>;
|
|
484
|
+
registerTrustedDevice(params: RegisterTrustedDeviceParams): Promise<PalbaseResponse<{
|
|
485
|
+
trusted_device_token: string;
|
|
486
|
+
}>>;
|
|
487
|
+
revokeTrustedDevice(deviceId: string): Promise<PalbaseResponse<{
|
|
488
|
+
success: boolean;
|
|
489
|
+
}>>;
|
|
490
|
+
getSession(): {
|
|
491
|
+
data: Session | null;
|
|
492
|
+
error: null;
|
|
493
|
+
};
|
|
494
|
+
onAuthStateChange(callback: AuthStateChangeCallback): {
|
|
495
|
+
data: {
|
|
496
|
+
subscription: {
|
|
497
|
+
unsubscribe: () => void;
|
|
498
|
+
};
|
|
499
|
+
};
|
|
500
|
+
};
|
|
501
|
+
/**
|
|
502
|
+
* Verify a user's JWT token by calling GET /auth/user with their token.
|
|
503
|
+
* Server-only — should NOT be exposed in client SDK.
|
|
504
|
+
*/
|
|
505
|
+
verifyUserToken(jwt: string): Promise<PalbaseResponse<User>>;
|
|
506
|
+
private setSessionAndWireRefresh;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
type CallState = 'connecting' | 'active' | 'ended';
|
|
510
|
+
interface CallParticipant {
|
|
511
|
+
identity: string;
|
|
512
|
+
isSpeaking: boolean;
|
|
513
|
+
audioMuted: boolean;
|
|
514
|
+
videoEnabled: boolean;
|
|
515
|
+
/** The live <video> element for this participant, or null before track arrives. */
|
|
516
|
+
videoElement: HTMLVideoElement | null;
|
|
517
|
+
/** The live <audio> element for this participant, or null before track arrives. */
|
|
518
|
+
audioElement: HTMLAudioElement | null;
|
|
519
|
+
}
|
|
520
|
+
type CallChangeCallback = (call: Call) => void;
|
|
521
|
+
/**
|
|
522
|
+
* A live call session. Obtain via `pb.calls.start()` or `pb.calls.accept()`.
|
|
523
|
+
*
|
|
524
|
+
* Lifecycle:
|
|
525
|
+
* connecting → active (room joined, tracks flowing)
|
|
526
|
+
* active → ended (leave() / remote disconnect)
|
|
527
|
+
*
|
|
528
|
+
* Subscribe to changes via `call.subscribe(cb)` which fires on state or
|
|
529
|
+
* participant changes (mirrors flags `onChange` / realtime `on` pattern).
|
|
530
|
+
*/
|
|
531
|
+
declare class Call {
|
|
532
|
+
readonly id: string;
|
|
533
|
+
private _state;
|
|
534
|
+
private readonly _participants;
|
|
535
|
+
private readonly _listeners;
|
|
536
|
+
private readonly _room;
|
|
537
|
+
private readonly _keyProvider;
|
|
538
|
+
/** @internal — obtain via PalbeCalls.start() / .accept() */
|
|
539
|
+
constructor(callId: string, room: Room, keyProvider: ExternalE2EEKeyProvider);
|
|
540
|
+
get state(): CallState;
|
|
541
|
+
/** Snapshot of current remote participants (does NOT include the local participant). */
|
|
542
|
+
get participants(): readonly CallParticipant[];
|
|
543
|
+
get localParticipant(): Room['localParticipant'];
|
|
544
|
+
/**
|
|
545
|
+
* Subscribe to call changes (state + participant updates).
|
|
546
|
+
* Returns an `Unsubscribe` function — matches the SDK's flags/auth pattern.
|
|
547
|
+
*/
|
|
548
|
+
subscribe(callback: CallChangeCallback): Unsubscribe;
|
|
549
|
+
/** Mute / unmute the local microphone. */
|
|
550
|
+
mute(on: boolean): Promise<void>;
|
|
551
|
+
/** Enable / disable the local camera. */
|
|
552
|
+
setCamera(on: boolean): Promise<void>;
|
|
553
|
+
/**
|
|
554
|
+
* Set a raw frame encryption key (ArrayBuffer) for this call.
|
|
555
|
+
* Design seam for SP-1.x web-MLS: call this with the MLS exporter secret
|
|
556
|
+
* to enable frame-level E2EE via ExternalE2EEKeyProvider.
|
|
557
|
+
*
|
|
558
|
+
* NOTE: The room must have been opened with `e2ee` options for this to take
|
|
559
|
+
* effect. Currently calls connect WITHOUT e2ee — see module docstring.
|
|
560
|
+
*
|
|
561
|
+
* TODO(SP-1-web): wire this to MLS-derived key on session join.
|
|
562
|
+
*/
|
|
563
|
+
setMediaKey(key: ArrayBuffer): Promise<void>;
|
|
564
|
+
/** Leave the call and disconnect from the LiveKit room. */
|
|
565
|
+
leave(): Promise<void>;
|
|
566
|
+
private _setState;
|
|
567
|
+
private _emit;
|
|
568
|
+
private _upsertParticipant;
|
|
569
|
+
private _attachTrack;
|
|
570
|
+
private _wireRoomEvents;
|
|
571
|
+
}
|
|
572
|
+
declare class PalbeCalls {
|
|
573
|
+
private readonly rt;
|
|
574
|
+
constructor(rt: PalbeRuntime);
|
|
575
|
+
/**
|
|
576
|
+
* Start a new call in a messaging group.
|
|
577
|
+
*
|
|
578
|
+
* @param groupId - Messaging group display-id (`grp_<uuidv7>`)
|
|
579
|
+
* @param media - Which media tracks to publish (default: audio + video)
|
|
580
|
+
* @returns A `Call` in `connecting` state; transitions to `active` once LiveKit connects.
|
|
581
|
+
*
|
|
582
|
+
* @throws BackendError('network', { code: 'call_service_unavailable' }) if LiveKit SFU is down (503)
|
|
583
|
+
* @throws BackendError('forbidden', { code: 'not_group_member' }) if the caller is not a member (403)
|
|
584
|
+
* @throws BackendError('conflict', { code: 'call_room_full' }) if the room is full (409)
|
|
585
|
+
*/
|
|
586
|
+
start(groupId: string, { media }?: {
|
|
587
|
+
media?: Array<'audio' | 'video'>;
|
|
588
|
+
}): Promise<Call>;
|
|
589
|
+
/**
|
|
590
|
+
* Accept an incoming call in a messaging group.
|
|
591
|
+
*
|
|
592
|
+
* @param groupId - Messaging group display-id
|
|
593
|
+
* @param callId - Call identifier (from the push notification payload)
|
|
594
|
+
* @param media - Which media tracks to publish (default: audio + video)
|
|
595
|
+
*/
|
|
596
|
+
accept(groupId: string, callId: string, { media }?: {
|
|
597
|
+
media?: Array<'audio' | 'video'>;
|
|
598
|
+
}): Promise<Call>;
|
|
599
|
+
/**
|
|
600
|
+
* Decline an incoming call.
|
|
601
|
+
*
|
|
602
|
+
* @param groupId - Messaging group display-id
|
|
603
|
+
* @param callId - Call identifier
|
|
604
|
+
* @param reason - Optional decline reason string
|
|
605
|
+
*/
|
|
606
|
+
decline(groupId: string, callId: string, reason?: string): Promise<void>;
|
|
607
|
+
private _connect;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
interface PalbeOAuthConfig {
|
|
611
|
+
google?: {
|
|
612
|
+
enabled?: boolean;
|
|
613
|
+
clientId?: string;
|
|
614
|
+
};
|
|
615
|
+
apple?: {
|
|
616
|
+
enabled?: boolean;
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
/** Baked into palbe.gen.ts by `palbase web link` — the generated web config. */
|
|
620
|
+
interface PalbeConfig {
|
|
621
|
+
url: string;
|
|
622
|
+
apiKey: string;
|
|
623
|
+
/** Informational — url+apiKey are already branch-specific (endpointRef embeds the branch slug); gen bakes all three consistently. */
|
|
624
|
+
branch?: string;
|
|
625
|
+
oauth?: PalbeOAuthConfig;
|
|
626
|
+
/** Refresh-token persistence. Default: endpoint-scoped localStorage in browsers, memory elsewhere. */
|
|
627
|
+
storage?: SessionStorageAdapter;
|
|
628
|
+
/** Extra headers on every request. */
|
|
629
|
+
headers?: Record<string, string>;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/** Frozen view of all cached flag values (what `all()` returns / `changes()` yields). */
|
|
633
|
+
type FlagsView = Readonly<Record<string, F>>;
|
|
634
|
+
/**
|
|
635
|
+
* `pb.flags` — iOS-parity facade over `FlagsPool` (cache + delta polling +
|
|
636
|
+
* auth binding) and `FlagsClient` (stateless transport).
|
|
637
|
+
*
|
|
638
|
+
* Start semantics: the facade is constructed lazily (first `pb.flags` touch).
|
|
639
|
+
* - Browser: the pool starts right here in the constructor — cold snapshot +
|
|
640
|
+
* 30s delta polling + visibility pause. "First use starts the machinery"
|
|
641
|
+
* without per-method start checks.
|
|
642
|
+
* - Server (no `document`): NEVER auto-starts. `ready()`/`refresh()` are
|
|
643
|
+
* one-shot snapshot fetches with zero timers and zero storage access, so a
|
|
644
|
+
* pbServer request that reads flags pays exactly one HTTP call.
|
|
645
|
+
*
|
|
646
|
+
* localStorage persistence is scoped per endpoint ref (`palbe.flags.<ref>`),
|
|
647
|
+
* mirroring the session-storage key convention.
|
|
648
|
+
*/
|
|
649
|
+
declare class PalbeFlags {
|
|
650
|
+
private readonly transport;
|
|
651
|
+
private readonly pool;
|
|
652
|
+
constructor(rt: PalbeRuntime);
|
|
653
|
+
/** Resolves once the first snapshot (or persisted hydrate) is available. Auto-starts the pool. */
|
|
654
|
+
ready(): Promise<void>;
|
|
655
|
+
/** Force an immediate re-snapshot. */
|
|
656
|
+
refresh(): Promise<void>;
|
|
657
|
+
/** Frozen snapshot of all cached values (identity-stable until a change). */
|
|
658
|
+
all(): FlagsView;
|
|
659
|
+
/** Raw cached value for `key`, or `undefined` when not in the cache. */
|
|
660
|
+
get(key: string): F | undefined;
|
|
661
|
+
/** `true` only when the cached value is strictly `true`; `fallback` when the key is absent. */
|
|
662
|
+
isEnabled(key: string, fallback?: boolean): boolean;
|
|
663
|
+
/** Alias of {@link isEnabled} (iOS parity). */
|
|
664
|
+
bool(key: string, fallback?: boolean): boolean;
|
|
665
|
+
/** Cached value when it is a string, else `fallback`. */
|
|
666
|
+
getString(key: string, fallback: string): string;
|
|
667
|
+
/** Cached value when it is an integer number, else `fallback`. */
|
|
668
|
+
getInt(key: string, fallback: number): number;
|
|
669
|
+
/** Cached value when it is a number (integers included), else `fallback`. */
|
|
670
|
+
getDouble(key: string, fallback: number): number;
|
|
671
|
+
/**
|
|
672
|
+
* Resolve the multivariate variant for `key` — the variant name, or `null`
|
|
673
|
+
* when the flag has no variant (or the read fails).
|
|
674
|
+
*
|
|
675
|
+
* Wire failures (network errors, 404, etc.) resolve to `null`.
|
|
676
|
+
* Invalid flag names throw `BackendError('validation', { code: 'invalid_flag_name' })`.
|
|
677
|
+
*
|
|
678
|
+
* DEVIATION from iOS sync-cache parity: the platform does not propagate
|
|
679
|
+
* variant metadata into the user-flags snapshot/delta cache, so this is an
|
|
680
|
+
* ASYNC transport read (`GET /v1/flags/{key}/variant`), not a cache lookup.
|
|
681
|
+
*/
|
|
682
|
+
getVariant(key: string): Promise<string | null>;
|
|
683
|
+
/** Subscribe to any change in the cached flag set. */
|
|
684
|
+
onChange(callback: () => void): Unsubscribe;
|
|
685
|
+
/**
|
|
686
|
+
* Observe ONE key: fires only when that key's value actually changes
|
|
687
|
+
* (per {@link sameFlagValue} — structural compare for objects), with the
|
|
688
|
+
* new value (`undefined` = deleted). P5 React-hook substrate.
|
|
689
|
+
*/
|
|
690
|
+
subscribeKey(key: string, callback: (value: F | undefined) => void): Unsubscribe;
|
|
691
|
+
/**
|
|
692
|
+
* Async iteration over flag changes: yields the new {@link all} view on
|
|
693
|
+
* every pool change notification. The listener is detached when the
|
|
694
|
+
* consumer `break`s/`return`s/`throw`s — including while a `next()` is
|
|
695
|
+
* still pending (it resolves `{ done: true }` instead of hanging, which a
|
|
696
|
+
* plain async-generator `finally` would not guarantee).
|
|
697
|
+
*/
|
|
698
|
+
changes(): AsyncIterableIterator<FlagsView>;
|
|
699
|
+
/** Stop polling and detach all listeners (auth + visibility + subscribers). */
|
|
700
|
+
destroy(): void;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
/** A direct (1:1) chat or a multi-party group. */
|
|
704
|
+
type ChatKind = 'direct' | 'group';
|
|
705
|
+
/** A draft (local-only, not yet on the server) or an active (materialized) chat. */
|
|
706
|
+
type ChatState = 'draft' | 'active';
|
|
707
|
+
/** Server-side ACL role (group only; a direct chat has no roles). */
|
|
708
|
+
type ChatRole = 'owner' | 'admin' | 'member';
|
|
709
|
+
/** Whether a message was received (`incoming`) or sent by this device (`outgoing`). */
|
|
710
|
+
type MessageDirection = 'incoming' | 'outgoing';
|
|
711
|
+
/** A renderable message kind. `system` = a membership commit / control frame. */
|
|
712
|
+
type ChatMessageKind = 'text' | 'media' | 'system';
|
|
713
|
+
/** A participating USER (not a device). For a direct chat: `[me, peer]`. */
|
|
714
|
+
interface ChatMember {
|
|
715
|
+
/** == userId (stable identity). */
|
|
716
|
+
readonly id: string;
|
|
717
|
+
readonly userId: string;
|
|
718
|
+
readonly displayName: string | null;
|
|
719
|
+
readonly role: ChatRole;
|
|
720
|
+
readonly isSelf: boolean;
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* A resolved reply context — produced by `resolveReply` on the decode path.
|
|
724
|
+
* `state:'resolved'` means the parent was found in local history and `quoteText`
|
|
725
|
+
* is the REAL parent text (spoof-proof). `state:'unavailable'` means the parent
|
|
726
|
+
* was not in local history; `quoteText` is the embedded preview body (may be null).
|
|
727
|
+
*/
|
|
728
|
+
interface ResolvedReply {
|
|
729
|
+
readonly parentClientMsgId: string;
|
|
730
|
+
readonly state: 'resolved' | 'unavailable';
|
|
731
|
+
readonly quoteSenderUserId: string;
|
|
732
|
+
readonly quoteText: string | null;
|
|
733
|
+
readonly quoteKind: string;
|
|
734
|
+
}
|
|
735
|
+
/** One message in a chat transcript. */
|
|
736
|
+
interface ChatMessage {
|
|
737
|
+
/** Routing-key-free id: `<chat.id>#<serverSeq>`. */
|
|
738
|
+
readonly id: string;
|
|
739
|
+
readonly kind: ChatMessageKind;
|
|
740
|
+
readonly direction: MessageDirection;
|
|
741
|
+
/** The sending USER id, when resolved (nil for system frames or unknown sender). */
|
|
742
|
+
readonly senderUserId: string | null;
|
|
743
|
+
readonly text: string | null;
|
|
744
|
+
/** The server-minted per-group monotonic sequence (sort key + read cursor). */
|
|
745
|
+
readonly serverSeq: number;
|
|
746
|
+
/** When this device decoded (incoming) or sent (outgoing) the message. */
|
|
747
|
+
readonly sentAt: Date;
|
|
748
|
+
/** The client-minted idempotency id for this message (empty string for legacy/system). */
|
|
749
|
+
readonly clientMsgId: string;
|
|
750
|
+
/** Resolved reply context, or null if this is not a reply. */
|
|
751
|
+
readonly replyTo: ResolvedReply | null;
|
|
752
|
+
}
|
|
753
|
+
/** The receipt from a send — the server's monotonic sequence + accepted epoch. */
|
|
754
|
+
interface SentReceipt {
|
|
755
|
+
readonly serverSeq: number;
|
|
756
|
+
readonly epoch: number;
|
|
757
|
+
}
|
|
758
|
+
/** Per-user comms privacy prefs (defaults both-true). */
|
|
759
|
+
interface CommsPrefs {
|
|
760
|
+
readonly sharePresence: boolean;
|
|
761
|
+
readonly shareReceipts: boolean;
|
|
762
|
+
}
|
|
763
|
+
/** A presence snapshot for a user in a chat (60s TTL, device-union). */
|
|
764
|
+
interface PresenceState {
|
|
765
|
+
readonly userId: string;
|
|
766
|
+
readonly isOnline: boolean;
|
|
767
|
+
readonly lastSeenAt: Date | null;
|
|
768
|
+
}
|
|
769
|
+
/** An unsubscribe handle (matches the flags/realtime/auth pattern). */
|
|
770
|
+
type Unsubscribe$1 = () => void;
|
|
771
|
+
|
|
772
|
+
/** A resolved group as the SDK tracks it. `name` is always null on web (no exporter). */
|
|
773
|
+
interface MessagingGroup {
|
|
774
|
+
displayId: string;
|
|
775
|
+
rfcGroupId: string;
|
|
776
|
+
currentEpoch: number;
|
|
777
|
+
ownerUserId: string | null;
|
|
778
|
+
directKey: string | null;
|
|
779
|
+
name: string | null;
|
|
780
|
+
}
|
|
781
|
+
interface QuotePreview {
|
|
782
|
+
kind: string;
|
|
783
|
+
author_user_id: string;
|
|
784
|
+
body?: string;
|
|
785
|
+
body_truncated: boolean;
|
|
786
|
+
}
|
|
787
|
+
interface ReplyRef {
|
|
788
|
+
v: number;
|
|
789
|
+
client_msg_id: string;
|
|
790
|
+
preview?: QuotePreview;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
/** A decoded incoming message handed to chat listeners. */
|
|
794
|
+
interface IncomingMessage {
|
|
795
|
+
kind: 'application' | 'commit' | 'proposal' | 'welcome';
|
|
796
|
+
group: MessagingGroup;
|
|
797
|
+
text: string | null;
|
|
798
|
+
senderDeviceId: string | null;
|
|
799
|
+
epoch: number;
|
|
800
|
+
serverSeq: number;
|
|
801
|
+
receivedAt: Date;
|
|
802
|
+
/** The client-minted idempotency id from the decoded envelope (empty string for legacy/system). */
|
|
803
|
+
clientMsgId: string;
|
|
804
|
+
/** The decoded reply reference, if present in the envelope. */
|
|
805
|
+
replyRef: ReplyRef | null;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
/** The intended participants of a draft chat (held until the first send). */
|
|
809
|
+
interface ChatDraft {
|
|
810
|
+
mode: {
|
|
811
|
+
kind: 'direct';
|
|
812
|
+
peerUserId: string;
|
|
813
|
+
} | {
|
|
814
|
+
kind: 'group';
|
|
815
|
+
members: string[];
|
|
816
|
+
};
|
|
817
|
+
/** The reserved local id a draft shows before it materializes. */
|
|
818
|
+
reservedId: string;
|
|
819
|
+
}
|
|
820
|
+
/** The seam the Chat talks to for the work needing the resolved machinery. */
|
|
821
|
+
interface ChatBackend {
|
|
822
|
+
selfUserId: string;
|
|
823
|
+
/** Materialize a draft → the active group (DM get-or-create / group create+add). */
|
|
824
|
+
materialize(draft: ChatDraft): Promise<MessagingGroup>;
|
|
825
|
+
sendText(group: MessagingGroup, text: string, replyTo?: ReplyRef | null): Promise<{
|
|
826
|
+
receipt: SentReceipt;
|
|
827
|
+
clientMsgId: string;
|
|
828
|
+
}>;
|
|
829
|
+
history(group: MessagingGroup, limit: number, before?: number): Promise<ChatMessage[]>;
|
|
830
|
+
members(group: MessagingGroup): Promise<ChatMember[]>;
|
|
831
|
+
addMember(group: MessagingGroup, userId: string): Promise<void>;
|
|
832
|
+
removeMember(group: MessagingGroup, userId: string): Promise<void>;
|
|
833
|
+
leave(group: MessagingGroup): Promise<void>;
|
|
834
|
+
registerActive(group: MessagingGroup): void;
|
|
835
|
+
setTyping(group: MessagingGroup, isTyping: boolean): void;
|
|
836
|
+
markRead(group: MessagingGroup, upToServerSeq: number): Promise<void>;
|
|
837
|
+
/** Subscribe live message + conv (presence/typing/read) for an active group. */
|
|
838
|
+
subscribeLive(group: MessagingGroup, chat: Chat): Unsubscribe$1;
|
|
839
|
+
/** Resolve a sender device id → its owning user id (for senderUserId). */
|
|
840
|
+
userIdForDevice(group: MessagingGroup, deviceId: string): Promise<string | null>;
|
|
841
|
+
}
|
|
842
|
+
declare class Chat {
|
|
843
|
+
/** Stable, URL/log-safe id (the grp_ display id once active; a reserved local id while draft). */
|
|
844
|
+
id: string;
|
|
845
|
+
readonly kind: ChatKind;
|
|
846
|
+
private _state;
|
|
847
|
+
private _group;
|
|
848
|
+
private _draft;
|
|
849
|
+
private readonly backend;
|
|
850
|
+
private messageList;
|
|
851
|
+
private memberCache;
|
|
852
|
+
private typingList;
|
|
853
|
+
private presenceStates;
|
|
854
|
+
private readWatermark;
|
|
855
|
+
private titleOverride;
|
|
856
|
+
private readonly seenKeys;
|
|
857
|
+
/** Index: clientMsgId → { text, senderUserId } for resolveReply lookups. */
|
|
858
|
+
private readonly byClientMsgId;
|
|
859
|
+
private loadedEarliestSeq;
|
|
860
|
+
private historyLoaded;
|
|
861
|
+
private wired;
|
|
862
|
+
private liveUnsub;
|
|
863
|
+
private readonly listeners;
|
|
864
|
+
/** @internal — obtain via pb.messaging.directChat / groupChat / chat(id). */
|
|
865
|
+
constructor(args: {
|
|
866
|
+
group: MessagingGroup;
|
|
867
|
+
kind: ChatKind;
|
|
868
|
+
backend: ChatBackend;
|
|
869
|
+
} | {
|
|
870
|
+
draft: ChatDraft;
|
|
871
|
+
kind: ChatKind;
|
|
872
|
+
backend: ChatBackend;
|
|
873
|
+
});
|
|
874
|
+
/** Subscribe to any change in this chat (messages/members/typing/state). */
|
|
875
|
+
onChange(cb: () => void): Unsubscribe$1;
|
|
876
|
+
private emit;
|
|
877
|
+
get state(): ChatState;
|
|
878
|
+
get isDirect(): boolean;
|
|
879
|
+
get messages(): readonly ChatMessage[];
|
|
880
|
+
get members(): readonly ChatMember[];
|
|
881
|
+
get typing(): readonly ChatMember[];
|
|
882
|
+
get lastMessage(): ChatMessage | null;
|
|
883
|
+
get unreadCount(): number;
|
|
884
|
+
get title(): string;
|
|
885
|
+
presence(userId: string): PresenceState | null;
|
|
886
|
+
private ensureWired;
|
|
887
|
+
private hydrateHistory;
|
|
888
|
+
private mergeHistory;
|
|
889
|
+
/** @internal — called by the backend's live subscription. */
|
|
890
|
+
ingestLive(incoming: IncomingMessage): Promise<void>;
|
|
891
|
+
/** @internal — called by the backend's conv subscription. */
|
|
892
|
+
applyConv(event: string, payload: Record<string, unknown>): void;
|
|
893
|
+
private kindOf;
|
|
894
|
+
private internalKey;
|
|
895
|
+
private publicId;
|
|
896
|
+
/** Page older messages in. Returns how many were prepended. */
|
|
897
|
+
loadEarlier(limit?: number): Promise<number>;
|
|
898
|
+
private refreshMembers;
|
|
899
|
+
private seedMembersFromGroup;
|
|
900
|
+
private seedDraftMembers;
|
|
901
|
+
send(text: string, opts?: {
|
|
902
|
+
replyTo?: ChatMessage;
|
|
903
|
+
}): Promise<SentReceipt>;
|
|
904
|
+
private appendOwnSend;
|
|
905
|
+
private materializeIfNeeded;
|
|
906
|
+
addMemberUser(userId: string): Promise<void>;
|
|
907
|
+
removeMemberUser(userId: string): Promise<void>;
|
|
908
|
+
leave(): Promise<void>;
|
|
909
|
+
setTyping(isTyping: boolean): void;
|
|
910
|
+
markRead(message: ChatMessage): Promise<void>;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
declare class PalbeMessaging {
|
|
914
|
+
private readonly coordinator;
|
|
915
|
+
constructor(rt: PalbeRuntime);
|
|
916
|
+
/**
|
|
917
|
+
* Warm messaging at sign-in (optional). Enrolls this device + starts the live
|
|
918
|
+
* delivery source so incoming DMs/Welcomes drain before the chat list opens.
|
|
919
|
+
* Never REQUIRED — any chat op self-enrolls. Idempotent.
|
|
920
|
+
*/
|
|
921
|
+
start(): Promise<void>;
|
|
922
|
+
/**
|
|
923
|
+
* Open the ONE direct chat with `userId`. INSTANT + LOCAL — no network, nothing
|
|
924
|
+
* created yet. Returns a draft `Chat` to show immediately; the server group +
|
|
925
|
+
* MLS material materialize LAZILY on the first `chat.send`. Idempotent + stable:
|
|
926
|
+
* the same two users always resolve to the SAME Chat.
|
|
927
|
+
*/
|
|
928
|
+
directChat(userId: string): Chat;
|
|
929
|
+
/**
|
|
930
|
+
* Open a multi-party group chat. LOCAL + LAZY like `directChat`: pick the
|
|
931
|
+
* members, get a draft Chat, the group is created on the FIRST `chat.send`.
|
|
932
|
+
*/
|
|
933
|
+
groupChat(opts?: {
|
|
934
|
+
members?: string[];
|
|
935
|
+
}): Chat;
|
|
936
|
+
/** Look up a chat by id (e.g. from a push payload / deep link). null if unknown. */
|
|
937
|
+
chat(id: string): Chat | null;
|
|
938
|
+
/** The observable chat list (DMs + groups, active only). Read it after an
|
|
939
|
+
* `onChatsChange` subscription to render the inbox. */
|
|
940
|
+
get chats(): readonly Chat[];
|
|
941
|
+
/** Subscribe to chat-list changes (a chat added/removed/hydrated). */
|
|
942
|
+
onChatsChange(cb: () => void): Unsubscribe$1;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
/**
|
|
946
|
+
* The connection state of the shared realtime WebSocket (iOS enum parity), plus
|
|
947
|
+
* `'error'` — surfaced when a channel could not be recovered after a
|
|
948
|
+
* token-expiry close exhausted its rejoin attempts (the socket itself may still
|
|
949
|
+
* be up; the app should stop expecting events on the dead channel).
|
|
950
|
+
*/
|
|
951
|
+
type RealtimeConnectionState = 'idle' | 'connected' | 'reconnecting' | 'error';
|
|
952
|
+
|
|
953
|
+
/** An inbound broadcast payload (the inner `payload` of the Phoenix envelope). */
|
|
954
|
+
type RealtimePayload = Record<string, unknown>;
|
|
955
|
+
type RealtimeHandler = (payload: RealtimePayload) => void;
|
|
956
|
+
/** A cancellable realtime subscription. `cancel()` removes the handler and,
|
|
957
|
+
* when it was the channel's last, leaves the channel on the shared socket.
|
|
958
|
+
* Cancelling twice is a no-op. */
|
|
959
|
+
interface RealtimeSubscription {
|
|
960
|
+
cancel(): void;
|
|
961
|
+
}
|
|
962
|
+
interface RealtimeStatusSnapshot {
|
|
963
|
+
state: RealtimeConnectionState;
|
|
964
|
+
lastEventAt: Date | null;
|
|
965
|
+
}
|
|
966
|
+
/**
|
|
967
|
+
* The observable connection status (`pb.realtime.status`) — the plain-JS
|
|
968
|
+
* analogue of the iOS `@Observable RealtimeStatusStore`. `state` drives a
|
|
969
|
+
* live "connected" badge; `lastEventAt` proves a push actually arrived.
|
|
970
|
+
* `onChange` fires on state transitions and on every recorded event.
|
|
971
|
+
*/
|
|
972
|
+
interface RealtimeStatus {
|
|
973
|
+
readonly state: RealtimeConnectionState;
|
|
974
|
+
readonly lastEventAt: Date | null;
|
|
975
|
+
onChange(callback: (status: RealtimeStatusSnapshot) => void): Unsubscribe;
|
|
976
|
+
}
|
|
977
|
+
/**
|
|
978
|
+
* A subscription handle for one realtime channel (returned by
|
|
979
|
+
* `pb.realtime.channel(name)` — the SAME instance per name). A channel is
|
|
980
|
+
* joined on the shared socket when its first handler is added (or on the
|
|
981
|
+
* first `send`) and left when its last handler cancels.
|
|
982
|
+
*/
|
|
983
|
+
declare class RealtimeChannel {
|
|
984
|
+
/** The app-defined channel name (bare sub-topic, no "realtime:" prefix). */
|
|
985
|
+
readonly name: string;
|
|
986
|
+
private readonly owner;
|
|
987
|
+
/** @internal — obtain channels via `pb.realtime.channel(name)`. */
|
|
988
|
+
constructor(name: string, owner: PalbeRealtime);
|
|
989
|
+
/**
|
|
990
|
+
* Subscribe `handler` to `event` on this channel. Fire-and-forget: the
|
|
991
|
+
* join rides the shared socket asynchronously. Hold the returned
|
|
992
|
+
* subscription and `cancel()` it to stop.
|
|
993
|
+
*/
|
|
994
|
+
on(event: string, handler: RealtimeHandler): RealtimeSubscription;
|
|
995
|
+
/**
|
|
996
|
+
* Broadcast `payload` to the channel's other subscribers (web addition —
|
|
997
|
+
* iOS is receive-only). Joins the channel if it isn't already; queued
|
|
998
|
+
* until the join is live on the socket.
|
|
999
|
+
*/
|
|
1000
|
+
send(event: string, payload?: RealtimePayload): void;
|
|
1001
|
+
}
|
|
1002
|
+
declare class PalbeRealtime {
|
|
1003
|
+
private readonly rt;
|
|
1004
|
+
private socket;
|
|
1005
|
+
private readonly channels;
|
|
1006
|
+
private readonly statusStore;
|
|
1007
|
+
private readonly handlers;
|
|
1008
|
+
private readonly topicRefcount;
|
|
1009
|
+
constructor(rt: PalbeRuntime);
|
|
1010
|
+
/**
|
|
1011
|
+
* Get the handle for an app-defined channel (e.g. "room:42"). The same
|
|
1012
|
+
* name returns the SAME instance. Throws a guided error on server-side
|
|
1013
|
+
* hosts (SSR/RSC/Node) — realtime is client-only.
|
|
1014
|
+
*/
|
|
1015
|
+
channel(name: string): RealtimeChannel;
|
|
1016
|
+
/**
|
|
1017
|
+
* Tear down the shared socket and clear all channel state. Called by
|
|
1018
|
+
* `__configure` and `__reset` when the runtime is replaced, so old sockets
|
|
1019
|
+
* are not left open and heartbeat timers do not leak.
|
|
1020
|
+
*/
|
|
1021
|
+
destroy(): void;
|
|
1022
|
+
/** The observable connection status. Safe to read anywhere (reports `idle` until a socket exists). */
|
|
1023
|
+
get status(): RealtimeStatus;
|
|
1024
|
+
/** @internal */
|
|
1025
|
+
subscribe(topic: string, event: string, handler: RealtimeHandler): RealtimeSubscription;
|
|
1026
|
+
/** @internal */
|
|
1027
|
+
send(topic: string, event: string, payload: RealtimePayload): void;
|
|
1028
|
+
/** Lazily build + start the shared socket on first subscription/send. */
|
|
1029
|
+
private ensureSocket;
|
|
1030
|
+
private route;
|
|
1031
|
+
/**
|
|
1032
|
+
* A channel died for good (token-expiry rejoin exhausted N attempts). Drop its
|
|
1033
|
+
* handlers + refcount so the app stops expecting events on it, and flip the
|
|
1034
|
+
* status observable to `'error'` (the React `useChannel` hook reports this).
|
|
1035
|
+
* A later `.on()` for the same topic re-joins from scratch (refcount 1).
|
|
1036
|
+
*/
|
|
1037
|
+
private handleChannelError;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
interface PalbeRuntime {
|
|
1041
|
+
config: PalbeConfig;
|
|
1042
|
+
http: HttpClient$1;
|
|
1043
|
+
tokenManager: TokenManager$1;
|
|
1044
|
+
authClient: AuthClient;
|
|
1045
|
+
auth: PalbeAuth;
|
|
1046
|
+
flags: PalbeFlags;
|
|
1047
|
+
realtime: PalbeRealtime;
|
|
1048
|
+
analytics: PalbeAnalytics;
|
|
1049
|
+
calls: PalbeCalls;
|
|
1050
|
+
messaging: PalbeMessaging;
|
|
1051
|
+
storage: SessionStorageAdapter;
|
|
1052
|
+
/**
|
|
1053
|
+
* Destroy the realtime facade if it was already constructed (no-op otherwise).
|
|
1054
|
+
* Called by `__configure` / `__reset` when the runtime is replaced so the old
|
|
1055
|
+
* socket is closed and heartbeat timers do not leak.
|
|
1056
|
+
*/
|
|
1057
|
+
destroyRealtime(): void;
|
|
1058
|
+
}
|
|
1059
|
+
declare function buildRuntime(config: PalbeConfig): PalbeRuntime;
|
|
1060
|
+
|
|
1061
|
+
type MagicLinkResult = ({
|
|
1062
|
+
status: 'signedIn';
|
|
1063
|
+
} & AuthSuccess) | {
|
|
1064
|
+
status: 'mfaRequired';
|
|
1065
|
+
mfaToken: string;
|
|
1066
|
+
factors: string[];
|
|
1067
|
+
};
|
|
1068
|
+
type OAuthExchangeResult = ({
|
|
1069
|
+
status: 'signedIn';
|
|
1070
|
+
} & AuthSuccess) | {
|
|
1071
|
+
status: 'mfaRequired';
|
|
1072
|
+
mfaToken: string;
|
|
1073
|
+
factors: string[];
|
|
1074
|
+
};
|
|
1075
|
+
interface AuthUser {
|
|
1076
|
+
id: string;
|
|
1077
|
+
/** null for phone-only users (the server omits email). */
|
|
1078
|
+
email: string | null;
|
|
1079
|
+
emailVerified: boolean;
|
|
1080
|
+
createdAt: string;
|
|
1081
|
+
}
|
|
1082
|
+
interface AuthSuccess {
|
|
1083
|
+
user: AuthUser;
|
|
1084
|
+
session: Session$1;
|
|
1085
|
+
}
|
|
1086
|
+
type AuthState = {
|
|
1087
|
+
status: 'signedIn';
|
|
1088
|
+
user: AuthUser;
|
|
1089
|
+
} | {
|
|
1090
|
+
status: 'signedOut';
|
|
1091
|
+
};
|
|
1092
|
+
type AuthChangeEvent = {
|
|
1093
|
+
type: 'signedIn';
|
|
1094
|
+
user: AuthUser;
|
|
1095
|
+
} | {
|
|
1096
|
+
type: 'signedOut';
|
|
1097
|
+
reason: 'userInitiated' | 'sessionExpired';
|
|
1098
|
+
} | {
|
|
1099
|
+
type: 'tokenRefreshed';
|
|
1100
|
+
};
|
|
1101
|
+
type Unsubscribe = () => void;
|
|
1102
|
+
declare class PalbeAuth {
|
|
1103
|
+
private readonly rt;
|
|
1104
|
+
private cachedUser;
|
|
1105
|
+
private signingOut;
|
|
1106
|
+
private signingIn;
|
|
1107
|
+
private signedInState;
|
|
1108
|
+
private readonly stateListeners;
|
|
1109
|
+
private readonly eventListeners;
|
|
1110
|
+
private readonly userListeners;
|
|
1111
|
+
constructor(rt: PalbeRuntime);
|
|
1112
|
+
get currentUser(): AuthUser | null;
|
|
1113
|
+
get isSignedIn(): boolean;
|
|
1114
|
+
signUp(params: {
|
|
1115
|
+
email: string;
|
|
1116
|
+
password: string;
|
|
1117
|
+
}): Promise<AuthSuccess>;
|
|
1118
|
+
signIn(params: {
|
|
1119
|
+
email: string;
|
|
1120
|
+
password: string;
|
|
1121
|
+
}): Promise<AuthSuccess>;
|
|
1122
|
+
signOut(): Promise<void>;
|
|
1123
|
+
getUser(): Promise<AuthUser>;
|
|
1124
|
+
refreshUser(): Promise<AuthUser>;
|
|
1125
|
+
/**
|
|
1126
|
+
* Subscribe to signed-in/signed-out state. Fires immediately with the
|
|
1127
|
+
* current snapshot (iOS parity). NOTE: a restored session (page reload) has
|
|
1128
|
+
* no cached user yet, so the immediate snapshot reports signedOut even when
|
|
1129
|
+
* `isSignedIn` is true — call `refreshUser()` on boot to populate the user
|
|
1130
|
+
* and rely on `isSignedIn` for the session truth.
|
|
1131
|
+
*/
|
|
1132
|
+
onAuthStateChange(callback: (state: AuthState) => void): Unsubscribe;
|
|
1133
|
+
onAuthEvent(callback: (event: AuthChangeEvent) => void): Unsubscribe;
|
|
1134
|
+
/** Subscribe to user-profile changes. Replays the cached user on subscribe (iOS parity). */
|
|
1135
|
+
onUserChange(callback: (user: AuthUser) => void): Unsubscribe;
|
|
1136
|
+
private snapshotState;
|
|
1137
|
+
/**
|
|
1138
|
+
* Listener exception isolation: a throwing consumer callback must never
|
|
1139
|
+
* break delivery to other listeners nor propagate into the emit caller
|
|
1140
|
+
* (tokenManager.clearSession callers, pb.call paths, signOut, ...).
|
|
1141
|
+
*/
|
|
1142
|
+
private safeInvoke;
|
|
1143
|
+
private emitState;
|
|
1144
|
+
private emitEvent;
|
|
1145
|
+
/** Cache the user + announce sign-in. Session was already set by AuthClient. */
|
|
1146
|
+
private adopt;
|
|
1147
|
+
/** Adopt a raw palauth AuthResult wire shape: wire tokens, cache user, announce. */
|
|
1148
|
+
private adoptWire;
|
|
1149
|
+
/** Run a sign-in flow under the signingIn flag to suppress spurious tokenRefreshed. */
|
|
1150
|
+
private withSigningIn;
|
|
1151
|
+
/**
|
|
1152
|
+
* Defensively decode a 200 union body (AuthResult | mfa-required) and
|
|
1153
|
+
* complete the flow. The wire contract promises one of the two shapes, but
|
|
1154
|
+
* a literal-`null` (or otherwise malformed) JSON body must surface as
|
|
1155
|
+
* BackendError('decode') — never a raw TypeError from probing a non-object.
|
|
1156
|
+
* The mfa branch validates its fields: `mfa_token` is required; the factor
|
|
1157
|
+
* list (named `factors` by magic-link verify, `mfa_factors` by the OAuth
|
|
1158
|
+
* callback — extraction-verified against palauth) tolerates a missing or
|
|
1159
|
+
* malformed value as []. The signedIn branch validates the FULL AuthResult
|
|
1160
|
+
* shape (asWireAuthResult) — an incomplete body falls through to decode,
|
|
1161
|
+
* never half-adopts.
|
|
1162
|
+
*/
|
|
1163
|
+
private completeAuthUnion;
|
|
1164
|
+
private decodeError;
|
|
1165
|
+
signInWithOTP(params: {
|
|
1166
|
+
phone: string;
|
|
1167
|
+
}): Promise<void>;
|
|
1168
|
+
verifyOTP(params: {
|
|
1169
|
+
phone: string;
|
|
1170
|
+
token: string;
|
|
1171
|
+
}): Promise<AuthSuccess>;
|
|
1172
|
+
resetPassword(email: string): Promise<void>;
|
|
1173
|
+
confirmPasswordReset(params: {
|
|
1174
|
+
token: string;
|
|
1175
|
+
newPassword: string;
|
|
1176
|
+
}): Promise<void>;
|
|
1177
|
+
updatePassword(params: {
|
|
1178
|
+
currentPassword: string;
|
|
1179
|
+
newPassword: string;
|
|
1180
|
+
}): Promise<void>;
|
|
1181
|
+
verifyEmail(params: {
|
|
1182
|
+
token: string;
|
|
1183
|
+
} | {
|
|
1184
|
+
code: string;
|
|
1185
|
+
email: string;
|
|
1186
|
+
}): Promise<void>;
|
|
1187
|
+
resendVerification(email: string): Promise<void>;
|
|
1188
|
+
signInWithMagicLink(email: string): Promise<void>;
|
|
1189
|
+
verifyMagicLink(token: string): Promise<MagicLinkResult>;
|
|
1190
|
+
signInWithCredential(params: {
|
|
1191
|
+
provider: string;
|
|
1192
|
+
credential: string;
|
|
1193
|
+
}): Promise<AuthSuccess>;
|
|
1194
|
+
signInWithOAuth(params: {
|
|
1195
|
+
provider: string;
|
|
1196
|
+
redirectTo?: string;
|
|
1197
|
+
/** Set false to skip the browser redirect (popup/manual flows). Default true. */
|
|
1198
|
+
redirect?: boolean;
|
|
1199
|
+
}): Promise<{
|
|
1200
|
+
url: string;
|
|
1201
|
+
}>;
|
|
1202
|
+
/**
|
|
1203
|
+
* Complete the OAuth redirect flow: trade the provider's `code` + `state`
|
|
1204
|
+
* (from the app's redirect_uri query) for a session. PKCE verifier + state
|
|
1205
|
+
* live server-side in palauth — the client only relays the two values.
|
|
1206
|
+
*/
|
|
1207
|
+
exchangeCodeForSession(params: {
|
|
1208
|
+
provider: string;
|
|
1209
|
+
code: string;
|
|
1210
|
+
state: string;
|
|
1211
|
+
}): Promise<OAuthExchangeResult>;
|
|
1212
|
+
/** Config-as-code gate for the zero-arg provider sugar. */
|
|
1213
|
+
private requireProvider;
|
|
1214
|
+
signInWithGoogle(opts?: {
|
|
1215
|
+
redirectTo?: string;
|
|
1216
|
+
redirect?: boolean;
|
|
1217
|
+
}): Promise<{
|
|
1218
|
+
url: string;
|
|
1219
|
+
}>;
|
|
1220
|
+
signInWithApple(opts?: {
|
|
1221
|
+
redirectTo?: string;
|
|
1222
|
+
redirect?: boolean;
|
|
1223
|
+
}): Promise<{
|
|
1224
|
+
url: string;
|
|
1225
|
+
}>;
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
/** Free-form event property bag (JSON object on the wire). */
|
|
1229
|
+
type AnalyticsProperties = Record<string, unknown>;
|
|
1230
|
+
/**
|
|
1231
|
+
* Runtime-scoped analytics identity — constructed EAGERLY in `buildRuntime`
|
|
1232
|
+
* (cheap: listener wiring only, no I/O) because the X-Distinct-Id header
|
|
1233
|
+
* interceptor must stamp every request from the first one, even when
|
|
1234
|
+
* `pb.analytics` is never touched (iOS: the resolver is wired at
|
|
1235
|
+
* PalBackend init). The facade wraps this state lazily.
|
|
1236
|
+
*
|
|
1237
|
+
* Auth events: while no facade exists, the state maintains identity only
|
|
1238
|
+
* (user id for the header, anon rotation on user-initiated sign-out). Once
|
|
1239
|
+
* the facade attaches, it takes over wholesale and adds the ingest
|
|
1240
|
+
* side-effects (flush + identify / flush + reset).
|
|
1241
|
+
*/
|
|
1242
|
+
declare class AnalyticsState {
|
|
1243
|
+
identifiedUserId: string | null;
|
|
1244
|
+
/** Set by PalbeAnalytics on construction — delegates auth events to it. */
|
|
1245
|
+
facadeAuthHandler: ((event: AuthChangeEvent) => void) | null;
|
|
1246
|
+
private anonId;
|
|
1247
|
+
private readonly store;
|
|
1248
|
+
private readonly idKey;
|
|
1249
|
+
private readonly optOutKey;
|
|
1250
|
+
constructor(rt: PalbeRuntime);
|
|
1251
|
+
/** User id when identified, else the stable anon id. NEVER empty —
|
|
1252
|
+
* this is what `identify()` links, so stamping it on every request lets
|
|
1253
|
+
* the trace pipeline stitch pre-login activity to the user. */
|
|
1254
|
+
distinctId(): string;
|
|
1255
|
+
anonymousId(): string;
|
|
1256
|
+
rotateAnonymousId(): string;
|
|
1257
|
+
isOptedOut(): boolean;
|
|
1258
|
+
setOptOut(on: boolean): void;
|
|
1259
|
+
}
|
|
1260
|
+
declare class PalbeAnalytics {
|
|
1261
|
+
private readonly rt;
|
|
1262
|
+
private readonly state;
|
|
1263
|
+
private readonly buffer;
|
|
1264
|
+
private flushTimer;
|
|
1265
|
+
/** Browser → buffer + size/timer flush. Server (no document) → immediate
|
|
1266
|
+
* per-call POST, zero timers (nothing leaks into RSC/route handlers). */
|
|
1267
|
+
private readonly browser;
|
|
1268
|
+
constructor(rt: PalbeRuntime, state: AnalyticsState);
|
|
1269
|
+
/** Record an event. Invalid names are dropped (one warn per process). */
|
|
1270
|
+
capture(event: string, properties?: AnalyticsProperties): void;
|
|
1271
|
+
/** Record a screen view — server-canonical `$screen` + `screen_name`.
|
|
1272
|
+
* Validates non-empty only (the live wire at /v1/analytics/screen requires
|
|
1273
|
+
* non-empty screen_name; the event-name regex does NOT apply here). */
|
|
1274
|
+
screen(name: string, properties?: AnalyticsProperties): void;
|
|
1275
|
+
/** Link the current anon id to `userId` and adopt it as the distinct id.
|
|
1276
|
+
* Immediate POST (not buffered). Re-identifying a DIFFERENT user
|
|
1277
|
+
* auto-resets first (iOS K10) so one anon id never links two users. */
|
|
1278
|
+
identify(userId: string, traits?: AnalyticsProperties): void;
|
|
1279
|
+
/** Merge distinct id `from` into `to` (identity stitching). Immediate POST. */
|
|
1280
|
+
alias(from: string, to: string): void;
|
|
1281
|
+
/** Drop the buffer, clear the identified user and rotate the anon id
|
|
1282
|
+
* (sign-out hygiene). Callers wanting pending events delivered flush first
|
|
1283
|
+
* — the auth binding does. */
|
|
1284
|
+
reset(): void;
|
|
1285
|
+
/** Persisted GDPR opt-out. Opting out drops anything pending so nothing
|
|
1286
|
+
* already-buffered leaks after the user said stop. */
|
|
1287
|
+
setOptOut(on: boolean): void;
|
|
1288
|
+
/** Drain the buffer to /v1/analytics/batch (≤100 per request, sequential).
|
|
1289
|
+
* Resolves when delivery finished; NEVER rejects — failed slices are
|
|
1290
|
+
* dropped with one warn per flush. 207 partial-reject is also warned once
|
|
1291
|
+
* (fire-and-forget: no retry for already-delivered batches). */
|
|
1292
|
+
flush(): Promise<void>;
|
|
1293
|
+
private ingest;
|
|
1294
|
+
/** iOS PalBackend auth-binding parity: signedIn → flush + identify;
|
|
1295
|
+
* userInitiated signedOut → flush + reset; sessionExpired → flush only. */
|
|
1296
|
+
private handleAuthEvent;
|
|
1297
|
+
private startTimer;
|
|
1298
|
+
private cancelTimer;
|
|
1299
|
+
private post;
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
export { type AnalyticsProperties as A, type RealtimeConnectionState as B, Call as C, type RealtimeHandler as D, type RealtimePayload as E, type FlagsView as F, type RealtimeStatus as G, type RealtimeStatusSnapshot as H, type RealtimeSubscription as I, type PalbeRuntime as J, buildRuntime as K, type MagicLinkResult as M, type OAuthExchangeResult as O, PalbeAnalytics as P, RealtimeChannel as R, type SentReceipt as S, type Unsubscribe as U, type AuthChangeEvent as a, type AuthState as b, type AuthSuccess as c, type AuthUser as d, type CallChangeCallback as e, type CallParticipant as f, type CallState as g, Chat as h, type ChatBackend as i, type ChatDraft as j, type ChatKind as k, type ChatMember as l, type ChatMessage as m, type ChatMessageKind as n, type ChatRole as o, type ChatState as p, type CommsPrefs as q, type MessageDirection as r, PalbeAuth as s, PalbeCalls as t, type PalbeConfig as u, PalbeFlags as v, PalbeMessaging as w, type PalbeOAuthConfig as x, PalbeRealtime as y, type PresenceState as z };
|