@zuzjs/flare 0.2.15 → 0.2.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2 @@
1
+ 'use strict';/* ZuzFlare Client */
2
+ var e=()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?document.currentScript.src:new URL("main.js",document.baseURI).href,t=e();exports.a=t;
package/dist/grpc.cjs ADDED
@@ -0,0 +1,2 @@
1
+ 'use strict';var chunkDGCKTOF5_cjs=require('./chunk-DGCKTOF5.cjs'),i=require('path'),url=require('url'),y=require('fs');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var i__default=/*#__PURE__*/_interopDefault(i);var y__default=/*#__PURE__*/_interopDefault(y);/* ZuzFlare Client */
2
+ var w=()=>typeof process<"u"&&!!process.versions?.node,f=e=>!(e.transport==="ws"||e.transport==="http"||!e.grpcUrl||e.grpcUrl.trim().length===0||!w());async function k(e){let t=await import('@grpc/grpc-js'),s=await import('@grpc/proto-loader'),o=i__default.default.dirname(url.fileURLToPath(chunkDGCKTOF5_cjs.a)),r=[i__default.default.resolve(o,"../../proto"),i__default.default.resolve(o,"../proto"),i__default.default.resolve(process.cwd(),"proto")],n=r.find(p=>y__default.default.existsSync(i__default.default.join(p,"flare.proto")))??r[0],l=i__default.default.join(n,"flare.proto"),a=await s.load(l,{keepCase:false,longs:String,enums:String,defaults:true,oneofs:true,includeDirs:[n]}),u=t.loadPackageDefinition(a).flare;return new u.QueryService(e,t.credentials.createInsecure())}async function m(e){let t=await import('@grpc/grpc-js'),s=await import('@grpc/proto-loader'),o=i__default.default.dirname(url.fileURLToPath(chunkDGCKTOF5_cjs.a)),r=[i__default.default.resolve(o,"../../proto"),i__default.default.resolve(o,"../proto"),i__default.default.resolve(process.cwd(),"proto")],n=r.find(p=>y__default.default.existsSync(i__default.default.join(p,"flare.proto")))??r[0],l=i__default.default.join(n,"flare.proto"),a=await s.load(l,{keepCase:false,longs:String,enums:String,defaults:true,oneofs:true,includeDirs:[n]}),u=t.loadPackageDefinition(a).flare;return new u.AuthService(e,t.credentials.createInsecure())}function h(e,t){return new Promise((s,o)=>{e.RunQuery(t,(r,n)=>{if(r)return o(r);s(n??{});});})}async function v(e,t,s){if(!f(e))return null;let o=await k(e.grpcUrl),r=await h(o,{app_id:e.appId,collection:t,query:s});if(r?.error)throw new Error(`[flare-client][grpc] run_query failed: ${r.error_description||r.error}`);try{let n=JSON.parse(r?.data_json||"[]");return Array.isArray(n)?n:[]}catch{return []}}async function C(e,t,s){if(!f(e))return null;let o=await m(e.grpcUrl),r=await new Promise((n,l)=>{o.Login({app_id:e.appId,client_id:e.apiKey??"",email:t,password:s},(a,c)=>{if(a)return l(a);n(c??{});});});if(r?.error)throw new Error(`[flare-client][grpc] login failed: ${r.error_description||r.error}`);return {token:String(r?.token??""),refreshToken:r?.refresh_token?String(r.refresh_token):null,role:String(r?.role??"user")}}async function D(e,t,s){if(!f(e))return null;let o=await m(e.grpcUrl),r=await new Promise((n,l)=>{o.Register({app_id:e.appId,client_id:e.apiKey??"",email:t,password:s},(a,c)=>{if(a)return l(a);n(c??{});});});if(r?.error)throw new Error(`[flare-client][grpc] register failed: ${r.error_description||r.error}`);return {token:String(r?.token??""),role:String(r?.role??"user"),userId:String(r?.user_id??"")}}exports.runGrpcLogin=C;exports.runGrpcQuery=v;exports.runGrpcRegister=D;
@@ -0,0 +1,16 @@
1
+ import { F as FlareConfig, ad as StructuredQuery } from './index-BAvE1URE.cjs';
2
+ import '@zuzjs/auth';
3
+
4
+ declare function runGrpcQuery<T = Record<string, unknown>>(config: FlareConfig, collection: string, query: StructuredQuery): Promise<T[] | null>;
5
+ declare function runGrpcLogin(config: FlareConfig, email: string, password: string): Promise<{
6
+ token: string;
7
+ refreshToken: string | null;
8
+ role: string;
9
+ } | null>;
10
+ declare function runGrpcRegister(config: FlareConfig, email: string, password: string): Promise<{
11
+ token: string;
12
+ role: string;
13
+ userId: string;
14
+ } | null>;
15
+
16
+ export { runGrpcLogin, runGrpcQuery, runGrpcRegister };
package/dist/grpc.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ import { F as FlareConfig, ad as StructuredQuery } from './index-BAvE1URE.js';
2
+ import '@zuzjs/auth';
3
+
4
+ declare function runGrpcQuery<T = Record<string, unknown>>(config: FlareConfig, collection: string, query: StructuredQuery): Promise<T[] | null>;
5
+ declare function runGrpcLogin(config: FlareConfig, email: string, password: string): Promise<{
6
+ token: string;
7
+ refreshToken: string | null;
8
+ role: string;
9
+ } | null>;
10
+ declare function runGrpcRegister(config: FlareConfig, email: string, password: string): Promise<{
11
+ token: string;
12
+ role: string;
13
+ userId: string;
14
+ } | null>;
15
+
16
+ export { runGrpcLogin, runGrpcQuery, runGrpcRegister };
package/dist/grpc.js ADDED
@@ -0,0 +1 @@
1
+ import i from'path';import {fileURLToPath}from'url';import g from'fs';var m=()=>typeof process<"u"&&!!process.versions?.node,d=e=>!(e.transport==="ws"||e.transport==="http"||!e.grpcUrl||e.grpcUrl.trim().length===0||!m());async function w(e){let t=await import('@grpc/grpc-js'),s=await import('@grpc/proto-loader'),o=i.dirname(fileURLToPath(import.meta.url)),r=[i.resolve(o,"../../proto"),i.resolve(o,"../proto"),i.resolve(process.cwd(),"proto")],n=r.find(u=>g.existsSync(i.join(u,"flare.proto")))??r[0],l=i.join(n,"flare.proto"),a=await s.load(l,{keepCase:false,longs:String,enums:String,defaults:true,oneofs:true,includeDirs:[n]}),p=t.loadPackageDefinition(a).flare;return new p.QueryService(e,t.credentials.createInsecure())}async function y(e){let t=await import('@grpc/grpc-js'),s=await import('@grpc/proto-loader'),o=i.dirname(fileURLToPath(import.meta.url)),r=[i.resolve(o,"../../proto"),i.resolve(o,"../proto"),i.resolve(process.cwd(),"proto")],n=r.find(u=>g.existsSync(i.join(u,"flare.proto")))??r[0],l=i.join(n,"flare.proto"),a=await s.load(l,{keepCase:false,longs:String,enums:String,defaults:true,oneofs:true,includeDirs:[n]}),p=t.loadPackageDefinition(a).flare;return new p.AuthService(e,t.credentials.createInsecure())}function k(e,t){return new Promise((s,o)=>{e.RunQuery(t,(r,n)=>{if(r)return o(r);s(n??{});});})}async function C(e,t,s){if(!d(e))return null;let o=await w(e.grpcUrl),r=await k(o,{app_id:e.appId,collection:t,query:s});if(r?.error)throw new Error(`[flare-client][grpc] run_query failed: ${r.error_description||r.error}`);try{let n=JSON.parse(r?.data_json||"[]");return Array.isArray(n)?n:[]}catch{return []}}async function D(e,t,s){if(!d(e))return null;let o=await y(e.grpcUrl),r=await new Promise((n,l)=>{o.Login({app_id:e.appId,client_id:e.apiKey??"",email:t,password:s},(a,c)=>{if(a)return l(a);n(c??{});});});if(r?.error)throw new Error(`[flare-client][grpc] login failed: ${r.error_description||r.error}`);return {token:String(r?.token??""),refreshToken:r?.refresh_token?String(r.refresh_token):null,role:String(r?.role??"user")}}async function F(e,t,s){if(!d(e))return null;let o=await y(e.grpcUrl),r=await new Promise((n,l)=>{o.Register({app_id:e.appId,client_id:e.apiKey??"",email:t,password:s},(a,c)=>{if(a)return l(a);n(c??{});});});if(r?.error)throw new Error(`[flare-client][grpc] register failed: ${r.error_description||r.error}`);return {token:String(r?.token??""),role:String(r?.role??"user"),userId:String(r?.user_id??"")}}export{D as runGrpcLogin,C as runGrpcQuery,F as runGrpcRegister};
@@ -1,509 +1,6 @@
1
+ import { an as WhereCondition, af as SubscriptionCallback, Z as QueryConfig, v as DocUpdatedCallback, u as DocDeletedCallback, t as DocChangedCallback, $ as QueryPresetMap, a0 as QueryPresetParams, a1 as QueryPresetRow, a as AggregateSpec, N as HavingClause, O as JoinClause, al as VectorSearchClause, ad as StructuredQuery, aj as SubscriptionHandle, o as CollectionStreamOptions, l as CollectionStream, k as CollectionExternalStore, s as DocAddedCallback, F as FlareConfig, ae as SubscribeOptions, ai as SubscriptionErrorCallback, ah as SubscriptionError, p as ConnectionState, U as PresenceCallback, V as PresenceJoinCallback, W as PresenceLeaveCallback, ak as VectorFieldConfig, a2 as QueryPresetSpec, y as FlareAuthConfig, f as AuthStateListener, d as AuthConfigListener, J as FlareAuthSession, K as FlareAuthUser, z as FlareAuthHydrationInput, G as FlareAuthHydrationOptions, i as BrowserPushTokenOptions, B as BrowserPushRegistrationOptions, a4 as RegisterPushTokenInput, a9 as SendPushNotificationInput, Y as PushSendResult, e as AuthResult } from './index-BAvE1URE.js';
1
2
  import { AuthToken } from '@zuzjs/auth';
