@zuzjs/flare 0.2.2 → 0.2.5

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.ts CHANGED
@@ -5,6 +5,7 @@ export { Anonymous, Apple, AuthGuard, AuthToken, CreateUserWithEmailAndPasswordI
5
5
  * Client Configuration
6
6
  */
7
7
  interface FlareConfig {
8
+ /** Base URL for the Flare API. */
8
9
  endpoint: string;
9
10
  /**
10
11
  * Optional HTTP base URL for auth API calls.
@@ -14,15 +15,26 @@ interface FlareConfig {
14
15
  * Example: '/api/flare' (relative, browser resolves against current origin)
15
16
  */
16
17
  httpBase?: string;
18
+ /** Unique identifier for the application. */
17
19
  appId: string;
20
+ /** API key for the application. */
18
21
  apiKey?: string;
22
+ /** Public key for the application. */
19
23
  publicKey?: string;
24
+ /** Whether to automatically reconnect on connection loss. */
20
25
  autoReconnect?: boolean;
26
+ /** Delay between reconnection attempts in milliseconds. */
21
27
  reconnectDelay?: number;
28
+ /** Maximum delay between reconnection attempts in milliseconds. */
22
29
  maxReconnectDelay?: number;
30
+ /** Enable or disable debug mode. */
23
31
  debug?: boolean;
32
+ /** Enable or disable request timing. */
24
33
  requestTiming?: boolean;
34
+ /** Connection timeout in milliseconds. */
25
35
  connectionTimeout?: number;
36
+ /** Enable automatic push notification registration on supported platforms. */
37
+ pushNotifications?: boolean;
26
38
  }
27
39
  type FlareAuthProviderId = "credentials" | "anonymous" | "google" | "facebook" | "github" | "dropbox" | "apple" | "twitter";
28
40
  interface FlareAuthProviderPublicConfig {
@@ -59,7 +71,93 @@ interface FlareAuthSession {
59
71
  email?: string | null;
60
72
  emailVerified?: boolean;
61
73
  }
62
- type AuthStateListener = (session: FlareAuthSession | null) => void;
74
+ interface FlareAuthUser {
75
+ uid: string;
76
+ email: string;
77
+ email_verified: string;
78
+ [x: string]: any;
79
+ }
80
+ interface RegisterPushTokenInput {
81
+ token: string;
82
+ platform?: string;
83
+ deviceId?: string;
84
+ topics?: string[];
85
+ authAppId?: string;
86
+ }
87
+ interface BrowserPushTokenOptions {
88
+ /** Service worker registration used for PushManager subscription. */
89
+ serviceWorkerRegistration?: ServiceWorkerRegistration;
90
+ /** Existing PushSubscription to reuse instead of subscribing again. */
91
+ subscription?: PushSubscription;
92
+ /** Public VAPID key used when creating a new PushSubscription. */
93
+ applicationServerKey?: string;
94
+ /** When true, unsubscribe old subscriptions before creating a new one. */
95
+ forceResubscribe?: boolean;
96
+ }
97
+ interface BrowserPushRegistrationOptions extends BrowserPushTokenOptions {
98
+ /** Optional explicit platform label. Defaults to "web". */
99
+ platform?: string;
100
+ deviceId?: string;
101
+ topics?: string[];
102
+ authAppId?: string;
103
+ }
104
+ interface SendPushNotificationInput {
105
+ title?: string;
106
+ body?: string;
107
+ image?: string;
108
+ data?: Record<string, unknown>;
109
+ tokens?: string[];
110
+ uid?: string;
111
+ topic?: string;
112
+ priority?: "normal" | "high";
113
+ ttlSeconds?: number;
114
+ dryRun?: boolean;
115
+ authAppId?: string;
116
+ }
117
+ interface PushSendResult {
118
+ sent: boolean;
119
+ appId: string;
120
+ targetCount: number;
121
+ successCount: number;
122
+ failureCount: number;
123
+ invalidatedTokenCount: number;
124
+ dryRun: boolean;
125
+ }
126
+ interface SendEmailInput {
127
+ to: string | string[];
128
+ tag: string;
129
+ values?: Record<string, unknown>;
130
+ authAppId?: string;
131
+ }
132
+ interface EmailSendResult {
133
+ sent: boolean;
134
+ appId: string;
135
+ tag: string;
136
+ recipientCount: number;
137
+ acceptedCount: number;
138
+ rejectedCount: number;
139
+ includeVerificationLink?: boolean;
140
+ linkId?: string;
141
+ verifyUrl?: string;
142
+ messageId?: string;
143
+ }
144
+ interface VerifyEmailLinkInput {
145
+ token: string;
146
+ tag?: string;
147
+ email?: string;
148
+ authAppId?: string;
149
+ }
150
+ interface EmailLinkVerifyResult {
151
+ verified: boolean;
152
+ alreadyVerified: boolean;
153
+ appId: string;
154
+ linkId: string;
155
+ email: string;
156
+ tag: string;
157
+ verifiedAt?: string;
158
+ acceptedByUid?: string;
159
+ }
160
+ type AuthStateListener = (session: FlareAuthSession & FlareAuthUser | null) => void;
63
161
  type AuthConfigListener = (conf: FlareAuthConfig) => void;
64
162
  interface SubscribeOptions {
65
163
  skipSnapshot?: boolean;
@@ -97,12 +195,62 @@ interface AggregateSpec {
97
195
  field?: string;
98
196
  alias?: string;
99
197
  }
100
- interface JoinClause {
198
+ /**
199
+ * Join definition used by CollectionReference.Join().
200
+ *
201
+ * Example:
202
+ * Join("tasks", { source: "id", target: "boardId", as: "tasks" })
203
+ */
204
+ interface JoinQueryPattern {
205
+ where?: AnyFilter[];
206
+ orderBy?: OrderByClause[];
207
+ limit?: number;
208
+ offset?: number;
209
+ startAt?: CursorValue;
210
+ startAfter?: CursorValue;
211
+ endAt?: CursorValue;
212
+ endBefore?: CursorValue;
213
+ aggregate?: AggregateSpec[];
214
+ groupBy?: GroupByClause;
215
+ having?: HavingClause[];
216
+ vectorSearch?: VectorSearchClause;
217
+ select?: string[];
218
+ distinctField?: string;
219
+ }
220
+ interface NestedJoinClause extends JoinQueryPattern {
221
+ /** Joined collection name for this nested join. */
222
+ collection: string;
223
+ /** Field from the parent join result. */
224
+ source: string;
225
+ /** Field from this nested collection to match source. */
226
+ target: string;
227
+ /** Alias where nested rows are attached in each parent join row. */
228
+ as: string;
229
+ /** If true, expect at most one joined row. */
230
+ single?: boolean;
231
+ /** Recursive nested joins. */
232
+ joins?: NestedJoinClause[];
233
+ }
234
+ interface JoinClause extends JoinQueryPattern {
235
+ /** Field from the base collection (the collection you started the query on). */
236
+ source: string;
237
+ /** Field from the joined collection that should match source. */
238
+ target: string;
239
+ /** Alias where joined rows will be attached in each result object. */
240
+ as: string;
241
+ /** If true, expect at most one joined row (object instead of array on server side). */
242
+ single?: boolean;
243
+ /** Optional nested joins under this join. */
244
+ joins?: NestedJoinClause[];
245
+ }
246
+ /** Internal wire-ready join shape sent to server query engine. */
247
+ interface StructuredJoinClause extends JoinQueryPattern {
101
248
  from: string;
102
249
  localField: string;
103
250
  foreignField: string;
104
251
  as: string;
105
252
  single?: boolean;
253
+ joins?: StructuredJoinClause[];
106
254
  }
107
255
  interface VectorSearchClause {
108
256
  field: string;
@@ -111,7 +259,7 @@ interface VectorSearchClause {
111
259
  metric?: "cosine" | "euclidean" | "dotProduct";
112
260
  minScore?: number;
113
261
  }
114
- /** Full structured query (Firestore + SQL feature set) */
262
+ /** Full structured query (document query + SQL-style feature set) */
115
263
  interface StructuredQuery {
116
264
  where?: AnyFilter[];
117
265
  orderBy?: OrderByClause[];
@@ -124,11 +272,18 @@ interface StructuredQuery {
124
272
  aggregate?: AggregateSpec[];
125
273
  groupBy?: GroupByClause;
126
274
  having?: HavingClause[];
127
- joins?: JoinClause[];
275
+ joins?: StructuredJoinClause[];
128
276
  vectorSearch?: VectorSearchClause;
129
277
  select?: string[];
130
278
  distinctField?: string;
131
279
  }
280
+ type QueryPresetSpec<Params extends Record<string, unknown> = Record<string, unknown>, Row = any> = {
281
+ params: Params;
282
+ row: Row;
283
+ };
284
+ type QueryPresetMap = Record<string, QueryPresetSpec<any, any>>;
285
+ type QueryPresetParams<TSpec> = TSpec extends QueryPresetSpec<infer Params, any> ? Params : Record<string, unknown>;
286
+ type QueryPresetRow<TSpec> = TSpec extends QueryPresetSpec<any, infer Row> ? Row : any;
132
287
  type ChangeOperation = 'insert' | 'update' | 'replace' | 'delete';
133
288
  /**
134
289
  * Fired once when the subscription is first established.
@@ -155,6 +310,20 @@ interface ChangeEvent<T = any> {
155
310
  /** Discriminated union — narrow on `event.type` to get the right shape. */
156
311
  type SubscriptionData<T = any> = SnapshotEvent<T> | ChangeEvent<T>;
157
312
  type SubscriptionCallback<T = any> = (data: SubscriptionData<T>) => void;
313
+ interface SubscriptionError {
314
+ code?: string;
315
+ message: string;
316
+ permissionDenied: boolean;
317
+ raw?: unknown;
318
+ }
319
+ type SubscriptionErrorCallback = (error: SubscriptionError) => void;
320
+ interface SubscriptionHandle {
321
+ (): void;
322
+ unsubscribe: () => void;
323
+ onError: (callback: SubscriptionErrorCallback) => SubscriptionHandle;
324
+ onPermissionDenied: (callback: SubscriptionErrorCallback) => SubscriptionHandle;
325
+ catch: (callback: SubscriptionErrorCallback) => SubscriptionHandle;
326
+ }
158
327
  type DocAddedCallback<T = any> = (data: T, docId: string) => void;
159
328
  type DocUpdatedCallback<T = any> = (data: T, docId: string) => void;
160
329
  type DocDeletedCallback<T = any> = (docId: string) => void;
@@ -216,6 +385,26 @@ type VectorFieldConfig = {
216
385
  /** Optional custom embedding function; defaults to client-configured embedder */
217
386
  embed?: (text: string) => Promise<number[]>;
218
387
  };
388
+ type RulePermission = "create" | "read" | "update" | "delete";
389
+ interface FlareRule {
390
+ id: string;
391
+ name: string;
392
+ auth: "any" | "guest" | "auth";
393
+ collection: string;
394
+ document?: string;
395
+ condition?: string;
396
+ permissions: RulePermission[];
397
+ }
398
+ interface SecurityRuleEntry {
399
+ ".read"?: string;
400
+ ".write"?: string;
401
+ ".create"?: string;
402
+ ".update"?: string;
403
+ ".delete"?: string;
404
+ }
405
+ type SecurityRulesMap = Record<string, SecurityRuleEntry>;
406
+ declare const flareRulesToSecurityMap: (rules: FlareRule[]) => SecurityRulesMap;
407
+ declare const securityMapToFlareRules: (rules: SecurityRulesMap) => FlareRule[];
219
408
 
220
409
  /**
221
410
  * Parse ORM-style where condition: { age: ">= 25", role: "admin" }
@@ -244,7 +433,7 @@ declare class DocumentQueryBuilder<T = any> implements PromiseLike<T | null | vo
244
433
  private setData?;
245
434
  private deleteOp;
246
435
  private promise?;
247
- constructor(client: FlareClient, collection: string, legacyId?: string | undefined);
436
+ constructor(client: FlareClient<any>, collection: string, legacyId?: string | undefined);
248
437
  /**
249
438
  * Set where condition
250
439
  */
@@ -295,7 +484,7 @@ declare class DocumentReference<T = any> {
295
484
  private client;
296
485
  readonly collection: string;
297
486
  readonly id: string;
298
- constructor(client: FlareClient, collection: string, id: string);
487
+ constructor(client: FlareClient<any>, collection: string, id: string);
299
488
  get(): Promise<T | null>;
300
489
  set(data: Partial<T>): Promise<void>;
301
490
  update(data: Partial<T>): Promise<void>;
@@ -321,46 +510,76 @@ declare class DocumentReference<T = any> {
321
510
  onDocChanged(callback: DocChangedCallback<T>): () => void;
322
511
  }
323
512
 
324
- declare class CollectionReference<T = any> implements PromiseLike<T[]> {
513
+ type CollectionPresetMethods<TPresetMap extends QueryPresetMap> = {
514
+ [K in keyof TPresetMap & string]: (params: QueryPresetParams<TPresetMap[K]>) => CollectionQuery<QueryPresetRow<TPresetMap[K]>, TPresetMap>;
515
+ };
516
+ type CollectionQuery<T = any, TPresetMap extends QueryPresetMap = {}> = CollectionReference<T, TPresetMap> & CollectionPresetMethods<TPresetMap>;
517
+ declare class CollectionReference<T = any, TPresetMap extends QueryPresetMap = {}> implements PromiseLike<T[]> {
325
518
  private client;
326
519
  readonly collection: string;
327
520
  private sq;
328
521
  private promise?;
329
- constructor(client: FlareClient, collection: string);
522
+ constructor(client: FlareClient<TPresetMap>, collection: string);
330
523
  doc(id: string): DocumentReference<T>;
331
524
  private clone;
525
+ with<Name extends keyof TPresetMap & string>(name: Name, params: QueryPresetParams<TPresetMap[Name]>): CollectionQuery<QueryPresetRow<TPresetMap[Name]>, TPresetMap>;
526
+ with(name: string, params?: Record<string, unknown>): CollectionQuery<T, TPresetMap>;
332
527
  /** ORM shorthand: .where({ age: ">= 25", role: "admin" }) */
333
- where(condition: WhereCondition): CollectionReference<T>;
528
+ where(condition: WhereCondition): CollectionQuery<T, TPresetMap>;
334
529
  /** Explicit field/op/value */
335
- where(field: string, op: QueryConfig['op'], value: unknown): CollectionReference<T>;
530
+ where(field: string, op: QueryConfig['op'], value: unknown): CollectionQuery<T, TPresetMap>;
336
531
  /** 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>;
532
+ orWhere(filters: QueryConfig[]): CollectionQuery<T, TPresetMap>;
533
+ /** Get items starting from the most recently created (descending sequence) */
534
+ latest(): CollectionQuery<T, TPresetMap>;
535
+ /** Get items starting from the first ever created (ascending sequence) */
536
+ oldest(): CollectionQuery<T, TPresetMap>;
537
+ orderBy(field: string, dir?: "asc" | "desc"): CollectionQuery<T, TPresetMap>;
538
+ limit(n: number): CollectionQuery<T, TPresetMap>;
539
+ offset(n: number): CollectionQuery<T, TPresetMap>;
540
+ startAt(...values: unknown[]): CollectionQuery<T, TPresetMap>;
541
+ startAfter(...values: unknown[]): CollectionQuery<T, TPresetMap>;
542
+ endAt(...values: unknown[]): CollectionQuery<T, TPresetMap>;
543
+ endBefore(...values: unknown[]): CollectionQuery<T, TPresetMap>;
544
+ aggregate(...specs: AggregateSpec[]): CollectionQuery<T, TPresetMap>;
545
+ count(alias?: string): CollectionQuery<T, TPresetMap>;
546
+ sum(field: string, alias?: string): CollectionQuery<T, TPresetMap>;
547
+ avg(field: string, alias?: string): CollectionQuery<T, TPresetMap>;
548
+ min(field: string, alias?: string): CollectionQuery<T, TPresetMap>;
549
+ max(field: string, alias?: string): CollectionQuery<T, TPresetMap>;
550
+ distinct(field: string, alias?: string): CollectionQuery<T, TPresetMap>;
551
+ groupBy(...fields: string[]): CollectionQuery<T, TPresetMap>;
552
+ having(field: string, op: HavingClause['op'], value: number): CollectionQuery<T, TPresetMap>;
553
+ private buildStructuredJoin;
554
+ /**
555
+ * Join another collection into this query.
556
+ *
557
+ * @param collectionName Joined collection name.
558
+ * @param j Join mapping clause.
559
+ * @example
560
+ * flare.collection("boards")
561
+ * .Join("tasks", { source: "id", target: "boardId", as: "tasks" })
562
+ * .get();
563
+ */
564
+ Join(collectionName: string, j: JoinClause): CollectionQuery<T, TPresetMap>;
565
+ /**
566
+ * Legacy join signature.
567
+ * Prefer Join(collectionName, clause) for better readability.
568
+ */
569
+ join(collectionName: string, j: JoinClause): CollectionQuery<T, TPresetMap>;
570
+ join(j: JoinClause & {
571
+ from?: string;
572
+ collection?: string;
573
+ }): CollectionQuery<T, TPresetMap>;
574
+ select(...fields: string[]): CollectionQuery<T, TPresetMap>;
356
575
  /** Returns unique values for a single field */
357
- distinctField(field: string): CollectionReference<T>;
576
+ distinctField(field: string): CollectionQuery<T, TPresetMap>;
358
577
  /**
359
578
  * KNN nearest-neighbour search (requires Atlas vector index).
360
579
  * @example
361
580
  * col.vectorSearch({ field: "embedding", vector: [...1536 numbers...], k: 10 })
362
581
  */
363
- vectorSearch(opts: VectorSearchClause): CollectionReference<T>;
582
+ vectorSearch(opts: VectorSearchClause): CollectionQuery<T, TPresetMap>;
364
583
  get(): Promise<T[]>;
365
584
  private _isStructured;
366
585
  private _execute;
@@ -374,7 +593,7 @@ declare class CollectionReference<T = any> implements PromiseLike<T[]> {
374
593
  * Individual change events are then sorted / filtered client-side to keep
375
594
  * the live result consistent.
376
595
  */
377
- onSnapshot(callback: SubscriptionCallback<T[]>): () => void;
596
+ onSnapshot(callback: SubscriptionCallback<T[]>): SubscriptionHandle;
378
597
  onDocAdded(callback: DocAddedCallback<T>): () => void;
379
598
  onDocUpdated(callback: DocUpdatedCallback<T>): () => void;
380
599
  onDocModified(callback: DocUpdatedCallback<T>): () => void;
@@ -470,6 +689,11 @@ declare class FlareTransport {
470
689
 
471
690
  type ConnectionListener = (state: ConnectionState) => void;
472
691
  type ErrorListener = (error: Error) => void;
692
+ type HttpResponseSnapshot = {
693
+ status: number;
694
+ headers: Record<string, string>;
695
+ data: any;
696
+ };
473
697
  type ActiveSubscription = {
474
698
  baseId: string;
475
699
  liveId: string;
@@ -479,14 +703,19 @@ type ActiveSubscription = {
479
703
  callback: SubscriptionCallback;
480
704
  options: SubscribeOptions;
481
705
  };
706
+ type QueryPresetHandler<Params extends Record<string, unknown> = Record<string, unknown>, Row = any> = (ref: CollectionQuery<any, any>, params: Params) => CollectionQuery<Row, any>;
482
707
  /** Embedder function registered by the user */
483
708
  type EmbedFn = (text: string) => Promise<number[]>;
484
- declare class FlareBase {
709
+ declare class FlareBase<TPresetMap extends QueryPresetMap = {}> {
485
710
  protected transport: FlareTransport;
486
711
  protected readonly config: FlareConfig;
487
712
  protected readonly pendingAcks: Map<string, (value: any) => void>;
488
713
  protected readonly subscriptions: Map<string, SubscriptionCallback>;
489
714
  protected readonly activeSubscriptions: Map<string, ActiveSubscription>;
715
+ protected readonly queryPresets: Map<string, QueryPresetHandler<any, any>>;
716
+ protected readonly subscriptionErrorHandlers: Map<string, Set<SubscriptionErrorCallback>>;
717
+ protected readonly subscriptionPermissionHandlers: Map<string, Set<SubscriptionErrorCallback>>;
718
+ protected readonly subscriptionLastErrors: Map<string, SubscriptionError>;
490
719
  protected readonly offlineQueue: any[];
491
720
  protected currentState: ConnectionState;
492
721
  protected connectionListeners: ConnectionListener[];
@@ -497,6 +726,9 @@ declare class FlareBase {
497
726
  protected subscriptionReplayPromise: Promise<void>;
498
727
  protected requestTraceSeq: number;
499
728
  protected requestTimingEnabled: boolean;
729
+ protected httpInFlight: Map<string, Promise<HttpResponseSnapshot>>;
730
+ protected httpResponseCache: Map<string, HttpResponseSnapshot>;
731
+ protected readonly maxHttpCacheEntries = 200;
500
732
  protected presenceCallbacks: Map<string, PresenceCallback[]>;
501
733
  protected presenceJoinCbs: Map<string, PresenceJoinCallback[]>;
502
734
  protected presenceLeaveCbs: Map<string, PresenceLeaveCallback[]>;
@@ -507,8 +739,33 @@ declare class FlareBase {
507
739
  protected nowMs(): number;
508
740
  protected normalizeHeaders(headers?: HeadersInit): Record<string, string>;
509
741
  protected redactHeaders(headers: Record<string, string>): Record<string, string>;
742
+ protected stableStringify(value: unknown): string;
743
+ protected buildHttpCacheKey(method: string, url: string, headers: Record<string, string>, body: unknown, credentials?: RequestCredentials): string;
744
+ protected shouldCacheResponse(method: string, url: string): boolean;
745
+ protected rememberHttpResponse(key: string, value: HttpResponseSnapshot): void;
746
+ protected createTimedFetchTrace(snapshot: HttpResponseSnapshot, requestId: number, startedAtMs: number, method: string, url: string, networkMs: number): {
747
+ response: {
748
+ status: number;
749
+ ok: boolean;
750
+ headers: {
751
+ get: (name: string) => string | null;
752
+ };
753
+ json: () => Promise<any>;
754
+ };
755
+ requestId: number;
756
+ startedAtMs: number;
757
+ networkMs: number;
758
+ method: string;
759
+ url: string;
760
+ };
510
761
  protected logHttpTiming(...args: any[]): void;
511
762
  protected mergeHeaders(base: HeadersInit | undefined, extra: Record<string, string>): HeadersInit;
763
+ protected toWireField(field: string): string;
764
+ protected fromWireField(field: string): string;
765
+ protected normalizeOutboundData(value: unknown): unknown;
766
+ protected normalizeInboundData(value: unknown): unknown;
767
+ protected normalizeOutboundAnyFilter(filter: Record<string, unknown>): Record<string, unknown>;
768
+ protected normalizeOutboundQuery(query: unknown): unknown;
512
769
  protected timedFetch(label: string, input: string, init?: RequestInit): Promise<{
513
770
  response: {
514
771
  status: number;
@@ -548,7 +805,14 @@ declare class FlareBase {
548
805
  get isConnected(): boolean;
549
806
  onConnectionStateChange(listener: ConnectionListener): () => void;
550
807
  onError(callback: ErrorListener): () => void;
551
- collection<T = any>(name: string): CollectionReference<T>;
808
+ collection<T = any>(name: string): CollectionQuery<T, TPresetMap>;
809
+ registerQueryPreset<Name extends string, Params extends Record<string, unknown>, Row = any>(name: Name, handler: QueryPresetHandler<Params, Row>): this & FlareBase<TPresetMap & Record<Name, QueryPresetSpec<Params, Row>>>;
810
+ registerQueryPresets<TRegistry extends Record<string, QueryPresetHandler<any, any>>>(presets: TRegistry): this & FlareBase<TPresetMap & {
811
+ [K in keyof TRegistry]: TRegistry[K] extends QueryPresetHandler<infer Params, infer Row> ? QueryPresetSpec<Params, Row> : QueryPresetSpec<Record<string, unknown>, any>;
812
+ }>;
813
+ hasQueryPreset(name: string): boolean;
814
+ applyQueryPreset<Name extends keyof TPresetMap & string>(ref: CollectionReference<any, TPresetMap>, name: Name, params: QueryPresetParams<TPresetMap[Name]>): CollectionQuery<QueryPresetRow<TPresetMap[Name]>, TPresetMap>;
815
+ applyQueryPreset<T = any>(ref: CollectionQuery<T, TPresetMap>, name: string, params?: Record<string, unknown>): CollectionQuery<T, TPresetMap>;
552
816
  doc<T = any>(collection: string): DocumentQueryBuilder<T>;
553
817
  doc<T = any>(collection: string, id: string): DocumentReference<T>;
554
818
  ping(): Promise<number>;
@@ -565,9 +829,12 @@ declare class FlareBase {
565
829
  private _startPresenceHeartbeat;
566
830
  private _stopPresenceHeartbeat;
567
831
  syncOffline(): Promise<void>;
832
+ protected beforeActivateSubscription(_entry: ActiveSubscription): Promise<void>;
568
833
  protected activateSubscription(entry: ActiveSubscription): Promise<void>;
834
+ protected toSubscriptionError(err: unknown): SubscriptionError;
835
+ protected emitSubscriptionError(baseId: string, error: SubscriptionError): void;
569
836
  protected replayActiveSubscriptions(): Promise<void>;
570
- subscribe(subId: string, collection: string, docId: string | undefined, query: QueryConfig | StructuredQuery | undefined, callback: SubscriptionCallback, options?: SubscribeOptions): () => void;
837
+ subscribe(subId: string, collection: string, docId: string | undefined, query: QueryConfig | StructuredQuery | undefined, callback: SubscriptionCallback, options?: SubscribeOptions): SubscriptionHandle;
571
838
  send(type: FlareAction, payload: any): Promise<any>;
572
839
  private handleTransportError;
573
840
  protected onConnected(): void;
@@ -596,7 +863,7 @@ declare class FlareBase {
596
863
  * the browser owns two HttpOnly cookies: one from the Flare
597
864
  * domain and one from the Next.js domain.
598
865
  */
599
- declare class FlareAuth extends FlareBase {
866
+ declare class FlareAuth<TPresetMap extends QueryPresetMap = {}> extends FlareBase<TPresetMap> {
600
867
  protected authToken?: string;
601
868
  protected userId?: string;
602
869
  protected authGuard?: AuthGuard;
@@ -605,9 +872,12 @@ declare class FlareAuth extends FlareBase {
605
872
  protected csrfToken?: string;
606
873
  protected csrfInitPromise?: Promise<void>;
607
874
  protected csrfBootstrapAttempted: boolean;
875
+ protected socketAuthSyncPromise?: Promise<void>;
876
+ protected pushServiceWorkerInitPromise?: Promise<ServiceWorkerRegistration | null>;
608
877
  protected authSession: FlareAuthSession | null;
609
878
  protected authStateListeners: AuthStateListener[];
610
879
  protected authConfigListeners: AuthConfigListener[];
880
+ protected currentProfile: FlareAuthUser | undefined;
611
881
  private getDefaultCsrfCookieName;
612
882
  getCsrfCookieName(): string;
613
883
  /**
@@ -650,13 +920,15 @@ declare class FlareAuth extends FlareBase {
650
920
  loadAuthConfig(): Promise<FlareAuthConfig>;
651
921
  protected fetchAuthConfig(): Promise<FlareAuthConfig>;
652
922
  onAuthConfigLoaded(listener: AuthConfigListener): () => void;
923
+ protected setProfile(profile: FlareAuthUser): void;
653
924
  protected setAuthSession(session: FlareAuthSession | null): void;
654
925
  onAuthStateChanged(listener: AuthStateListener): () => void;
655
926
  onAuthStateChange(listener: AuthStateListener): () => void;
656
- get currentUser(): string | undefined;
657
- getCurrentUser(): string | undefined;
927
+ get currentUser(): FlareAuthUser | undefined;
928
+ getCurrentUser(): FlareAuthUser | undefined;
658
929
  protected syncSocketAuth(accessToken?: string | null): Promise<void>;
659
930
  protected updateSocketIdentity(uid?: string, forceReplay?: boolean): Promise<void>;
931
+ protected beforeActivateSubscription(_entry: any): Promise<void>;
660
932
  protected onConnected(): void;
661
933
  protected handleIncoming(msg: any): void;
662
934
  auth(token: string): Promise<AuthResult>;
@@ -798,6 +1070,39 @@ declare class FlareAuth extends FlareBase {
798
1070
  email: string;
799
1071
  sessionsRevoked?: number;
800
1072
  }>;
1073
+ private toUint8ArrayFromBase64Url;
1074
+ private encodePushTokenFromSubscription;
1075
+ private fetchPushSetupConfig;
1076
+ setupPushServiceWorker(): Promise<ServiceWorkerRegistration | null>;
1077
+ requestPushPermission(): Promise<NotificationPermission>;
1078
+ acquireBrowserPushToken(options?: BrowserPushTokenOptions): Promise<{
1079
+ token: string;
1080
+ subscription: PushSubscription;
1081
+ }>;
1082
+ enableBrowserPush(options?: BrowserPushRegistrationOptions): Promise<{
1083
+ registered: boolean;
1084
+ appId: string;
1085
+ uid: string;
1086
+ token: string;
1087
+ platform?: string;
1088
+ subscription: PushSubscription;
1089
+ }>;
1090
+ registerPushToken(input: RegisterPushTokenInput): Promise<{
1091
+ registered: boolean;
1092
+ appId: string;
1093
+ uid: string;
1094
+ token: string;
1095
+ platform?: string;
1096
+ }>;
1097
+ unregisterPushToken(token: string, authAppId?: string): Promise<{
1098
+ unregistered: boolean;
1099
+ appId: string;
1100
+ token: string;
1101
+ removed: boolean;
1102
+ }>;
1103
+ sendPushNotification(input: SendPushNotificationInput): Promise<PushSendResult>;
1104
+ sendEmail(input: SendEmailInput): Promise<EmailSendResult>;
1105
+ verifyEmailLink(input: VerifyEmailLinkInput): Promise<EmailLinkVerifyResult>;
801
1106
  signIn(providerId: ProviderId, options?: {
802
1107
  returnTo?: string;
803
1108
  metaTag?: string;
@@ -847,7 +1152,9 @@ declare class FlareAuth extends FlareBase {
847
1152
  additionalParams?: Record<string, string>;
848
1153
  signInIfAllowed?: boolean;
849
1154
  }): Promise<Record<string, any>>;
850
- protected requestEmailPasswordToken(email: string, password: string, scope?: string[]): Promise<AuthToken>;
1155
+ protected requestEmailPasswordToken(email: string, password: string, scope?: string[]): Promise<AuthToken & {
1156
+ kind: string;
1157
+ }>;
851
1158
  protected fetchAuthMe(token: string): Promise<{
852
1159
  id?: string;
853
1160
  email?: string | null;
@@ -880,8 +1187,11 @@ declare class FlareAuth extends FlareBase {
880
1187
  * This file wires FlareAuth together and leaves CSRF bootstrapping to the user.
881
1188
  */
882
1189
 
883
- declare class FlareClient extends FlareAuth {
1190
+ declare class FlareClient<TPresetMap extends QueryPresetMap = {}> extends FlareAuth<TPresetMap> {
1191
+ private autoPushRegisteredIdentity?;
884
1192
  constructor(config: FlareConfig);
1193
+ private enableAutoPushNotificationsAfterAuth;
1194
+ autoEnablePushNotifications(): Promise<void>;
885
1195
  }
886
1196
 
887
1197
  /**
@@ -1072,4 +1382,4 @@ declare const getFlare: () => FlareClient | null;
1072
1382
  */
1073
1383
  declare const disconnectFlare: () => void;
1074
1384
 
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 };
1385
+ export { type AggregateFunction, type AggregateSpec, type AnyFilter, type AuthConfigListener, type AuthConfigResponse, type AuthResult, type AuthStateListener, type AuthWithPendingVerificationResult, type AuthWithTokenResult, type BaseMessage, type BrowserPushRegistrationOptions, type BrowserPushTokenOptions, type ChangeEvent, type ChangeOperation, type CollectionPresetMethods, type CollectionQuery, CollectionReference, type ConnectionState, type CsrfProxyConfig, type CursorValue, type DocAddedCallback, type DocChangedCallback, type DocDeletedCallback, type DocUpdatedCallback, DocumentQueryBuilder, DocumentReference, type DocumentSnapshot, type EmailLinkVerifyResult, type EmailSendResult, FlareAction, type FlareAuthConfig, type FlareAuthProviderId, type FlareAuthProviderPublicConfig, type FlareAuthSession, type FlareAuthUser, type FlareConfig, FlareError, FlareErrors, FlareEvent, FlareResponseCodes, type FlareRule, type GroupByClause, type HavingClause, type JoinClause, type JoinQueryPattern, type NestedJoinClause, type OfflineOperation, type OrFilter, type OrderByClause, type PresenceCallback, type PresenceJoinCallback, type PresenceLeaveCallback, type PresenceMember, type PushSendResult, type QueryConfig, type QueryOperator, type QueryPresetMap, type QueryPresetParams, type QueryPresetRow, type QueryPresetSpec, type QuerySnapshot, type RegisterPushTokenInput, type RulePermission, type SecurityRuleEntry, type SecurityRulesMap, type SendEmailInput, type SendPushNotificationInput, type SnapshotEvent, type StructuredJoinClause, type StructuredQuery, type SubscribeMessage, type SubscribeOptions, type SubscriptionCallback, type SubscriptionData, type SubscriptionError, type SubscriptionErrorCallback, type SubscriptionHandle, type VectorFieldConfig, type VectorSearchClause, type VerifyEmailLinkInput, type WhereCondition, buildFlareHeaders, connectApp, createCsrfProxy, createCsrfProxyHandler, FlareClient as default, disconnectFlare, extractCsrfFromRequest, flareRulesToSecurityMap, getFlare, parseValue, parseWhereCondition, securityMapToFlareRules };