@zuzjs/flare 0.2.1 → 0.2.2

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/index.d.cts CHANGED
@@ -1,80 +1,174 @@
1
- export { AuthGuard, AuthToken, Dropbox, Google, NormalizedProfile, OAuthProvider, ProviderId } from '@zuzjs/auth';
1
+ import { AuthToken, AuthGuard, ProviderId } from '@zuzjs/auth';
2
+ export { Anonymous, Apple, AuthGuard, AuthToken, CreateUserWithEmailAndPasswordInput, Credentials, Dropbox, Facebook, GitHub, Google, NormalizedProfile, OAuthProvider, ProviderId, Providers, SignInAnonymouslyInput, SignInWithEmailAndPasswordInput, Twitter, setupProvider } from '@zuzjs/auth';
2
3
 
3
4
  /**
4
5
  * Client Configuration
5
6
  */
6
7
  interface FlareConfig {
7
- /** WebSocket endpoint URL (e.g., 'http://localhost:5050' or 'wss://api.example.com') */
8
8
  endpoint: string;
9
- /** Application/Project ID */
10
- appId: string;
11
- /** API Key for authentication (optional) */
12
- apiKey?: string;
13
9
  /**
14
- * RSA public key (PEM) returned by `flare app create`.
15
- * When provided, all outgoing messages are wrapped in an RSA-OAEP encrypted
16
- * envelope: `{ enc: "rsa", data: "<base64>" }` before being sent over the wire.
10
+ * Optional HTTP base URL for auth API calls.
11
+ * When set, all auth HTTP calls go through this base instead of calling
12
+ * Flare directly. Use this to route calls through a Next.js proxy so CSRF
13
+ * is handled entirely server-side.
14
+ * Example: '/api/flare' (relative, browser resolves against current origin)
17
15
  */
16
+ httpBase?: string;
17
+ appId: string;
18
+ apiKey?: string;
18
19
  publicKey?: string;
19
- /** Enable automatic reconnection (default: true) */
20
20
  autoReconnect?: boolean;
21
- /** Initial reconnect delay in seconds (default: 2) */
22
21
  reconnectDelay?: number;
23
- /** Maximum reconnect delay in seconds (default: 60) */
24
22
  maxReconnectDelay?: number;
25
- /** Enable debug logging (default: false) */
26
23
  debug?: boolean;
27
- /** Connection timeout in milliseconds (default: 10000) */
24
+ requestTiming?: boolean;
28
25
  connectionTimeout?: number;
29
26
  }
30
- /**
31
- * Query configuration (NEW v0.2: Object-based query syntax)
32
- */
27
+ type FlareAuthProviderId = "credentials" | "anonymous" | "google" | "facebook" | "github" | "dropbox" | "apple" | "twitter";
28
+ interface FlareAuthProviderPublicConfig {
29
+ enabled: boolean;
30
+ clientId?: string;
31
+ scopes?: string[];
32
+ }
33
+ interface FlareAuthConfig {
34
+ appId: string;
35
+ enabled: boolean;
36
+ needsEmailVerification?: boolean;
37
+ autoSendVerificationEmail?: boolean;
38
+ redirectUri?: string;
39
+ csrfToken?: string;
40
+ cookie?: {
41
+ accessTokenName?: string;
42
+ refreshTokenName?: string;
43
+ csrfTokenName?: string;
44
+ domain?: string;
45
+ path?: string;
46
+ secure?: boolean;
47
+ sameSite?: "Lax" | "Strict" | "None";
48
+ accessTokenMaxAge?: number;
49
+ refreshTokenMaxAge?: number;
50
+ csrfTokenMaxAge?: number;
51
+ };
52
+ providers: Record<FlareAuthProviderId, FlareAuthProviderPublicConfig>;
53
+ }
54
+ interface FlareAuthSession {
55
+ uid: string;
56
+ accessToken: string;
57
+ refreshToken: string | null;
58
+ provider?: string;
59
+ email?: string | null;
60
+ emailVerified?: boolean;
61
+ }
62
+ type AuthStateListener = (session: FlareAuthSession | null) => void;
63
+ type AuthConfigListener = (conf: FlareAuthConfig) => void;
64
+ interface SubscribeOptions {
65
+ skipSnapshot?: boolean;
66
+ }
67
+ type QueryOperator = "==" | "!=" | "<" | "<=" | ">" | ">=" | "in" | "not-in" | "array-contains" | "array-contains-any" | "like" | "not-like" | "contains" | "exists" | "not-exists";
33
68
  interface QueryConfig {
34
69
  field: string;
35
70
  op: QueryOperator;
36
71
  value: unknown;
37
72
  }
38
- /**
39
- * Where condition (NEW v0.2: Object-based syntax)
40
- * Example: { age: ">= 25", role: "admin" }
41
- */
73
+ /** OR group */
74
+ interface OrFilter {
75
+ or: QueryConfig[];
76
+ }
77
+ type AnyFilter = QueryConfig | OrFilter;
42
78
  type WhereCondition = Record<string, string | number | boolean | any[]>;
43
- type QueryOperator = "==" | "!=" | "<" | "<=" | ">" | ">=" | "in" | "not-in" | "array-contains";
44
- /**
45
- * Subscription callback
46
- */
47
- type SubscriptionCallback<T = any> = (data: SubscriptionData<T>) => void;
79
+ interface OrderByClause {
80
+ field: string;
81
+ dir?: "asc" | "desc";
82
+ }
83
+ interface GroupByClause {
84
+ fields: string[];
85
+ }
86
+ interface HavingClause {
87
+ field: string;
88
+ op: "==" | "!=" | "<" | "<=" | ">" | ">=";
89
+ value: number;
90
+ }
91
+ interface CursorValue {
92
+ values: unknown[];
93
+ }
94
+ type AggregateFunction = "count" | "sum" | "avg" | "min" | "max" | "distinct";
95
+ interface AggregateSpec {
96
+ fn: AggregateFunction;
97
+ field?: string;
98
+ alias?: string;
99
+ }
100
+ interface JoinClause {
101
+ from: string;
102
+ localField: string;
103
+ foreignField: string;
104
+ as: string;
105
+ single?: boolean;
106
+ }
107
+ interface VectorSearchClause {
108
+ field: string;
109
+ vector: number[];
110
+ k: number;
111
+ metric?: "cosine" | "euclidean" | "dotProduct";
112
+ minScore?: number;
113
+ }
114
+ /** Full structured query (Firestore + SQL feature set) */
115
+ interface StructuredQuery {
116
+ where?: AnyFilter[];
117
+ orderBy?: OrderByClause[];
118
+ limit?: number;
119
+ offset?: number;
120
+ startAt?: CursorValue;
121
+ startAfter?: CursorValue;
122
+ endAt?: CursorValue;
123
+ endBefore?: CursorValue;
124
+ aggregate?: AggregateSpec[];
125
+ groupBy?: GroupByClause;
126
+ having?: HavingClause[];
127
+ joins?: JoinClause[];
128
+ vectorSearch?: VectorSearchClause;
129
+ select?: string[];
130
+ distinctField?: string;
131
+ }
132
+ type ChangeOperation = 'insert' | 'update' | 'replace' | 'delete';
48
133
  /**
49
- * Subscription data received from server
134
+ * Fired once when the subscription is first established.
135
+ * `data` is always an array — the full matching collection snapshot.
50
136
  */