2
3
 
3
- /**
4
- * Client Configuration
5
- */
6
- interface FlareConfig {
7
- /** Base URL for the Flare API. */
8
- endpoint: string;
9
- /**
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)
15
- */
16
- httpBase?: string;
17
- /**
18
- * WebSocket path used for realtime transport.
19
- * Defaults to '/' for backward compatibility.
20
- */
21
- wsPath?: string;
22
- /** Unique identifier for the application. */
23
- appId: string;
24
- /** API key for the application. */
25
- apiKey?: string;
26
- /**
27
- * Request content type for credential auth endpoints (/auth/token, /auth/register).
28
- * Defaults to OAuth-compatible form encoding.
29
- */
30
- authRequestContentType?: "application/x-www-form-urlencoded" | "application/json";
31
- /**
32
- * Controls how onAuthStateChanged initializes auth in browser runtime.
33
- * - `refresh` (default): attempt /auth/refresh once in httpBase mode.
34
- * - `none`: skip automatic refresh bootstrap; listeners receive current in-memory state only.
35
- */
36
- authBootstrapMode?: "refresh" | "none";
37
- /** Public key for the application. */
38
- publicKey?: string;
39
- /** Whether to automatically reconnect on connection loss. */
40
- autoReconnect?: boolean;
41
- /** Delay between reconnection attempts in milliseconds. */
42
- reconnectDelay?: number;
43
- /** Maximum delay between reconnection attempts in milliseconds. */
44
- maxReconnectDelay?: number;
45
- /** Enable or disable debug mode. */
46
- debug?: boolean;
47
- /** Enable or disable request timing. */
48
- requestTiming?: boolean;
49
- /** Connection timeout in milliseconds. */
50
- connectionTimeout?: number;
51
- /** Enable automatic push notification registration on supported platforms. */
52
- pushNotifications?: boolean;
53
- /**
54
- * Optional per-collection mapper registry for shaping inbound data.
55
- *
56
- * Keys can be:
57
- * - base collection names (e.g. "boards")
58
- * - join aliases (`join(..., { as: "team" })` => "team")
59
- */
60
- dataMapper?: DataMapperRegistry;
61
- }
62
- type DataMapperFn<TRow = any, TMapped = any> = (row: TRow) => TMapped;
63
- type DataMapperRegistry = Record<string, DataMapperFn<any, any>>;
64
- type FlareAuthProviderId = "credentials" | "anonymous" | "google" | "facebook" | "github" | "dropbox" | "apple" | "twitter";
65
- interface FlareAuthProviderPublicConfig {
66
- enabled: boolean;
67
- clientId?: string;
68
- scopes?: string[];
69
- }
70
- interface FlareAuthConfig {
71
- appId: string;
72
- enabled: boolean;
73
- needsEmailVerification?: boolean;
74
- autoSendVerificationEmail?: boolean;
75
- redirectUri?: string;
76
- csrfToken?: string;
77
- cookie?: {
78
- accessTokenName?: string;
79
- refreshTokenName?: string;
80
- csrfTokenName?: string;
81
- domain?: string;
82
- path?: string;
83
- secure?: boolean;
84
- sameSite?: "Lax" | "Strict" | "None";
85
- accessTokenMaxAge?: number;
86
- refreshTokenMaxAge?: number;
87
- csrfTokenMaxAge?: number;
88
- };
89
- providers: Record<FlareAuthProviderId, FlareAuthProviderPublicConfig>;
90
- }
91
- interface FlareAuthSession {
92
- uid: string;
93
- accessToken: string;
94
- refreshToken: string | null;
95
- provider?: string;
96
- email?: string | null;
97
- emailVerified?: boolean;
98
- }
99
- interface FlareAuthUser {
100
- uid: string;
101
- email: string;
102
- email_verified: string;
103
- [x: string]: any;
104
- }
105
- interface FlareAuthHydrationInput {
106
- uid?: string | null;
107
- id?: string | null;
108
- accessToken?: string | null;
109
- refreshToken?: string | null;
110
- ticket?: string | null;
111
- provider?: string;
112
- email?: string | null;
113
- emailVerified?: boolean;
114
- email_verified?: boolean;
115
- profile?: Partial<FlareAuthUser> | null;
116
- }
117
- interface FlareAuthHydrationOptions {
118
- source?: string;
119
- markBootstrapAttempted?: boolean;
120
- syncSocket?: boolean;
121
- }
122
- interface RegisterPushTokenInput {
123
- token: string;
124
- platform?: string;
125
- deviceId?: string;
126
- topics?: string[];
127
- authAppId?: string;
128
- }
129
- interface BrowserPushTokenOptions {
130
- /** Service worker registration used for PushManager subscription. */
131
- serviceWorkerRegistration?: ServiceWorkerRegistration;
132
- /** Existing PushSubscription to reuse instead of subscribing again. */
133
- subscription?: PushSubscription;
134
- /** Public VAPID key used when creating a new PushSubscription. */
135
- applicationServerKey?: string;
136
- /** When true, unsubscribe old subscriptions before creating a new one. */
137
- forceResubscribe?: boolean;
138
- }
139
- interface BrowserPushRegistrationOptions extends BrowserPushTokenOptions {
140
- /** Optional explicit platform label. Defaults to "web". */
141
- platform?: string;
142
- deviceId?: string;
143
- topics?: string[];
144
- authAppId?: string;
145
- }
146
- interface SendPushNotificationInput {
147
- title?: string;
148
- body?: string;
149
- image?: string;
150
- data?: Record<string, unknown>;
151
- tokens?: string[];
152
- uid?: string;
153
- topic?: string;
154
- priority?: "normal" | "high";
155
- ttlSeconds?: number;
156
- dryRun?: boolean;
157
- authAppId?: string;
158
- }
159
- interface PushSendResult {
160
- sent: boolean;
161
- appId: string;
162
- targetCount: number;
163
- successCount: number;
164
- failureCount: number;
165
- invalidatedTokenCount: number;
166
- dryRun: boolean;
167
- }
168
- interface SendEmailInput {
169
- to: string | string[];
170
- tag: string;
171
- values?: Record<string, unknown>;
172
- authAppId?: string;
173
- }
174
- interface EmailSendResult {
175
- sent: boolean;
176
- appId: string;
177
- tag: string;
178
- recipientCount: number;
179
- acceptedCount: number;
180
- rejectedCount: number;
181
- includeVerificationLink?: boolean;
182
- linkId?: string;
183
- verifyUrl?: string;
184
- messageId?: string;
185
- }
186
- interface VerifyEmailLinkInput {
187
- token: string;
188
- tag?: string;
189
- email?: string;
190
- authAppId?: string;
191
- }
192
- interface EmailLinkVerifyResult {
193
- verified: boolean;
194
- alreadyVerified: boolean;
195
- appId: string;
196
- linkId: string;
197
- email: string;
198
- tag: string;
199
- verifiedAt?: string;
200
- acceptedByUid?: string;
201
- }
202
- type AuthStateListener = (session: FlareAuthSession & FlareAuthUser | null) => void;
203
- type AuthConfigListener = (conf: FlareAuthConfig) => void;
204
- interface SubscribeOptions {
205
- skipSnapshot?: boolean;
206
- }
207
- type QueryOperator = "==" | "!=" | "<" | "<=" | ">" | ">=" | "in" | "not-in" | "array-contains" | "array-contains-any" | "elem-match" | "like" | "not-like" | "contains" | "exists" | "not-exists";
208
- interface QueryConfig {
209
- field: string;
210
- op: QueryOperator;
211
- value: unknown;
212
- }
213
- /** OR group */
214
- interface OrFilter {
215
- or: AnyFilter[];
216
- }
217
- /** AND group */
218
- interface AndFilter {
219
- and: AnyFilter[];
220
- }
221
- type AnyFilter = QueryConfig | OrFilter | AndFilter;
222
- type WhereCondition = Record<string, string | number | boolean | any[]>;
223
- interface OrderByClause {
224
- field: string;
225
- dir?: "asc" | "desc";
226
- }
227
- interface GroupByClause {
228
- fields: string[];
229
- }
230
- interface HavingClause {
231
- field: string;
232
- op: "==" | "!=" | "<" | "<=" | ">" | ">=";
233
- value: number;
234
- }
235
- interface CursorValue {
236
- values: unknown[];
237
- }
238
- type AggregateFunction = "count" | "sum" | "avg" | "min" | "max" | "distinct";
239
- interface AggregateSpec {
240
- fn: AggregateFunction;
241
- field?: string;
242
- alias?: string;
243
- }
244
- /**
245
- * Join definition used by CollectionReference.Join().
246
- *
247
- * Example:
248
- * Join("tasks", { source: "id", target: "boardId", as: "tasks" })
249
- */
250
- interface JoinQueryPattern {
251
- where?: AnyFilter[];
252
- orderBy?: OrderByClause[];
253
- limit?: number;
254
- offset?: number;
255
- startAt?: CursorValue;
256
- startAfter?: CursorValue;
257
- endAt?: CursorValue;
258
- endBefore?: CursorValue;
259
- aggregate?: AggregateSpec[];
260
- groupBy?: GroupByClause;
261
- having?: HavingClause[];
262
- vectorSearch?: VectorSearchClause;
263
- select?: string[];
264
- distinctField?: string;
265
- }
266
- interface NestedJoinClause extends JoinQueryPattern {
267
- /** Joined collection name for this nested join. */
268
- collection: string;
269
- /** Field from the parent join result. */
270
- source: string;
271
- /** Field from this nested collection to match source. */
272
- target: string;
273
- /** Alias where nested rows are attached in each parent join row. */
274
- as: string;
275
- /** If true, expect at most one joined row. */
276
- single?: boolean;
277
- /** Recursive nested joins. */
278
- joins?: NestedJoinClause[];
279
- }
280
- interface JoinClause extends JoinQueryPattern {
281
- /** Field from the base collection (the collection you started the query on). */
282
- source: string;
283
- /** Field from the joined collection that should match source. */
284
- target: string;
285
- /** Alias where joined rows will be attached in each result object. */
286
- as: string;
287
- /** If true, expect at most one joined row (object instead of array on server side). */
288
- single?: boolean;
289
- /** Optional nested joins under this join. */
290
- joins?: NestedJoinClause[];
291
- }
292
- /** Internal wire-ready join shape sent to server query engine. */
293
- interface StructuredJoinClause extends JoinQueryPattern {
294
- from: string;
295
- localField: string;
296
- foreignField: string;
297
- as: string;
298
- single?: boolean;
299
- joins?: StructuredJoinClause[];
300
- }
301
- interface VectorSearchClause {
302
- field: string;
303
- vector: number[];
304
- k: number;
305
- metric?: "cosine" | "euclidean" | "dotProduct";
306
- minScore?: number;
307
- }
308
- /** Full structured query (document query + SQL-style feature set) */
309
- interface StructuredQuery {
310
- where?: AnyFilter[];
311
- orderBy?: OrderByClause[];
312
- limit?: number;
313
- offset?: number;
314
- startAt?: CursorValue;
315
- startAfter?: CursorValue;
316
- endAt?: CursorValue;
317
- endBefore?: CursorValue;
318
- aggregate?: AggregateSpec[];
319
- groupBy?: GroupByClause;
320
- having?: HavingClause[];
321
- joins?: StructuredJoinClause[];
322
- vectorSearch?: VectorSearchClause;
323
- select?: string[];
324
- distinctField?: string;
325
- }
326
- type QueryPresetSpec<Params extends Record<string, unknown> = Record<string, unknown>, Row = any> = {
327
- params: Params;
328
- row: Row;
329
- };
330
- type QueryPresetMap = Record<string, QueryPresetSpec<any, any>>;
331
- type QueryPresetParams<TSpec> = TSpec extends QueryPresetSpec<infer Params, any> ? Params : Record<string, unknown>;
332
- type QueryPresetRow<TSpec> = TSpec extends QueryPresetSpec<any, infer Row> ? Row : any;
333
- type ChangeOperation = 'insert' | 'update' | 'replace' | 'delete';
334
- /**
335
- * Fired once when the subscription is first established.
336
- * `data` is always an array — the full matching collection snapshot.
337
- */
338
- interface SnapshotEvent<T = any> {
339
- type: 'snapshot';
340
- subscriptionId: string;
341
- collection: string;
342
- data: T[];
343
- }
344
- /**
345
- * Fired on every subsequent document mutation that matches the subscription query.
346
- * `data` is the single affected document (null on delete).
347
- */
348
- interface ChangeEvent<T = any> {
349
- type: 'change';
350
- subscriptionId: string;
351
- collection: string;
352
- docId: string;
353
- operation: ChangeOperation;
354
- data: T | null;
355
- }
356
- /** Discriminated union — narrow on `event.type` to get the right shape. */
357
- type SubscriptionData<T = any> = SnapshotEvent<T> | ChangeEvent<T>;
358
- type SubscriptionCallback<T = any> = (data: SubscriptionData<T>) => void;
359
- interface SubscriptionError {
360
- code?: string;
361
- message: string;
362
- permissionDenied: boolean;
363
- raw?: unknown;
364
- }
365
- type SubscriptionErrorCallback = (error: SubscriptionError) => void;
366
- interface SubscriptionHandle {
367
- (): void;
368
- unsubscribe: () => void;
369
- onError: (callback: SubscriptionErrorCallback) => SubscriptionHandle;
370
- onPermissionDenied: (callback: SubscriptionErrorCallback) => SubscriptionHandle;
371
- catch: (callback: SubscriptionErrorCallback) => SubscriptionHandle;
372
- }
373
- type DocAddedCallback<T = any> = (data: T, docId: string) => void;
374
- type DocUpdatedCallback<T = any> = (data: T, docId: string) => void;
375
- type DocDeletedCallback<T = any> = (docId: string) => void;
376
- type DocChangedCallback<T = any> = (data: T | null, docId: string, operation: ChangeOperation) => void;
377
- type StreamFlushReason = 'snapshot' | 'change-batch';
378
- interface CollectionStreamOptions<T = any> {
379
- /** Delay before a queued burst is flushed to listeners. */
380
- flushMs?: number;
381
- /** Flush immediately when queued changes reach this count. */
382
- maxBatchSize?: number;
383
- /** Field used to identify docs inside snapshots when getId is not provided. */
384
- idField?: keyof T & string;
385
- /** Custom identifier extractor for snapshot rows. */
386
- getId?: (doc: T) => string | undefined;
387
- /** Where newly inserted docs should be placed when they were not in snapshot. */
388
- insertAt?: 'start' | 'end';
389
- /** Optional cap to keep only the newest N docs in local stream state. */
390
- maxDocs?: number;
391
- /** Optional local sort run after flush. */
392
- sort?: (a: T, b: T) => number;
393
- }
394
- interface CollectionStreamMeta {
395
- reason: StreamFlushReason;
396
- batchSize: number;
397
- version: number;
398
- ready: boolean;
399
- }
400
- type CollectionStreamListener<T = any> = (rows: readonly T[], meta: CollectionStreamMeta) => void;
401
- interface CollectionStream<T = any> {
402
- /** Subscribe to stream updates (call unsubscribe to stop). */
403
- subscribe: (listener: CollectionStreamListener<T>, emitCurrent?: boolean) => () => void;
404
- /** Returns the latest immutable snapshot of rows. */
405
- getSnapshot: () => readonly T[];
406
- /** Returns true after the initial snapshot has been received. */
407
- isReady: () => boolean;
408
- /** Monotonic version incremented on each flush. */
409
- getVersion: () => number;
410
- /** Stop the underlying realtime subscription and cleanup timers/listeners. */
411
- close: () => void;
412
- /** Attach subscription-level error handler. */
413
- onError: (callback: SubscriptionErrorCallback) => CollectionStream<T>;
414
- /** Attach permission-denied handler. */
415
- onPermissionDenied: (callback: SubscriptionErrorCallback) => CollectionStream<T>;
416
- }
417
- interface CollectionExternalStore<T = any> {
418
- /** Standard external-store subscribe signature used by UI store hooks. */
419
- subscribe: (onStoreChange: () => void) => () => void;
420
- /** Returns current immutable rows snapshot. */
421
- getSnapshot: () => readonly T[];
422
- /** Server snapshot fallback for SSR-safe store hooks. */
423
- getServerSnapshot: () => readonly T[];
424
- /** Access to underlying realtime stream for advanced handlers. */
425
- stream: CollectionStream<T>;
426
- /** Stops realtime stream and detaches listeners. */
427
- destroy: () => void;
428
- }
429
- interface DocumentSnapshot<T = any> {
430
- id: string;
431
- data: T | null;
432
- exists: boolean;
433
- }
434
- interface QuerySnapshot<T = any> {
435
- docs: DocumentSnapshot<T>[];
436
- size: number;
437
- empty: boolean;
438
- }
439
- interface OfflineOperation {
440
- id: string;
441
- type: 'write' | 'delete';
442
- collection: string;
443
- docId: string;
444
- data?: Record<string, unknown>;
445
- merge?: boolean;
446
- clientTs: number;
447
- }
448
- interface AuthResult {
449
- uid: string;
450
- token?: string;
451
- }
452
- type ConnectionState = 'connecting' | 'connected' | 'disconnected' | 'reconnecting' | 'error';
453
- interface AuthWithPendingVerificationResult {
454
- verificationRequired: true;
455
- created: true;
456
- emailSent: boolean;
457
- preview?: {
458
- code: string;
459
- link: string;
460
- };
461
- }
462
- interface AuthWithTokenResult extends AuthResult {
463
- accessToken: string;
464
- refreshToken: string | null;
465
- authToken: AuthToken;
466
- created: boolean;
467
- }
468
- interface PresenceMember {
469
- uid: string;
470
- socketId: string;
471
- room: string;
472
- meta?: Record<string, unknown>;
473
- joinedAt: number;
474
- lastSeen: number;
475
- }
476
- type PresenceCallback = (members: PresenceMember[]) => void;
477
- type PresenceJoinCallback = (member: PresenceMember) => void;
478
- type PresenceLeaveCallback = (uid: string) => void;
479
- /** Fields marked as vector will be auto-embedded before write */
480
- type VectorFieldConfig = {
481
- /** Dimensions of the vector (e.g. 1536 for OpenAI ada-002) */
482
- dimensions: number;
483
- /** Optional custom embedding function; defaults to client-configured embedder */
484
- embed?: (text: string) => Promise<number[]>;
485
- };
486
- type RulePermission = "create" | "read" | "update" | "delete";
487
- interface FlareRule {
488
- id: string;
489
- name: string;
490
- auth: "any" | "guest" | "auth";
491
- collection: string;
492
- document?: string;
493
- condition?: string;
494
- permissions: RulePermission[];
495
- }
496
- interface SecurityRuleEntry {
497
- ".read"?: string;
498
- ".write"?: string;
499
- ".create"?: string;
500
- ".update"?: string;
501
- ".delete"?: string;
502
- }
503
- type SecurityRulesMap = Record<string, SecurityRuleEntry>;
504
- declare const flareRulesToSecurityMap: (rules: FlareRule[]) => SecurityRulesMap;
505
- declare const securityMapToFlareRules: (rules: SecurityRulesMap) => FlareRule[];
506
-
507
4
  /**
508
5
  * Parse ORM-style where condition: { age: ">= 25", role: "admin" }
509
6
  * Returns array of QueryConfig objects
@@ -975,6 +472,7 @@ declare class FlareBase<TPresetMap extends QueryPresetMap = {}> {
975
472
  doc<T = any>(collection: string, id: string): DocumentReference<T>;
976
473
  ping(): Promise<number>;
977
474
  call<T = Record<string, unknown>>(topic: string, payload?: Record<string, unknown>): Promise<T>;
475
+ trackAnalytics(event: string, payload?: Record<string, unknown>): Promise<void>;
978
476
  query<T = Record<string, unknown>>(collection: string, q?: StructuredQuery): Promise<T[]>;
979
477
  setEmbedder(fn: EmbedFn): void;
980
478
  markVectorField(collection: string, field: string, config?: VectorFieldConfig): void;
@@ -1319,4 +817,4 @@ declare class FlareClient<TPresetMap extends QueryPresetMap = {}> extends FlareA
1319
817
  autoEnablePushNotifications(): Promise<void>;
1320
818
  }
1321
819
 
1322
- export { type OrFilter as $, type AggregateFunction as A, type BaseMessage as B, type ChangeEvent as C, type DataMapperFn as D, type DocUpdatedCallback as E, type FlareConfig as F, DocumentQueryBuilder as G, DocumentReference as H, type DocumentSnapshot as I, type EmailLinkVerifyResult as J, type EmailSendResult as K, FlareAction as L, type FlareAuthConfig as M, type FlareAuthHydrationInput as N, type FlareAuthHydrationOptions as O, type FlareAuthProviderId as P, type FlareAuthProviderPublicConfig as Q, type FlareAuthSession as R, type FlareAuthUser as S, FlareEvent as T, type FlareRule as U, type GroupByClause as V, type HavingClause as W, type JoinClause as X, type JoinQueryPattern as Y, type NestedJoinClause as Z, type OfflineOperation as _, FlareClient as a, type OrderByClause as a0, type PresenceCallback as a1, type PresenceJoinCallback as a2, type PresenceLeaveCallback as a3, type PresenceMember as a4, type PushSendResult as a5, type QueryConfig as a6, type QueryOperator as a7, type QueryPresetMap as a8, type QueryPresetParams as a9, parseWhereCondition as aA, securityMapToFlareRules as aB, type QueryPresetRow as aa, type QueryPresetSpec as ab, type QuerySnapshot as ac, type RegisterPushTokenInput as ad, type RulePermission as ae, type SecurityRuleEntry as af, type SecurityRulesMap as ag, type SendEmailInput as ah, type SendPushNotificationInput as ai, type SnapshotEvent as aj, type StreamFlushReason as ak, type StructuredJoinClause as al, type StructuredQuery as am, type SubscribeMessage as an, type SubscribeOptions as ao, type SubscriptionCallback as ap, type SubscriptionData as aq, type SubscriptionError as ar, type SubscriptionErrorCallback as as, type SubscriptionHandle as at, type VectorFieldConfig as au, type VectorSearchClause as av, type VerifyEmailLinkInput as aw, type WhereCondition as ax, flareRulesToSecurityMap as ay, parseValue as az, type AggregateSpec as b, type AndFilter as c, type AnyFilter as d, type AuthConfigListener as e, type AuthResult as f, type AuthStateListener as g, type AuthWithPendingVerificationResult as h, type AuthWithTokenResult as i, type BrowserPushRegistrationOptions as j, type BrowserPushTokenOptions as k, type ChangeOperation as l, type CollectionExternalStore as m, type CollectionPresetMethods as n, type CollectionQuery as o, CollectionReference as p, type CollectionStream as q, type CollectionStreamListener as r, type CollectionStreamMeta as s, type CollectionStreamOptions as t, type ConnectionState as u, type CursorValue as v, type DataMapperRegistry as w, type DocAddedCallback as x, type DocChangedCallback as y, type DocDeletedCallback as z };
820
+ export { type BaseMessage as B, type CollectionPresetMethods as C, DocumentQueryBuilder as D, FlareClient as F, type SubscribeMessage as S, type CollectionQuery as a, CollectionReference as b, DocumentReference as c, FlareAction as d, FlareEvent as e, parseWhereCondition as f, parseValue as p };