@lark-sh/client 0.1.10 → 0.1.12

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.mts CHANGED
@@ -59,10 +59,18 @@ interface QueryState {
59
59
  value: unknown;
60
60
  key?: string;
61
61
  };
62
+ startAfter?: {
63
+ value: unknown;
64
+ key?: string;
65
+ };
62
66
  endAt?: {
63
67
  value: unknown;
64
68
  key?: string;
65
69
  };
70
+ endBefore?: {
71
+ value: unknown;
72
+ key?: string;
73
+ };
66
74
  equalTo?: {
67
75
  value: unknown;
68
76
  key?: string;
@@ -89,6 +97,38 @@ declare class DatabaseReference {
89
97
  * Get a reference to the root of the database.
90
98
  */
91
99
  get root(): DatabaseReference;
100
+ /**
101
+ * Get the LarkDatabase instance this reference belongs to.
102
+ */
103
+ get database(): LarkDatabase;
104
+ /**
105
+ * Get the underlying reference for a query.
106
+ * For queries (created via orderBy*, limitTo*, startAt, etc.), this returns
107
+ * a reference to the same path without query constraints.
108
+ * For non-query references, this returns the reference itself.
109
+ * This matches Firebase's Query.ref behavior.
110
+ */
111
+ get ref(): DatabaseReference;
112
+ /**
113
+ * Check if this reference/query is equal to another.
114
+ * Two references are equal if they have the same database, path, and query constraints.
115
+ */
116
+ isEqual(other: DatabaseReference | null): boolean;
117
+ /**
118
+ * Get the unique identifier for this query's parameters.
119
+ * Used to differentiate multiple queries on the same path.
120
+ *
121
+ * Returns "default" for non-query references (no constraints).
122
+ * Returns a sorted JSON string of wire-format params for queries.
123
+ *
124
+ * This matches Firebase's queryIdentifier format for wire compatibility.
125
+ */
126
+ get queryIdentifier(): string;
127
+ /**
128
+ * Get the data at this location. Alias for once('value').
129
+ * This is Firebase's newer API for reading data.
130
+ */
131
+ get(): Promise<DataSnapshot>;
92
132
  /**
93
133
  * Get a reference to a child path.
94
134
  */
@@ -98,6 +138,8 @@ declare class DatabaseReference {
98
138
  *
99
139
  * For volatile paths (high-frequency updates), this is fire-and-forget
100
140
  * and resolves immediately without waiting for server confirmation.
141
+ *
142
+ * @param value - The value to write
101
143
  */
102
144
  set(value: unknown): Promise<void>;
103
145
  /**
@@ -118,6 +160,8 @@ declare class DatabaseReference {
118
160
  * '/leaderboard/alice': null // null = delete
119
161
  * });
120
162
  * ```
163
+ *
164
+ * @param values - The values to update
121
165
  */
122
166
  update(values: Record<string, unknown>): Promise<void>;
123
167
  /**
@@ -129,23 +173,46 @@ declare class DatabaseReference {
129
173
  /**
130
174
  * Generate a new child location with a unique key and optionally set its value.
131
175
  *
132
- * If value is provided, sets the value and returns a Promise that resolves
133
- * to the new reference.
176
+ * Returns a ThenableReference - an object that is both a DatabaseReference
177
+ * AND a Promise. You can access reference properties immediately (like `.key`)
178
+ * and also await the result.
179
+ *
180
+ * If value is provided, the promise resolves after the write completes.
181
+ * If no value is provided, the promise resolves immediately.
182
+ *
183
+ * @example
184
+ * ```javascript
185
+ * // Without value - returns ThenableReference, resolves immediately
186
+ * const pushed = ref.push();
187
+ * console.log(pushed.key); // "-Abc123..." (available immediately)
188
+ * await pushed; // Resolves immediately to the same reference
134
189
  *
135
- * If no value is provided, returns a reference immediately with a client-generated
136
- * push key (you can then call set() on it).
190
+ * // With value - returns ThenableReference, resolves after write
191
+ * const pushed2 = ref.push({ name: 'Alice' });
192
+ * console.log(pushed2.key); // "-Xyz789..." (available immediately)
193
+ * await pushed2; // Waits for write to complete
194
+ * ```
137
195
  */
138
- push(value?: unknown): DatabaseReference | Promise<DatabaseReference>;
196
+ push(): ThenableReference;
197
+ push(value: unknown): ThenableReference;
139
198
  /**
140
199
  * Set the data with a priority value for ordering.
141
- * Priority is injected as `.priority` into the value object.
200
+ *
201
+ * For objects: injects `.priority` into the value object.
202
+ * For primitives: wraps as `{ '.value': primitive, '.priority': priority }`.
203
+ *
204
+ * This follows Firebase's wire format for primitives with priority.
205
+ *
206
+ * @param value - The value to write
207
+ * @param priority - The priority for ordering
142
208
  */
143
209
  setWithPriority(value: unknown, priority: number | string): Promise<void>;
144
210
  /**
145
211
  * Set the priority of the data at this location.
146
- * Fetches current value and sets it with the new priority.
212
+ * Uses cached value for optimistic behavior (local effects are immediate).
213
+ * The optimistic update happens synchronously, Promise resolves after server ack.
147
214
  */
148
- setPriority(priority: number | string): Promise<void>;
215
+ setPriority(priority: number | string | null): Promise<void>;
149
216
  /**
150
217
  * Atomically modify the data at this location using optimistic concurrency.
151
218
  *
@@ -168,11 +235,18 @@ declare class DatabaseReference {
168
235
  * @param maxRetries - Maximum number of retries (default: 25)
169
236
  * @returns TransactionResult with committed status and final snapshot
170
237
  */
171
- transaction(updateFunction: (currentValue: unknown) => unknown, maxRetries?: number): Promise<TransactionResult>;
238
+ transaction(updateFunction: (currentValue: any) => any, maxRetries?: number): Promise<TransactionResult>;
172
239
  /**
173
240
  * Read the data at this location once.
241
+ *
242
+ * For 'value' events, this fetches data directly from the server.
243
+ * For child events ('child_added', 'child_changed', 'child_removed', 'child_moved'),
244
+ * this subscribes, waits for the first event, then unsubscribes.
245
+ *
246
+ * @param eventType - The event type
247
+ * @returns Promise that resolves to the DataSnapshot
174
248
  */
175
- once(eventType?: 'value'): Promise<DataSnapshot>;
249
+ once(eventType?: EventType): Promise<DataSnapshot>;
176
250
  /**
177
251
  * Subscribe to events at this location.
178
252
  * Returns an unsubscribe function.
@@ -180,8 +254,14 @@ declare class DatabaseReference {
180
254
  on(eventType: EventType, callback: SnapshotCallback$1): () => void;
181
255
  /**
182
256
  * Unsubscribe from events.
183
- * If eventType is specified, removes all listeners of that type.
184
- * If no eventType, removes ALL listeners at this path.
257
+ *
258
+ * - `off()` - removes ALL listeners at this path
259
+ * - `off('value')` - removes all 'value' listeners at this path
260
+ *
261
+ * Note: To unsubscribe a specific callback, use the unsubscribe function
262
+ * returned by `on()`.
263
+ *
264
+ * @param eventType - Optional event type to unsubscribe from
185
265
  */
186
266
  off(eventType?: EventType): void;
187
267
  /**
@@ -214,16 +294,52 @@ declare class DatabaseReference {
214
294
  limitToLast(limit: number): DatabaseReference;
215
295
  /**
216
296
  * Start at a specific value/key.
297
+ * If no value is provided, starts at the beginning (null priority).
298
+ */
299
+ startAt(value?: unknown, key?: string): DatabaseReference;
300
+ /**
301
+ * Start after a specific value/key (exclusive).
302
+ * Like startAt() but excludes the starting point.
217
303
  */
218
- startAt(value: unknown, key?: string): DatabaseReference;
304
+ startAfter(value?: unknown, key?: string): DatabaseReference;
219
305
  /**
220
306
  * End at a specific value/key.
307
+ * If no value is provided, ends at the end (null priority).
308
+ */
309
+ endAt(value?: unknown, key?: string): DatabaseReference;
310
+ /**
311
+ * End before a specific value/key (exclusive).
312
+ * Like endAt() but excludes the ending point.
221
313
  */
222
- endAt(value: unknown, key?: string): DatabaseReference;
314
+ endBefore(value?: unknown, key?: string): DatabaseReference;
223
315
  /**
224
316
  * Filter to items equal to a specific value.
225
317
  */
226
318
  equalTo(value: unknown, key?: string): DatabaseReference;
319
+ /**
320
+ * Validate that no orderBy has been set yet.
321
+ */
322
+ private _validateNoOrderBy;
323
+ /**
324
+ * Validate that no key parameter has been set on startAt/endAt/equalTo.
325
+ * Used when calling orderByKey() after startAt/endAt/equalTo.
326
+ */
327
+ private _validateNoKeyParameterForOrderByKey;
328
+ /**
329
+ * Validate that startAt/endAt/equalTo values are strings.
330
+ * Used when calling orderByKey() after startAt/endAt/equalTo.
331
+ */
332
+ private _validateStringValuesForOrderByKey;
333
+ /**
334
+ * Validate value and key types for query methods (startAt, endAt, equalTo, etc.)
335
+ */
336
+ private _validateQueryValue;
337
+ /**
338
+ * Validate that a key is a valid Firebase key format.
339
+ * Invalid characters: . $ # [ ] /
340
+ * Also cannot start or end with .
341
+ */
342
+ private _validateKeyFormat;
227
343
  /**
228
344
  * Build query parameters for wire protocol.
229
345
  */
@@ -233,7 +349,71 @@ declare class DatabaseReference {
233
349
  * Format: https://db.lark.sh/project/database/path/to/data
234
350
  */
235
351
  toString(): string;
352
+ /**
353
+ * Returns the URL for JSON serialization.
354
+ * This allows refs to be serialized with JSON.stringify().
355
+ */
356
+ toJSON(): string;
236
357
  }
358
+ /**
359
+ * A reference that is also a Promise - returned by push().
360
+ *
361
+ * This allows Firebase-compatible patterns like:
362
+ * ```javascript
363
+ * const pushed = ref.push();
364
+ * console.log(pushed.key); // Key available immediately
365
+ * await pushed; // Wait for write to complete
366
+ * ```
367
+ */
368
+ declare class ThenableReference extends DatabaseReference implements PromiseLike<DatabaseReference> {
369
+ private readonly _promise;
370
+ constructor(db: LarkDatabase, path: string, promise?: Promise<DatabaseReference>);
371
+ then<TResult1 = DatabaseReference, TResult2 = never>(onfulfilled?: ((value: DatabaseReference) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
372
+ catch<TResult = never>(onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | undefined | null): Promise<DatabaseReference | TResult>;
373
+ }
374
+
375
+ interface QueryParams {
376
+ orderBy?: 'key' | 'priority' | 'child' | 'value';
377
+ orderByChild?: string;
378
+ limitToFirst?: number;
379
+ limitToLast?: number;
380
+ startAt?: unknown;
381
+ startAtKey?: string;
382
+ startAfter?: unknown;
383
+ startAfterKey?: string;
384
+ endAt?: unknown;
385
+ endAtKey?: string;
386
+ endBefore?: unknown;
387
+ endBeforeKey?: string;
388
+ equalTo?: unknown;
389
+ equalToKey?: string;
390
+ }
391
+ interface TxSetOp {
392
+ o: 's';
393
+ p: string;
394
+ v: unknown;
395
+ }
396
+ interface TxUpdateOp {
397
+ o: 'u';
398
+ p: string;
399
+ v: Record<string, unknown>;
400
+ }
401
+ interface TxDeleteOp {
402
+ o: 'd';
403
+ p: string;
404
+ }
405
+ interface TxConditionValueOp {
406
+ o: 'c';
407
+ p: string;
408
+ v: unknown;
409
+ }
410
+ interface TxConditionHashOp {
411
+ o: 'c';
412
+ p: string;
413
+ h: string;
414
+ }
415
+ type TxConditionOp = TxConditionValueOp | TxConditionHashOp;
416
+ type TxOperation = TxSetOp | TxUpdateOp | TxDeleteOp | TxConditionOp;
237
417
 
238
418
  /**
239
419
  * DataSnapshot - an immutable snapshot of data at a location.
@@ -244,6 +424,11 @@ declare class DatabaseReference {
244
424
  * - val() strips `.priority` from returned objects (so app code doesn't see it)
245
425
  * - getPriority() reads from the data's `.priority` field
246
426
  * - This matches Firebase behavior where priority is metadata, not user data
427
+ *
428
+ * Wrapped Primitives:
429
+ * - Primitives with priority are stored as `{ '.value': x, '.priority': y }`
430
+ * - val() automatically unwraps these to return just the primitive value
431
+ * - This follows Firebase's wire format for primitives with priority
247
432
  */
248
433
 
249
434
  declare class DataSnapshot {
@@ -252,9 +437,13 @@ declare class DataSnapshot {
252
437
  private readonly _db;
253
438
  private readonly _volatile;
254
439
  private readonly _serverTimestamp;
440
+ private readonly _queryParams;
441
+ private readonly _orderedKeys;
255
442
  constructor(data: unknown, path: string, db: LarkDatabase, options?: {
256
443
  volatile?: boolean;
257
444
  serverTimestamp?: number | null;
445
+ queryParams?: QueryParams | null;
446
+ orderedKeys?: string[] | null;
258
447
  });
259
448
  /**
260
449
  * Get a DatabaseReference for the location of this snapshot.
@@ -265,32 +454,60 @@ declare class DataSnapshot {
265
454
  */
266
455
  get key(): string | null;
267
456
  /**
268
- * Get the data value, with `.priority` stripped if present.
269
- * Priority is internal metadata and should not be visible to app code.
457
+ * Get the data value, with metadata stripped.
458
+ *
459
+ * - Strips `.priority` from objects (it's metadata, not user data)
460
+ * - Unwraps `{ '.value': x, '.priority': y }` to just `x` (wrapped primitives)
461
+ *
462
+ * @typeParam T - Optional type for the returned value. Defaults to `any`.
463
+ * @example
464
+ * ```typescript
465
+ * // Untyped (returns any)
466
+ * const data = snapshot.val();
467
+ *
468
+ * // Typed (returns User)
469
+ * const user = snapshot.val<User>();
470
+ * ```
270
471
  */
271
- val(): unknown;
472
+ val<T = any>(): T;
272
473
  /**
273
474
  * Check if data exists at this location (is not null/undefined).
475
+ * Returns false for priority-only nodes (only .priority, no actual value).
274
476
  */
275
477
  exists(): boolean;
276
478
  /**
277
479
  * Get a child snapshot at the specified path.
480
+ *
481
+ * Special handling:
482
+ * - `.priority` returns the priority value (Firebase compatible)
483
+ * - For wrapped primitives, only `.priority` returns data; other paths return null
484
+ * - Non-existent paths return a snapshot with val() === null (Firebase compatible)
278
485
  */
279
486
  child(path: string): DataSnapshot;
280
487
  /**
281
488
  * Check if this snapshot has any children.
489
+ * Excludes `.priority` metadata from consideration.
490
+ * Wrapped primitives have no children.
282
491
  */
283
492
  hasChildren(): boolean;
284
493
  /**
285
494
  * Check if this snapshot has a specific child.
495
+ * `.priority` is always accessible if it exists.
496
+ * Wrapped primitives have no children except `.priority`.
286
497
  */
287
498
  hasChild(path: string): boolean;
288
499
  /**
289
500
  * Get the number of children.
501
+ * Excludes `.priority` metadata from count.
502
+ * Wrapped primitives have 0 children.
290
503
  */
291
504
  numChildren(): number;
292
505
  /**
293
- * Iterate over children. Return true from callback to stop iteration.
506
+ * Iterate over children in the correct order.
507
+ * Uses pre-computed orderedKeys if available (from subscription View),
508
+ * otherwise computes sorted keys based on query params.
509
+ * Excludes `.priority` metadata from iteration.
510
+ * Wrapped primitives have no children to iterate.
294
511
  */
295
512
  forEach(callback: (child: DataSnapshot) => boolean | void): void;
296
513
  /**
@@ -311,49 +528,21 @@ declare class DataSnapshot {
311
528
  */
312
529
  getServerTimestamp(): number | null;
313
530
  /**
314
- * Export the snapshot data as JSON (alias for val()).
531
+ * Export the snapshot data with priority metadata intact.
532
+ * Unlike val(), this preserves `.value` and `.priority` wrappers.
533
+ * Useful for serializing data while preserving priorities.
534
+ *
535
+ * @typeParam T - Optional type for the returned value. Defaults to `any`.
315
536
  */
316
- toJSON(): unknown;
317
- }
318
-
319
- interface QueryParams {
320
- orderBy?: 'key' | 'priority' | 'child' | 'value';
321
- orderByChild?: string;
322
- limitToFirst?: number;
323
- limitToLast?: number;
324
- startAt?: unknown;
325
- startAtKey?: string;
326
- endAt?: unknown;
327
- endAtKey?: string;
328
- equalTo?: unknown;
329
- equalToKey?: string;
330
- }
331
- interface TxSetOp {
332
- o: 's';
333
- p: string;
334
- v: unknown;
335
- }
336
- interface TxUpdateOp {
337
- o: 'u';
338
- p: string;
339
- v: Record<string, unknown>;
340
- }
341
- interface TxDeleteOp {
342
- o: 'd';
343
- p: string;
344
- }
345
- interface TxConditionValueOp {
346
- o: 'c';
347
- p: string;
348
- v: unknown;
349
- }
350
- interface TxConditionHashOp {
351
- o: 'c';
352
- p: string;
353
- h: string;
537
+ exportVal<T = any>(): T;
538
+ /**
539
+ * Export the snapshot data as JSON.
540
+ * Same as exportVal() - preserves priority metadata.
541
+ *
542
+ * @typeParam T - Optional type for the returned value. Defaults to `any`.
543
+ */
544
+ toJSON<T = any>(): T;
354
545
  }
355
- type TxConditionOp = TxConditionValueOp | TxConditionHashOp;
356
- type TxOperation = TxSetOp | TxUpdateOp | TxDeleteOp | TxConditionOp;
357
546
 
358
547
  /**
359
548
  * View - represents a client's subscription to a database path.
@@ -431,14 +620,103 @@ interface TransactionConditionOp {
431
620
  type TransactionOp = TransactionSetOp | TransactionUpdateOp | TransactionDeleteOp | TransactionConditionOp;
432
621
  /** Object syntax for transactions: path -> value (null = delete) */
433
622
  type TransactionObject = Record<string, unknown>;
434
- type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';
623
+ /**
624
+ * Connection state machine:
625
+ * - 'disconnected': Not connected
626
+ * - 'connecting': Initial connection in progress
627
+ * - 'connected': WebSocket open
628
+ * - 'joined': Join complete (database identified)
629
+ * - 'authenticated': Auth complete (ready to operate)
630
+ * - 'reconnecting': Attempting to reconnect after disconnect
631
+ */
632
+ type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'joined' | 'authenticated' | 'reconnecting';
633
+ /**
634
+ * Server values that are resolved by the server when a write is committed.
635
+ * Use these with set(), update(), or push() to have the server fill in values.
636
+ */
637
+ declare const ServerValue: {
638
+ /**
639
+ * A placeholder value for auto-populating the current server timestamp.
640
+ * The server will replace this with the actual Unix timestamp in milliseconds.
641
+ *
642
+ * @example
643
+ * ```javascript
644
+ * import { ServerValue } from '@lark-sh/client';
645
+ * await ref.set({ createdAt: ServerValue.TIMESTAMP });
646
+ * // Server stores: { createdAt: 1704067200000 }
647
+ * ```
648
+ */
649
+ TIMESTAMP: {
650
+ readonly '.sv': "timestamp";
651
+ };
652
+ /**
653
+ * Returns a placeholder value for atomically incrementing a numeric field.
654
+ * If the field doesn't exist or isn't a number, it's treated as 0.
655
+ *
656
+ * @param delta - The amount to increment by (can be negative to decrement)
657
+ * @returns A server value placeholder
658
+ *
659
+ * @example
660
+ * ```javascript
661
+ * import { ServerValue } from '@lark-sh/client';
662
+ * await ref.child('score').set(ServerValue.increment(10));
663
+ * // Atomically adds 10 to the current score
664
+ * ```
665
+ */
666
+ increment: (delta: number) => {
667
+ '.sv': {
668
+ increment: number;
669
+ };
670
+ };
671
+ };
435
672
  declare class LarkDatabase {
673
+ /**
674
+ * Server values that are resolved by the server when a write is committed.
675
+ * Alias for the exported ServerValue object.
676
+ */
677
+ static ServerValue: {
678
+ /**
679
+ * A placeholder value for auto-populating the current server timestamp.
680
+ * The server will replace this with the actual Unix timestamp in milliseconds.
681
+ *
682
+ * @example
683
+ * ```javascript
684
+ * import { ServerValue } from '@lark-sh/client';
685
+ * await ref.set({ createdAt: ServerValue.TIMESTAMP });
686
+ * // Server stores: { createdAt: 1704067200000 }
687
+ * ```
688
+ */
689
+ TIMESTAMP: {
690
+ readonly '.sv': "timestamp";
691
+ };
692
+ /**
693
+ * Returns a placeholder value for atomically incrementing a numeric field.
694
+ * If the field doesn't exist or isn't a number, it's treated as 0.
695
+ *
696
+ * @param delta - The amount to increment by (can be negative to decrement)
697
+ * @returns A server value placeholder
698
+ *
699
+ * @example
700
+ * ```javascript
701
+ * import { ServerValue } from '@lark-sh/client';
702
+ * await ref.child('score').set(ServerValue.increment(10));
703
+ * // Atomically adds 10 to the current score
704
+ * ```
705
+ */
706
+ increment: (delta: number) => {
707
+ '.sv': {
708
+ increment: number;
709
+ };
710
+ };
711
+ };
436
712
  private _state;
437
713
  private _auth;
438
714
  private _databaseId;
439
715
  private _coordinatorUrl;
440
716
  private _volatilePaths;
441
717
  private _transportType;
718
+ private _currentToken;
719
+ private _isAnonymous;
442
720
  private _connectionId;
443
721
  private _connectOptions;
444
722
  private _intentionalDisconnect;
@@ -452,9 +730,15 @@ declare class LarkDatabase {
452
730
  private disconnectCallbacks;
453
731
  private errorCallbacks;
454
732
  private reconnectingCallbacks;
733
+ private authStateChangedCallbacks;
734
+ private infoSubscriptions;
735
+ private authenticationPromise;
736
+ private authenticationResolve;
737
+ private _serverTimeOffset;
455
738
  constructor();
456
739
  /**
457
- * Whether the database is currently connected.
740
+ * Whether the database is fully connected and authenticated.
741
+ * Returns true when ready to perform database operations.
458
742
  */
459
743
  get connected(): boolean;
460
744
  /**
@@ -483,6 +767,11 @@ declare class LarkDatabase {
483
767
  * Returns 'websocket' or 'webtransport', or null if not connected.
484
768
  */
485
769
  get transportType(): 'websocket' | 'webtransport' | null;
770
+ /**
771
+ * Get the estimated server time offset in milliseconds.
772
+ * Add this to Date.now() to get approximate server time.
773
+ */
774
+ get serverTimeOffset(): number;
486
775
  /**
487
776
  * Check if there are any pending writes waiting for acknowledgment.
488
777
  * Useful for showing "saving..." indicators in UI.
@@ -506,6 +795,10 @@ declare class LarkDatabase {
506
795
  connect(databaseId: string, options?: ConnectOptions): Promise<void>;
507
796
  /**
508
797
  * Internal connect implementation used by both initial connect and reconnect.
798
+ * Implements the Join → Auth flow:
799
+ * 1. Connect WebSocket
800
+ * 2. Send join (identifies database)
801
+ * 3. Send auth (authenticates user - required even for anonymous)
509
802
  */
510
803
  private performConnect;
511
804
  /**
@@ -513,6 +806,16 @@ declare class LarkDatabase {
513
806
  * This triggers onDisconnect hooks on the server.
514
807
  */
515
808
  disconnect(): Promise<void>;
809
+ /**
810
+ * Temporarily disable the connection.
811
+ * Disconnects from the server but preserves subscriptions for later reconnection via goOnline().
812
+ */
813
+ goOffline(): void;
814
+ /**
815
+ * Re-enable the connection after goOffline().
816
+ * Reconnects to the database and restores subscriptions.
817
+ */
818
+ goOnline(): void;
516
819
  /**
517
820
  * Full cleanup - clears all state including subscriptions.
518
821
  * Used for intentional disconnect.
@@ -523,6 +826,27 @@ declare class LarkDatabase {
523
826
  * Used for unexpected disconnect.
524
827
  */
525
828
  private cleanupForReconnect;
829
+ /**
830
+ * Check if a path is a .info path (handled locally).
831
+ */
832
+ private isInfoPath;
833
+ /**
834
+ * Get the current value for a .info path.
835
+ */
836
+ private getInfoValue;
837
+ /**
838
+ * Subscribe to a .info path.
839
+ * Returns an unsubscribe function.
840
+ */
841
+ private subscribeToInfo;
842
+ /**
843
+ * Fire events for .info path changes.
844
+ */
845
+ private fireInfoEvents;
846
+ /**
847
+ * Fire connection state change events to .info/connected subscribers.
848
+ */
849
+ private fireConnectionStateChange;
526
850
  /**
527
851
  * Schedule a reconnection attempt with exponential backoff.
528
852
  */
@@ -607,9 +931,50 @@ declare class LarkDatabase {
607
931
  * Returns an unsubscribe function.
608
932
  */
609
933
  onReconnecting(callback: () => void): () => void;
934
+ /**
935
+ * Register a callback for auth state changes.
936
+ * Fires when user signs in, signs out, or auth changes.
937
+ * Returns an unsubscribe function.
938
+ */
939
+ onAuthStateChanged(callback: (auth: AuthInfo | null) => void): () => void;
940
+ /**
941
+ * Sign in with a new auth token while connected.
942
+ * Changes the authenticated user without disconnecting.
943
+ *
944
+ * Note: Some subscriptions may be revoked if the new user doesn't have
945
+ * permission. Listen for 'permission_denied' errors on your subscriptions.
946
+ *
947
+ * @param token - The auth token for the new user
948
+ * @throws Error if not connected (must call connect() first)
949
+ */
950
+ signIn(token: string): Promise<void>;
951
+ /**
952
+ * Sign out the current user.
953
+ * Reverts to anonymous authentication.
954
+ *
955
+ * Note: Some subscriptions may be revoked if anonymous users don't have
956
+ * permission. Listen for 'permission_denied' errors on your subscriptions.
957
+ */
958
+ signOut(): Promise<void>;
610
959
  private handleMessage;
611
960
  private handleClose;
612
961
  private handleError;
962
+ /**
963
+ * Check if authenticated synchronously.
964
+ * Returns true if authenticated, false if connecting (should wait), throws if disconnected.
965
+ */
966
+ private isAuthenticatedOrThrow;
967
+ /**
968
+ * Wait for authentication to complete before performing an operation.
969
+ * If already authenticated, returns immediately (synchronously).
970
+ * If connecting/reconnecting, waits for auth to complete.
971
+ * If disconnected and no connect in progress, throws.
972
+ *
973
+ * IMPORTANT: This returns a Promise only if waiting is needed.
974
+ * Callers should use: `if (!this.isAuthenticatedOrThrow()) if (!this.isAuthenticatedOrThrow()) await this.waitForAuthenticated();`
975
+ * to preserve synchronous execution when already authenticated.
976
+ */
977
+ private waitForAuthenticated;
613
978
  private send;
614
979
  /**
615
980
  * @internal Send a set operation.
@@ -668,12 +1033,22 @@ declare class LarkDatabase {
668
1033
  * @internal Send an onDisconnect operation.
669
1034
  */
670
1035
  _sendOnDisconnect(path: string, action: string, value?: unknown): Promise<void>;
1036
+ /**
1037
+ * @internal Get a cached value from the subscription manager.
1038
+ * Used for optimistic writes where we need the current value without a network fetch.
1039
+ */
1040
+ _getCachedValue(path: string): {
1041
+ value: unknown;
1042
+ found: boolean;
1043
+ };
671
1044
  /**
672
1045
  * @internal Send a subscribe message to server.
1046
+ * Includes tag for non-default queries to enable proper event routing.
673
1047
  */
674
1048
  private sendSubscribeMessage;
675
1049
  /**
676
1050
  * @internal Send an unsubscribe message to server.
1051
+ * Includes query params and tag so server can identify which specific subscription to remove.
677
1052
  */
678
1053
  private sendUnsubscribeMessage;
679
1054
  /**
@@ -683,7 +1058,7 @@ declare class LarkDatabase {
683
1058
  /**
684
1059
  * @internal Subscribe to events at a path.
685
1060
  */
686
- _subscribe(path: string, eventType: EventType, callback: SnapshotCallback, queryParams?: QueryParams): () => void;
1061
+ _subscribe(path: string, eventType: EventType, callback: SnapshotCallback, queryParams?: QueryParams, queryIdentifier?: string): () => void;
687
1062
  /**
688
1063
  * @internal Unsubscribe from a specific event type at a path.
689
1064
  */
@@ -807,4 +1182,4 @@ declare function generatePushId(): string;
807
1182
  */
808
1183
  declare function isVolatilePath(path: string, patterns: string[] | null | undefined): boolean;
809
1184
 
810
- export { type AuthInfo, type ConnectOptions, DataSnapshot, DatabaseReference, type EventType, LarkDatabase, LarkError, OnDisconnect, type PendingWrite, PendingWriteManager, type QueryParams, type QueryState, type SnapshotCallback$1 as SnapshotCallback, type TransactionConditionOp, type TransactionDeleteOp, type TransactionObject, type TransactionOp, type TransactionResult, type TransactionSetOp, type TransactionUpdateOp, type TransportType, type WriteOperation, generatePushId, isVolatilePath };
1185
+ export { type AuthInfo, type ConnectOptions, DataSnapshot, DatabaseReference, type EventType, LarkDatabase, LarkError, OnDisconnect, type PendingWrite, PendingWriteManager, type QueryParams, type QueryState, ServerValue, type SnapshotCallback$1 as SnapshotCallback, ThenableReference, type TransactionConditionOp, type TransactionDeleteOp, type TransactionObject, type TransactionOp, type TransactionResult, type TransactionSetOp, type TransactionUpdateOp, type TransportType, type WriteOperation, generatePushId, isVolatilePath };