51
- interface SubscriptionData<T = any> {
137
+ interface SnapshotEvent<T = any> {
138
+ type: 'snapshot';
52
139
  subscriptionId: string;
53
140
  collection: string;
54
- docId?: string;
55
- data: T | T[];
56
- type: 'snapshot' | 'change';
57
- operation?: 'insert' | 'update' | 'delete' | 'replace';
141
+ data: T[];
58
142
  }
59
143
  /**
60
- * Document reference
144
+ * Fired on every subsequent document mutation that matches the subscription query.
145
+ * `data` is the single affected document (null on delete).
61
146
  */
147
+ interface ChangeEvent<T = any> {
148
+ type: 'change';
149
+ subscriptionId: string;
150
+ collection: string;
151
+ docId: string;
152
+ operation: ChangeOperation;
153
+ data: T | null;
154
+ }
155
+ /** Discriminated union — narrow on `event.type` to get the right shape. */
156
+ type SubscriptionData<T = any> = SnapshotEvent<T> | ChangeEvent<T>;
157
+ type SubscriptionCallback<T = any> = (data: SubscriptionData<T>) => void;
158
+ type DocAddedCallback<T = any> = (data: T, docId: string) => void;
159
+ type DocUpdatedCallback<T = any> = (data: T, docId: string) => void;
160
+ type DocDeletedCallback<T = any> = (docId: string) => void;
161
+ type DocChangedCallback<T = any> = (data: T | null, docId: string, operation: ChangeOperation) => void;
62
162
  interface DocumentSnapshot<T = any> {
63
163
  id: string;
64
164
  data: T | null;
65
165
  exists: boolean;
66
166
  }
67
- /**
68
- * Collection query result
69
- */
70
167
  interface QuerySnapshot<T = any> {
71
168
  docs: DocumentSnapshot<T>[];
72
169
  size: number;
73
170
  empty: boolean;
74
171
  }
75
- /**
76
- * Offline operation
77
- */
78
172
  interface OfflineOperation {
79
173
  id: string;
80
174
  type: 'write' | 'delete';
@@ -84,18 +178,54 @@ interface OfflineOperation {
84
178
  merge?: boolean;
85
179
  clientTs: number;
86
180
  }
87
- /**
88
- * Authentication result
89
- */
90
181
  interface AuthResult {
91
182
  uid: string;
92
183
  token?: string;
93
184
  }
94
- /**
95
- * Connection state
96
- */
97
185
  type ConnectionState = 'connecting' | 'connected' | 'disconnected' | 'reconnecting' | 'error';
186
+ interface AuthWithPendingVerificationResult {
187
+ verificationRequired: true;
188
+ created: true;
189
+ emailSent: boolean;
190
+ preview?: {
191
+ code: string;
192
+ link: string;
193
+ };
194
+ }
195
+ interface AuthWithTokenResult extends AuthResult {
196
+ accessToken: string;
197
+ refreshToken: string | null;
198
+ authToken: AuthToken;
199
+ created: boolean;
200
+ }
201
+ interface PresenceMember {
202
+ uid: string;
203
+ socketId: string;
204
+ room: string;
205
+ meta?: Record<string, unknown>;
206
+ joinedAt: number;
207
+ lastSeen: number;
208
+ }
209
+ type PresenceCallback = (members: PresenceMember[]) => void;
210
+ type PresenceJoinCallback = (member: PresenceMember) => void;
211
+ type PresenceLeaveCallback = (uid: string) => void;
212
+ /** Fields marked as vector will be auto-embedded before write */
213
+ type VectorFieldConfig = {
214
+ /** Dimensions of the vector (e.g. 1536 for OpenAI ada-002) */
215
+ dimensions: number;
216
+ /** Optional custom embedding function; defaults to client-configured embedder */
217
+ embed?: (text: string) => Promise<number[]>;
218
+ };
98
219
 
220
+ /**
221
+ * Parse ORM-style where condition: { age: ">= 25", role: "admin" }
222
+ * Returns array of QueryConfig objects
223
+ */
224
+ declare function parseWhereCondition(condition: WhereCondition): QueryConfig[];
225
+ /**
226
+ * Parse string value to appropriate type
227
+ */
228
+ declare function parseValue(val: string): any;
99
229
  /**
100
230
  * Query builder for document operations (ORM-style)
101
231
  * Supports: doc('users').update({...}).where({ id: 'alice' })
@@ -157,6 +287,7 @@ declare class DocumentQueryBuilder<T = any> implements PromiseLike<T | null | vo
157
287
  */
158
288
  onSnapshot(callback: SubscriptionCallback<T>): () => void;
159
289
  }
290
+
160
291
  /**
161
292
  * Legacy document reference (for backward compatibility)
162
293
  */
@@ -170,57 +301,88 @@ declare class DocumentReference<T = any> {
170
301
  update(data: Partial<T>): Promise<void>;
171
302
  delete(): Promise<void>;
172
303
  onSnapshot(callback: SubscriptionCallback<T>): () => void;
304
+ /**
305
+ * Fires when this document is updated / replaced.
306
+ * Aliases: onDocModified, onDocChange
307
+ */
308
+ onDocUpdated(callback: DocUpdatedCallback<T>): () => void;
309
+ /** Alias for onDocUpdated */
310
+ onDocModified(callback: DocUpdatedCallback<T>): () => void;
311
+ /** Alias for onDocUpdated */
312
+ onDocChange(callback: DocUpdatedCallback<T>): () => void;
313
+ /**
314
+ * Fires when this document is deleted.
315
+ */
316
+ onDocDeleted(callback: DocDeletedCallback<T>): () => void;
317
+ /**
318
+ * Fires on any change to this document (update / delete).
319
+ * `data` is null on deletes.
320
+ */
321
+ onDocChanged(callback: DocChangedCallback<T>): () => void;
173
322
  }
174
- /**
175
- * Collection reference with ORM-style query builder
176
- *
177
- * This class is thenable - you can await it directly without .get()
178
- * @example
179
- * await collection('users').where({ age: '>= 25' })
180
- */
323
+
181
324
  declare class CollectionReference<T = any> implements PromiseLike<T[]> {
182
325
  private client;
183
326
  readonly collection: string;
184
- private queries;
327
+ private sq;
185
328
  private promise?;
186
329
  constructor(client: FlareClient, collection: string);
187
- /**
188
- * Get a document reference (legacy API)
189
- */
190
330
  doc(id: string): DocumentReference<T>;
191
- /**
192
- * Add a where filter (NEW ORM-style API)
193
- * @example .where({ age: ">= 25", role: "admin" })
194
- */
331
+ private clone;
332
+ /** ORM shorthand: .where({ age: ">= 25", role: "admin" }) */
195
333
  where(condition: WhereCondition): CollectionReference<T>;
334
+ /** Explicit field/op/value */
335
+ where(field: string, op: QueryConfig['op'], value: unknown): CollectionReference<T>;
336
+ /** OR group: .orWhere([{ field:"status", op:"==", value:"active" }, ...]) */
337
+ orWhere(filters: QueryConfig[]): CollectionReference<T>;
338
+ orderBy(field: string, dir?: "asc" | "desc"): CollectionReference<T>;
339
+ limit(n: number): CollectionReference<T>;
340
+ offset(n: number): CollectionReference<T>;
341
+ startAt(...values: unknown[]): CollectionReference<T>;
342
+ startAfter(...values: unknown[]): CollectionReference<T>;
343
+ endAt(...values: unknown[]): CollectionReference<T>;
344
+ endBefore(...values: unknown[]): CollectionReference<T>;
345
+ aggregate(...specs: AggregateSpec[]): CollectionReference<T>;
346
+ count(alias?: string): CollectionReference<T>;
347
+ sum(field: string, alias?: string): CollectionReference<T>;
348
+ avg(field: string, alias?: string): CollectionReference<T>;
349
+ min(field: string, alias?: string): CollectionReference<T>;
350
+ max(field: string, alias?: string): CollectionReference<T>;
351
+ distinct(field: string, alias?: string): CollectionReference<T>;
352
+ groupBy(...fields: string[]): CollectionReference<T>;
353
+ having(field: string, op: HavingClause['op'], value: number): CollectionReference<T>;
354
+ join(j: JoinClause): CollectionReference<T>;
355
+ select(...fields: string[]): CollectionReference<T>;
356
+ /** Returns unique values for a single field */
357
+ distinctField(field: string): CollectionReference<T>;
196
358
  /**
197
- * Get all documents once
198
- * @deprecated Use await directly instead of .get()
359
+ * KNN nearest-neighbour search (requires Atlas vector index).
360
+ * @example
361
+ * col.vectorSearch({ field: "embedding", vector: [...1536 numbers...], k: 10 })
199
362
  */
363
+ vectorSearch(opts: VectorSearchClause): CollectionReference<T>;
200
364
  get(): Promise<T[]>;
201
- /**
202
- * Internal execute method
203
- */
365
+ private _isStructured;
204
366
  private _execute;
205
- /**
206
- * Make this class thenable so it can be awaited directly
207
- */
367
+ private _executeQuery;
368
+ private _executeSubscribe;
208
369
  then<TResult1 = T[], TResult2 = never>(onfulfilled?: ((value: T[]) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null): PromiseLike<TResult1 | TResult2>;
209
370
  /**
210
- * Subscribe to real-time updates
371
+ * Subscribe to real-time updates.
372
+ * The full StructuredQuery (including orderBy, where, limit, offset) is sent
373
+ * to the server so the initial snapshot respects all constraints.
374
+ * Individual change events are then sorted / filtered client-side to keep
375
+ * the live result consistent.
211
376
  */
212
377
  onSnapshot(callback: SubscriptionCallback<T[]>): () => void;
213
- /**
214
- * Add a new document with auto-generated ID
215
- */
378
+ onDocAdded(callback: DocAddedCallback<T>): () => void;
379
+ onDocUpdated(callback: DocUpdatedCallback<T>): () => void;
380
+ onDocModified(callback: DocUpdatedCallback<T>): () => void;
381
+ onDocChange(callback: DocUpdatedCallback<T>): () => void;
382
+ onDocDeleted(callback: DocDeletedCallback<T>): () => void;
383
+ onDocChanged(callback: DocChangedCallback<T>): () => void;
216
384
  add(data: Partial<T>): Promise<DocumentReference<T>>;
217
- /**
218
- * Update documents matching the where condition
219
- */
220
385
  update(data: Partial<T>): DocumentQueryBuilder<T>;
221
- /**
222
- * Delete documents matching the where condition
223
- */
224
386
  delete(): DocumentQueryBuilder<T>;
225
387
  }
226
388
 
@@ -233,8 +395,13 @@ declare enum FlareAction {
233
395
  AUTH = "auth",
234
396
  PING = "ping",
235
397
  OFFLINE_SYNC = "offline_sync",
236
- /** General-purpose RPC / topic call */
237
- CALL = "call"
398
+ CALL = "call",
399
+ /** One-shot rich query (no real-time subscription) */
400
+ QUERY = "query",
401
+ /** Presence */
402
+ PRESENCE_JOIN = "presence_join",
403
+ PRESENCE_LEAVE = "presence_leave",
404
+ PRESENCE_HEARTBEAT = "presence_heartbeat"
238
405
  }
239
406
  /** Server Response */
240
407
  declare enum FlareEvent {
@@ -245,116 +412,586 @@ declare enum FlareEvent {
245
412
  PONG = "pong",
246
413
  AUTH_OK = "auth_ok",
247
414
  OFFLINE_ACK = "offline_ack",
248
- /** Response to a CALL */
249
- CALL_RESPONSE = "call_response"
415
+ CALL_RESPONSE = "call_response",
416
+ QUERY_RESULT = "query_result",
417
+ PRESENCE_STATE = "presence_state",
418
+ PRESENCE_JOIN = "presence_join",
419
+ PRESENCE_LEAVE = "presence_leave"
250
420
  }
251
421
  interface BaseMessage {
252
422
  id: string;
253
423
  type: FlareAction | FlareEvent;
254
424
  ts: number;
255
425
  }
426
+ interface SubscribeMessage extends BaseMessage {
427
+ type: FlareAction.SUBSCRIBE;
428
+ collection: string;
429
+ docId?: string;
430
+ query?: Record<string, unknown>;
431
+ skipSnapshot?: boolean;
432
+ resumeToken?: string;
433
+ }
434
+
435
+ type TransportOptions = {
436
+ url: string;
437
+ onMessage: (data: any) => void;
438
+ onOpen?: () => void;
439
+ onClose?: () => void;
440
+ onError?: (error: Error) => void;
441
+ autoReconnect?: boolean;
442
+ reconnectDelay?: number;
443
+ maxReconnectDelay?: number;
444
+ debug?: boolean;
445
+ /** RSA public key (PEM). When set, all outgoing messages are RSA-OAEP encrypted. */
446
+ publicKey?: string;
447
+ };
448
+
449
+ declare class FlareTransport {
450
+ private socket;
451
+ private reconnectInterval;
452
+ private maxReconnectDelay;
453
+ private isConnected;
454
+ private shouldReconnect;
455
+ private options;
456
+ private messageQueue;
457
+ private heartbeatInterval;
458
+ private connectionTimeout;
459
+ constructor(options: TransportOptions);
460
+ connect(): void;
461
+ private handleReconnect;
462
+ private startHeartbeat;
463
+ private stopHeartbeat;
464
+ private flushQueue;
465
+ send(message: object): void;
466
+ disconnect(): void;
467
+ get connected(): boolean;
468
+ private log;
469
+ }
256
470
 
257
471
  type ConnectionListener = (state: ConnectionState) => void;
258
472
  type ErrorListener = (error: Error) => void;
259
- declare class FlareClient {
260
- private transport;
261
- private readonly config;
262
- private readonly pendingAcks;
263
- private readonly subscriptions;
264
- private readonly offlineQueue;
265
- private currentState;
266
- private connectionListeners;
267
- private errorListeners;
268
- private authToken?;
269
- private userId?;
270
- private isDebug;
473
+ type ActiveSubscription = {
474
+ baseId: string;
475
+ liveId: string;
476
+ collection: string;
477
+ docId?: string;
478
+ query?: QueryConfig | StructuredQuery;
479
+ callback: SubscriptionCallback;
480
+ options: SubscribeOptions;
481
+ };
482
+ /** Embedder function registered by the user */
483
+ type EmbedFn = (text: string) => Promise<number[]>;
484
+ declare class FlareBase {
485
+ protected transport: FlareTransport;
486
+ protected readonly config: FlareConfig;
487
+ protected readonly pendingAcks: Map<string, (value: any) => void>;
488
+ protected readonly subscriptions: Map<string, SubscriptionCallback>;
489
+ protected readonly activeSubscriptions: Map<string, ActiveSubscription>;
490
+ protected readonly offlineQueue: any[];
491
+ protected currentState: ConnectionState;
492
+ protected connectionListeners: ConnectionListener[];
493
+ protected errorListeners: ErrorListener[];
494
+ protected isDebug: boolean;
495
+ protected socketAuthUid: string;
496
+ protected pendingSubscriptionReplay: boolean;
497
+ protected subscriptionReplayPromise: Promise<void>;
498
+ protected requestTraceSeq: number;
499
+ protected requestTimingEnabled: boolean;
500
+ protected presenceCallbacks: Map<string, PresenceCallback[]>;
501
+ protected presenceJoinCbs: Map<string, PresenceJoinCallback[]>;
502
+ protected presenceLeaveCbs: Map<string, PresenceLeaveCallback[]>;
503
+ protected presenceHeartbeatTimer?: ReturnType<typeof setInterval>;
504
+ protected embedder?: EmbedFn;
505
+ protected vectorSchema: Map<string, Map<string, VectorFieldConfig>>;
506
+ protected throwFetchFlareError(payload: unknown, fallbackMessage: string, fallbackCode: string): never;
507
+ protected nowMs(): number;
508
+ protected normalizeHeaders(headers?: HeadersInit): Record<string, string>;
509
+ protected redactHeaders(headers: Record<string, string>): Record<string, string>;
510
+ protected logHttpTiming(...args: any[]): void;
511
+ protected mergeHeaders(base: HeadersInit | undefined, extra: Record<string, string>): HeadersInit;
512
+ protected timedFetch(label: string, input: string, init?: RequestInit): Promise<{
513
+ response: {
514
+ status: number;
515
+ ok: boolean;
516
+ headers: {
517
+ get: (name: string) => string | null;
518
+ };
519
+ json: () => Promise<any>;
520
+ };
521
+ requestId: number;
522
+ startedAtMs: number;
523
+ networkMs: number;
524
+ method: string;
525
+ url: string;
526
+ }>;
527
+ protected parseJsonWithTiming(label: string, trace: {
528
+ requestId: number;
529
+ startedAtMs: number;
530
+ response: {
531
+ status: number;
532
+ ok: boolean;
533
+ headers: {
534
+ get: (name: string) => string | null;
535
+ };
536
+ json: () => Promise<any>;
537
+ };
538
+ networkMs: number;
539
+ method: string;
540
+ url: string;
541
+ }): Promise<any>;
542
+ protected getHttpBase(): string;
543
+ protected log(...args: any[]): void;
271
544
  constructor(config: FlareConfig);
272
- /**
273
- * Connect to the server
274
- */
275
545
  connect(): void;
276
- /**
277
- * Disconnect from the server
278
- */
279
546
  disconnect(): void;
280
- /**
281
- * Get a collection reference
282
- */
283
- collection<T = any>(name: string): CollectionReference<T>;
284
- /**
285
- * Get a document query builder (NEW ORM-style API)
286
- * @example flare.doc('users').update({...}).where({ id: 'alice' })
287
- */
288
- doc<T = any>(collection: string): DocumentQueryBuilder<T>;
289
- /**
290
- * Get a document reference (Legacy API - deprecated)
291
- * @deprecated Use doc(collection).where({ id: '...' }) instead
292
- */
293
- doc<T = any>(collection: string, id: string): DocumentReference<T>;
294
- /**
295
- * Authenticate with a token
296
- */
297
- auth(token: string): Promise<AuthResult>;
298
- /**
299
- * Sign out
300
- */
301
- signOut(): void;
302
- /**
303
- * Get current user ID
304
- */
305
- get currentUser(): string | undefined;
306
- /**
307
- * Get connection state
308
- */
309
547
  get connectionState(): ConnectionState;
310
- /**
311
- * Check if connected
312
- */
313
548
  get isConnected(): boolean;
314
- /**
315
- * Listen to connection state changes
316
- */
317
549
  onConnectionStateChange(listener: ConnectionListener): () => void;
550
+ onError(callback: ErrorListener): () => void;
551
+ collection<T = any>(name: string): CollectionReference<T>;
552
+ doc<T = any>(collection: string): DocumentQueryBuilder<T>;
553
+ doc<T = any>(collection: string, id: string): DocumentReference<T>;
554
+ ping(): Promise<number>;
555
+ call<T = Record<string, unknown>>(topic: string, payload?: Record<string, unknown>): Promise<T>;
556
+ query<T = Record<string, unknown>>(collection: string, q?: StructuredQuery): Promise<T[]>;
557
+ setEmbedder(fn: EmbedFn): void;
558
+ markVectorField(collection: string, field: string, config?: VectorFieldConfig): void;
559
+ embedVectorFields(collection: string, data: Record<string, unknown>): Promise<Record<string, unknown>>;
560
+ joinPresence(room: string, meta?: Record<string, unknown>): Promise<() => void>;
561
+ leavePresence(room: string): Promise<void>;
562
+ onPresenceState(room: string, cb: PresenceCallback): () => void;
563
+ onPresenceJoin(room: string, cb: PresenceJoinCallback): () => void;
564
+ onPresenceLeave(room: string, cb: PresenceLeaveCallback): () => void;
565
+ private _startPresenceHeartbeat;
566
+ private _stopPresenceHeartbeat;
567
+ syncOffline(): Promise<void>;
568
+ protected activateSubscription(entry: ActiveSubscription): Promise<void>;
569
+ protected replayActiveSubscriptions(): Promise<void>;
570
+ subscribe(subId: string, collection: string, docId: string | undefined, query: QueryConfig | StructuredQuery | undefined, callback: SubscriptionCallback, options?: SubscribeOptions): () => void;
571
+ send(type: FlareAction, payload: any): Promise<any>;
572
+ private handleTransportError;
573
+ protected onConnected(): void;
574
+ protected onDisconnected(): void;
575
+ protected setState(state: ConnectionState): void;
576
+ protected handleIncoming(msg: any): void;
577
+ }
578
+
579
+ /**
580
+ * FlareAuth extends FlareBase with all authentication and CSRF logic.
581
+ *
582
+ * CSRF strategy
583
+ * ─────────────
584
+ * The server sets an HttpOnly cookie on /auth/config responses. The raw
585
+ * cookie value is NOT readable by JS (HttpOnly), but the server also echoes
586
+ * the token in the `x-flare-csrf` response header so the client can send
587
+ * it back as `x-flare-csrf` on every mutating request.
588
+ *
589
+ * Two environments are supported:
590
+ * 1. Browser – header is read from the /auth/config fetch; stored in
591
+ * `this.csrfToken` (in-memory only, never written to a
592
+ * readable cookie by the client).
593
+ * 2. Next.js SSR – use the standalone `createCsrfProxy()` handler
594
+ * (see Client/proxy.ts) which captures the Set-Cookie header
595
+ * from Flare server and sets it on the client domain too, so
596
+ * the browser owns two HttpOnly cookies: one from the Flare
597
+ * domain and one from the Next.js domain.
598
+ */
599
+ declare class FlareAuth extends FlareBase {
600
+ protected authToken?: string;
601
+ protected userId?: string;
602
+ protected authGuard?: AuthGuard;
603
+ protected authConfig?: FlareAuthConfig;
604
+ /** In-memory CSRF token extracted from the `x-flare-csrf` response header */
605
+ protected csrfToken?: string;
606
+ protected csrfInitPromise?: Promise<void>;
607
+ protected csrfBootstrapAttempted: boolean;
608
+ protected authSession: FlareAuthSession | null;
609
+ protected authStateListeners: AuthStateListener[];
610
+ protected authConfigListeners: AuthConfigListener[];
611
+ private getDefaultCsrfCookieName;
612
+ getCsrfCookieName(): string;
318
613
  /**
319
- * Listen to errors
614
+ * Read the CSRF token from a browser-readable cookie (set by the server as
615
+ * a non-HttpOnly fallback) or fall back to the in-memory value captured
616
+ * from the response header.
617
+ *
618
+ * Priority:
619
+ * 1. Non-HttpOnly cookie on the current domain (browser only)
620
+ * 2. In-memory value from `x-flare-csrf` response header
320
621
  */
321
- onError(callback: ErrorListener): () => void;
622
+ getCsrfToken(): string | null;
623
+ private getCookieValue;
322
624
  /**
323
- * Ping the server
625
+ * Extract CSRF token from a server response.
626
+ * The server now sends it ONLY as the `x-flare-csrf` response header
627
+ * (not in the JSON body). We still support the body field as a fallback
628
+ * for older server versions.
324
629
  */
325
- ping(): Promise<number>;
630
+ protected extractCsrfToken(json: unknown, response?: {
631
+ headers: {
632
+ get: (name: string) => string | null;
633
+ };
634
+ }): string | undefined;
635
+ getCsrfHeaders(): Record<string, string>;
326
636
  /**
327
- * Invoke a server-side CALL handler by topic and await its response.
637
+ * Inject CSRF token directly (used by SSR middleware).
638
+ * This allows the server to bootstrap CSRF once and inject it into the client,
639
+ * preventing redundant /auth/config calls.
328
640
  *
329
641
  * @example
330
- * const result = await flare.call("agent:backup", { name: "db-daily" });
331
- * console.log(result.jobId);
332
- *
333
- * @param topic The topic registered with `flare.registerCallHandler(topic, fn)` on the server.
334
- * @param payload Arbitrary JSON payload forwarded to the handler.
335
- * @returns The object returned by the server handler.
336
- * @throws If the server returns `success: false` or the request times out.
337
- */
338
- call<T = Record<string, unknown>>(topic: string, payload?: Record<string, unknown>): Promise<T>;
339
- /**
340
- * Sync offline operations
642
+ * // In Next.js middleware
643
+ * const csrf = extractCsrfFromRequest(request, appId);
644
+ * if (csrf) {
645
+ * flareClient.setCsrfToken(csrf);
646
+ * }
341
647
  */
342
- syncOffline(): Promise<void>;
343
- private handleTransportError;
344
- private onConnected;
345
- private onDisconnected;
346
- private setState;
347
- private handleIncoming;
648
+ setCsrfToken(token: string): void;
649
+ ensureCsrfProtection(): Promise<void>;
650
+ loadAuthConfig(): Promise<FlareAuthConfig>;
651
+ protected fetchAuthConfig(): Promise<FlareAuthConfig>;
652
+ onAuthConfigLoaded(listener: AuthConfigListener): () => void;
653
+ protected setAuthSession(session: FlareAuthSession | null): void;
654
+ onAuthStateChanged(listener: AuthStateListener): () => void;
655
+ onAuthStateChange(listener: AuthStateListener): () => void;
656
+ get currentUser(): string | undefined;
657
+ getCurrentUser(): string | undefined;
658
+ protected syncSocketAuth(accessToken?: string | null): Promise<void>;
659
+ protected updateSocketIdentity(uid?: string, forceReplay?: boolean): Promise<void>;
660
+ protected onConnected(): void;
661
+ protected handleIncoming(msg: any): void;
662
+ auth(token: string): Promise<AuthResult>;
663
+ signInWithEmailAndPassword(email: string, password: string, options?: {
664
+ scope?: string[];
665
+ createIfMissing?: boolean;
666
+ }): Promise<AuthResult & {
667
+ kind?: string;
668
+ accessToken: string;
669
+ refreshToken: string | null;
670
+ authToken: AuthToken;
671
+ created?: boolean;
672
+ }>;
673
+ signInWithEmail(email: string, password: string, options?: {
674
+ scope?: string[];
675
+ createIfMissing?: boolean;
676
+ }): Promise<AuthResult & {
677
+ kind?: string;
678
+ accessToken: string;
679
+ refreshToken: string | null;
680
+ authToken: AuthToken;
681
+ created?: boolean;
682
+ }>;
683
+ createUserWithEmail(email: string, password: string, options?: {
684
+ scope?: string[];
685
+ additionalParams?: Record<string, string>;
686
+ signInIfAllowed?: boolean;
687
+ }): Promise<{
688
+ kind?: string;
689
+ verificationRequired: true;
690
+ emailSent: boolean;
691
+ preview?: {
692
+ code: string;
693
+ link: string;
694
+ };
695
+ } | (AuthResult & {
696
+ kind?: string;
697
+ accessToken: string;
698
+ refreshToken: string | null;
699
+ authToken: AuthToken;
700
+ verificationRequired?: false;
701
+ emailSent?: boolean;
702
+ preview?: {
703
+ code: string;
704
+ link: string;
705
+ };
706
+ })>;
707
+ createUserWithEmailAndPassword(email: string, password: string, options?: {
708
+ scope?: string[];
709
+ additionalParams?: Record<string, string>;
710
+ signInIfAllowed?: boolean;
711
+ }): Promise<{
712
+ kind?: string;
713
+ verificationRequired: true;
714
+ emailSent: boolean;
715
+ preview?: {
716
+ code: string;
717
+ link: string;
718
+ };
719
+ } | (AuthResult & {
720
+ kind?: string;
721
+ accessToken: string;
722
+ refreshToken: string | null;
723
+ authToken: AuthToken;
724
+ verificationRequired?: false;
725
+ emailSent?: boolean;
726
+ preview?: {
727
+ code: string;
728
+ link: string;
729
+ };
730
+ })>;
731
+ signInOrCreateWithEmail(email: string, password: string, options?: {
732
+ scope?: string[];
733
+ additionalParams?: Record<string, string>;
734
+ }): Promise<{
735
+ kind?: string;
736
+ verificationRequired: true;
737
+ created: true;
738
+ emailSent: boolean;
739
+ preview?: {
740
+ code: string;
741
+ link: string;
742
+ };
743
+ } | (AuthResult & {
744
+ accessToken: string;
745
+ refreshToken: string | null;
746
+ authToken: AuthToken;
747
+ created: boolean;
748
+ })>;
749
+ signInOrCreateWithEmailAndPassword(email: string, password: string, options?: {
750
+ scope?: string[];
751
+ additionalParams?: Record<string, string>;
752
+ }): Promise<{
753
+ kind?: string;
754
+ verificationRequired: true;
755
+ created: true;
756
+ emailSent: boolean;
757
+ preview?: {
758
+ code: string;
759
+ link: string;
760
+ };
761
+ } | (AuthResult & {
762
+ accessToken: string;
763
+ refreshToken: string | null;
764
+ authToken: AuthToken;
765
+ created: boolean;
766
+ })>;
767
+ sendEmailVerification(email: string): Promise<{
768
+ sent: boolean;
769
+ emailSent: boolean;
770
+ preview?: {
771
+ code: string;
772
+ link: string;
773
+ };
774
+ }>;
775
+ verifyEmailWithCode(email: string, code: string): Promise<{
776
+ verified: boolean;
777
+ email: string;
778
+ }>;
779
+ confirmEmailLink(token: string, email: string): Promise<{
780
+ verified: boolean;
781
+ email: string;
782
+ }>;
783
+ sendAccountRecovery(email: string): Promise<{
784
+ sent: boolean;
785
+ emailSent?: boolean;
786
+ preview?: {
787
+ code: string;
788
+ token: string;
789
+ };
790
+ }>;
791
+ recoverAccountWithCode(email: string, code: string, newPassword: string): Promise<{
792
+ recovered: boolean;
793
+ email: string;
794
+ sessionsRevoked?: number;
795
+ }>;
796
+ recoverAccountWithToken(token: string, newPassword: string): Promise<{
797
+ recovered: boolean;
798
+ email: string;
799
+ sessionsRevoked?: number;
800
+ }>;
801
+ signIn(providerId: ProviderId, options?: {
802
+ returnTo?: string;
803
+ metaTag?: string;
804
+ }): Promise<any>;
805
+ signIn(authGuard: Pick<AuthGuard, 'signIn'>, providerId: ProviderId, options?: {
806
+ returnTo?: string;
807
+ metaTag?: string;
808
+ }): Promise<any>;
809
+ signInWithGoogle(options?: {
810
+ returnTo?: string;
811
+ metaTag?: string;
812
+ }): Promise<any>;
813
+ signInWithGitHub(options?: {
814
+ returnTo?: string;
815
+ metaTag?: string;
816
+ }): Promise<any>;
817
+ signInWithFacebook(options?: {
818
+ returnTo?: string;
819
+ metaTag?: string;
820
+ }): Promise<any>;
821
+ signInWithDropbox(options?: {
822
+ returnTo?: string;
823
+ metaTag?: string;
824
+ }): Promise<any>;
825
+ handleSignInRedirect(autoRedirect?: boolean): Promise<(AuthResult & {
826
+ authToken: AuthToken;
827
+ provider?: ProviderId;
828
+ }) | null>;
829
+ handleSignInRedirect(authGuard: Pick<AuthGuard, 'handleRedirect'>, autoRedirect?: boolean): Promise<(AuthResult & {
830
+ authToken: AuthToken;
831
+ provider?: ProviderId;
832
+ }) | null>;
833
+ private exchangeProviderToken;
834
+ protected getAuthGuard(): Promise<AuthGuard>;
835
+ refreshAuthSession(refresh_token?: string): Promise<FlareAuthSession | null>;
836
+ issueSsrToken(ttlSeconds?: number): Promise<{
837
+ token: string;
838
+ token_type: string;
839
+ expires_in: number;
840
+ uid: string;
841
+ role: string;
842
+ email?: string;
843
+ }>;
844
+ signOut(): Promise<void>;
845
+ protected registerWithEmail(email: string, password: string, options?: {
846
+ scope?: string[];
847
+ additionalParams?: Record<string, string>;
848
+ signInIfAllowed?: boolean;
849
+ }): Promise<Record<string, any>>;
850
+ protected requestEmailPasswordToken(email: string, password: string, scope?: string[]): Promise<AuthToken>;
851
+ protected fetchAuthMe(token: string): Promise<{
852
+ id?: string;
853
+ email?: string | null;
854
+ email_verified?: boolean;
855
+ }>;
856
+ }
857
+
858
+ /**
859
+ * Client/index.ts ─ entry point
860
+ *
861
+ * FlareClient is the public-facing class. All logic lives in:
862
+ * - Client/base.ts → transport, subscriptions, presence, vector, offline
863
+ * - Client/auth.ts → CSRF capture, all auth & session methods
864
+ *
865
+ * CSRF Protection (SSR-Only by Default)
866
+ * ────────────────────────────────────
867
+ * FlareClient does NOT automatically fetch CSRF on construction. Instead:
868
+ *
869
+ * 1. SSR (Next.js): Middleware fetches /auth/config once, sets CSRF as HttpOnly
870
+ * cookie on response. Methods automatically use this cookie (no extra calls).
871
+ *
872
+ * 2. Browser-only (SPA): Explicitly call client.ensureCsrfProtection() before
873
+ * mutations to fetch /auth/config and cache CSRF token in memory.
874
+ *
875
+ * Why? Eliminates redundant /auth/config calls in SSR, where every method used
876
+ * to fetch it again internally. Now CSRF bootstrapping happens once (in middleware),
877
+ * and auth methods just use getCsrfHeaders() which returns the cached token
878
+ * (if available) or empty object (relying on HttpOnly cookie validation).
879
+ *
880
+ * This file wires FlareAuth together and leaves CSRF bootstrapping to the user.
881
+ */
882
+
883
+ declare class FlareClient extends FlareAuth {
884
+ constructor(config: FlareConfig);
885
+ }
886
+
887
+ /**
888
+ * Client/proxy.ts ─ Next.js SSR CSRF proxy helper
889
+ *
890
+ * Why this exists
891
+ * ───────────────
892
+ * The Flare server now sets the CSRF token exclusively as an HttpOnly cookie
893
+ * on its own domain (e.g. api.flare.example.com) and also echoes it in the
894
+ * `x-flare-csrf` response header so the browser client can capture it in-
895
+ * memory and send it back as a request header.
896
+ *
897
+ * When your Next.js app runs server-side rendering (SSR / Route Handlers /
898
+ * Server Actions) it operates on a *different* domain (e.g. app.example.com).
899
+ * The browser's HttpOnly Flare cookie is scoped to the Flare domain and is
900
+ * therefore NOT automatically forwarded by the browser to your Next.js
901
+ * server-side fetch calls.
902
+ *
903
+ * Solution — two-cookie strategy
904
+ * ────────────────────────────────
905
+ * 1. Browser → Flare domain : Flare sets `__flare_csrf_<appId>` as HttpOnly
906
+ * on the Flare domain. Browser also reads the
907
+ * token from the `x-flare-csrf` header and keeps
908
+ * it in-memory for direct API calls.
909
+ *
910
+ * 2. Browser → Next.js domain : Mount `createCsrfProxy()` at a route such as
911
+ * `/api/flare/csrf`. On first browser load call
912
+ * this route; it hits Flare's /auth/config,
913
+ * reads the `x-flare-csrf` header, and sets
914
+ * it as an HttpOnly cookie on the *Next.js*
915
+ * domain too (`__flare_csrf_<appId>`).
916
+ * All subsequent SSR fetch calls from the
917
+ * Next.js server can then read this cookie from
918
+ * the incoming request and forward it as the
919
+ * `x-flare-csrf` header to Flare.
920
+ *
921
+ * Usage (Next.js App Router)
922
+ * ─────────────────────────────
923
+ * // app/api/flare/csrf/route.ts
924
+ * import { createCsrfProxy } from "@zuzjs/flare-client/proxy";
925
+ * export const GET = createCsrfProxy({ endpoint: "https://api.flare.example.com", appId: "my-app" });
926
+ *
927
+ * // In any Server Component / Route Handler:
928
+ * import { extractCsrfFromRequest, buildFlareHeaders } from "@zuzjs/flare-client/proxy";
929
+ * const csrf = extractCsrfFromRequest(request, "my-app");
930
+ * const res = await withGet(`${FLARE}/auth/whatever`, { headers: buildFlareHeaders(csrf), ignoreKind: true });
931
+ *
932
+ * Usage (Next.js Pages Router)
933
+ * ──────────────────────────────
934
+ * // pages/api/flare/csrf.ts
935
+ * import { createCsrfProxyHandler } from "@zuzjs/flare-client/proxy";
936
+ * export default createCsrfProxyHandler({ endpoint: "...", appId: "my-app" });
937
+ */
938
+ interface CsrfProxyConfig {
939
+ /** Base URL of the Flare server, e.g. "https://api.flare.example.com" */
940
+ endpoint: string;
941
+ /** App ID passed to Flare's /auth/config */
942
+ appId: string;
943
+ /** Optional Flare API key */
944
+ apiKey?: string;
348
945
  /**
349
- * Internal: Send message to server
946
+ * Name of the proxy cookie written on the Next.js domain.
947
+ * Defaults to `__flare_csrf_<appId>`.
350
948
  */
351
- send(type: FlareAction, payload: any): Promise<any>;
949
+ proxyCookieName?: string;
352
950
  /**
353
- * Internal: Create a subscription
951
+ * Max-Age for the proxy cookie in seconds.
952
+ * Defaults to 3600 (1 hour).
354
953
  */
355
- subscribe(subId: string, collection: string, docId: string | undefined, query: QueryConfig | undefined, callback: SubscriptionCallback): () => void;
356
- private log;
954
+ proxyCookieMaxAge?: number;
357
955
  }
956
+ /**
957
+ * Creates a Next.js App Router `GET` handler that:
958
+ * 1. Calls Flare's /auth/config and captures the `x-flare-csrf` header.
959
+ * 2. Sets it as `__flare_csrf_<appId>` HttpOnly cookie on the current domain.
960
+ * 3. Returns the token in JSON for the browser to store in-memory as well.
961
+ *
962
+ * Mount at: `app/api/flare/csrf/route.ts`
963
+ */
964
+ declare function createCsrfProxy(config: CsrfProxyConfig): (_request: Request) => Promise<Response>;
965
+ /**
966
+ * Creates a Next.js Pages Router API handler (`pages/api/flare/csrf.ts`).
967
+ * Same behaviour as `createCsrfProxy()` but uses the Node.js req/res API.
968
+ */
969
+ declare function createCsrfProxyHandler(config: CsrfProxyConfig): (req: any, res: any) => Promise<void>;
970
+ /**
971
+ * Extract the proxied CSRF token from an incoming Next.js request's cookies.
972
+ *
973
+ * Call this inside Server Components, Route Handlers, or `getServerSideProps`
974
+ * to retrieve the token that was set by `createCsrfProxy`.
975
+ *
976
+ * @example
977
+ * // App Router Route Handler
978
+ * const csrf = extractCsrfFromRequest(request, "my-app");
979
+ */
980
+ declare function extractCsrfFromRequest(request: Request | {
981
+ cookies: Record<string, string> | {
982
+ get(name: string): {
983
+ value: string;
984
+ } | undefined;
985
+ };
986
+ }, appId: string, proxyCookieName?: string): string | null;
987
+ /**
988
+ * Build the headers object to attach to a server-side fetch call to Flare,
989
+ * forwarding the CSRF token and (optionally) the Authorization bearer token.
990
+ */
991
+ declare function buildFlareHeaders(csrfToken: string | null, options?: {
992
+ accessToken?: string;
993
+ apiKey?: string;
994
+ }): Record<string, string>;
358
995
 
359
996
  declare class FlareError extends Error {
360
997
  readonly code: string;
@@ -362,6 +999,65 @@ declare class FlareError extends Error {
362
999
  constructor(message: string, code: string, cause?: unknown | undefined);
363
1000
  }
364
1001
 
1002
+ declare enum FlareErrors {
1003
+ authEmailNotVerified = "auth/email-not-verified",
1004
+ authEmailAlreadyVerified = "auth/email-already-verified",
1005
+ authInvalidToken = "auth/invalid-token",
1006
+ authUserDisabled = "auth/user-disabled",
1007
+ authUserNotFound = "auth/user-not-found",
1008
+ authWrongPassword = "auth/wrong-password",
1009
+ authEmailAlreadyInUse = "auth/email-already-in-use",
1010
+ authInvalidEmail = "auth/invalid-email",
1011
+ authWeakPassword = "auth/weak-password",
1012
+ authTooManyRequests = "auth/too-many-requests",
1013
+ authInternalError = "auth/internal-error"
1014
+ }
1015
+
1016
+ declare enum FlareResponseCodes {
1017
+ health = "health",
1018
+ authConfig = "auth_config",
1019
+ authRegistration = "auth/registration",
1020
+ authRegistrationVerificationRequired = "auth/registration-verification-required",
1021
+ authSession = "auth/session",
1022
+ authExchange = "auth/exchange",
1023
+ authLogout = "auth/logout",
1024
+ authSsrBridge = "auth/ssr_bridge",
1025
+ authSsrVerify = "auth/ssr_verify",
1026
+ accountRecovery = "account/recovery",
1027
+ emailVerification = "email/verification",
1028
+ verificationDispatch = "verification/dispatch",
1029
+ authProfile = "auth/profile",
1030
+ adminToken = "admin/token",
1031
+ documentDelete = "document/delete",
1032
+ documentsDelete = "documents/delete",
1033
+ documents = "documents",
1034
+ document = "document",
1035
+ documentCreate = "document/create",
1036
+ documentUpdate = "document/update",
1037
+ oauthProviderResponse = "oauth_provider_response",
1038
+ success = "success",
1039
+ response = "response"
1040
+ }
1041
+ interface AuthConfigResponse {
1042
+ kind: string;
1043
+ appId: string;
1044
+ enabled: boolean;
1045
+ csrfToken?: string;
1046
+ cookie: {
1047
+ accessTokenName: string;
1048
+ refreshTokenName: string;
1049
+ csrfTokenName: string;
1050
+ path: string;
1051
+ secure: boolean;
1052
+ sameSite: 'Strict' | 'Lax' | 'None';
1053
+ accessTokenMaxAge: number;
1054
+ refreshTokenMaxAge: number;
1055
+ csrfTokenMaxAge: number;
1056
+ };
1057
+ providers: Record<string, any>;
1058
+ ssr: Record<string, any>;
1059
+ }
1060
+
365
1061
  /**
366
1062
  * Initialize and connect to FlareServer
367
1063
  * Returns a singleton instance
@@ -376,4 +1072,4 @@ declare const getFlare: () => FlareClient | null;
376
1072
  */
377
1073
  declare const disconnectFlare: () => void;
378
1074
 
379
- export { type AuthResult, type BaseMessage, CollectionReference, type ConnectionState, DocumentQueryBuilder, DocumentReference, type DocumentSnapshot, FlareAction, type FlareConfig, FlareError, FlareEvent, type OfflineOperation, type QueryConfig, type QueryOperator, type QuerySnapshot, type SubscriptionCallback, type SubscriptionData, type WhereCondition, connectApp, FlareClient as default, disconnectFlare, getFlare };
1075
+ export { type AggregateFunction, type AggregateSpec, type AnyFilter, type AuthConfigListener, type AuthConfigResponse, type AuthResult, type AuthStateListener, type AuthWithPendingVerificationResult, type AuthWithTokenResult, type BaseMessage, type ChangeEvent, type ChangeOperation, CollectionReference, type ConnectionState, type CsrfProxyConfig, type CursorValue, type DocAddedCallback, type DocChangedCallback, type DocDeletedCallback, type DocUpdatedCallback, DocumentQueryBuilder, DocumentReference, type DocumentSnapshot, FlareAction, type FlareAuthConfig, type FlareAuthProviderId, type FlareAuthProviderPublicConfig, type FlareAuthSession, type FlareConfig, FlareError, FlareErrors, FlareEvent, FlareResponseCodes, type GroupByClause, type HavingClause, type JoinClause, type OfflineOperation, type OrFilter, type OrderByClause, type PresenceCallback, type PresenceJoinCallback, type PresenceLeaveCallback, type PresenceMember, type QueryConfig, type QueryOperator, type QuerySnapshot, type SnapshotEvent, type StructuredQuery, type SubscribeMessage, type SubscribeOptions, type SubscriptionCallback, type SubscriptionData, type VectorFieldConfig, type VectorSearchClause, type WhereCondition, buildFlareHeaders, connectApp, createCsrfProxy, createCsrfProxyHandler, FlareClient as default, disconnectFlare, extractCsrfFromRequest, getFlare, parseValue, parseWhereCondition };