edmaxlabs-core 2.5.6 → 2.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -114,57 +114,61 @@ declare class DocumentRef {
114
114
  set(data: Record<string, any>): Promise<DocumentSnapshot | null>;
115
115
  delete(): Promise<boolean>;
116
116
  onSnapshot(callback: (snapshot: DocumentSnapshot | null, change: string) => void): () => void;
117
+ private fetchRemoteSnapshot;
118
+ private refreshFromRemote;
119
+ }
120
+
121
+ type SnapshotSource = "initial" | "insert" | "update" | "delete";
122
+ type ChildChangeType = "added" | "modified" | "removed";
123
+ interface ChildChange {
124
+ type: ChildChangeType;
125
+ doc: DocumentSnapshot;
126
+ previousDoc: DocumentSnapshot | null;
127
+ oldIndex: number;
128
+ newIndex: number;
129
+ }
130
+ interface CollectionEmission {
131
+ snapshots: DocumentSnapshot[];
132
+ source: SnapshotSource;
133
+ changedDocId?: string;
134
+ fromCache?: boolean;
135
+ childChanges?: ChildChange[];
136
+ }
137
+ interface ChildListenerContext {
138
+ snapshots: DocumentSnapshot[];
139
+ source: SnapshotSource;
140
+ changedDocId?: string;
141
+ fromCache: boolean;
142
+ oldIndex: number;
143
+ newIndex: number;
144
+ previousDoc: DocumentSnapshot | null;
145
+ }
146
+ interface ChildListenerCallbacks {
147
+ onChildAdded?: (snapshot: DocumentSnapshot, context: ChildListenerContext) => void;
148
+ onChildUpdated?: (snapshot: DocumentSnapshot, context: ChildListenerContext) => void;
149
+ onChildRemoved?: (snapshot: DocumentSnapshot, context: ChildListenerContext) => void;
117
150
  }
118
151
 
119
152
  type DocListener = (snapshot: DocumentSnapshot | null, change: string) => void;
120
- /**
121
- * For collection listeners we pass:
122
- * - snapshots: all current documents in the collection
123
- * - change: what triggered this emission
124
- * - changedDocId?: which specific document changed (useful for granular updates)
125
- */
126
153
  type CollectionListener = (snapshots: DocumentSnapshot[], change: string, changedDocId?: string) => void;
127
154
  declare class LocalStore {
128
155
  private documentListeners;
129
156
  private collectionListeners;
157
+ private childListeners;
130
158
  private docKey;
131
159
  subscribeToDocument(collection: string, id: string, callback: DocListener): () => void;
132
- subscribeToCollection(collection: string, callback: CollectionListener): () => void;
133
- /**
134
- * Notify all listeners for a specific document
135
- */
160
+ subscribeToCollection(targetKey: string, callback: CollectionListener): () => void;
161
+ subscribeToChildEvents(targetKey: string, callbacks: ChildListenerCallbacks): () => void;
136
162
  emitDocument(collection: string, id: string, snapshot: DocumentSnapshot | null, change: string): void;
137
- /**
138
- * Notify all listeners for a collection.
139
- * This is the most important fix — collection listeners now receive the full list.
140
- */
141
- emitCollection(collection: string, snapshots: DocumentSnapshot[], // ← Changed from single snapshot
142
- change: string, changedDocId?: string): void;
143
- /**
144
- * OPTIMIZED: Notify collection listeners that something changed, without fetching full collection.
145
- * Listeners can call getCollectionSnapshots() themselves if they need the full list.
146
- * This avoids expensive collection queries after every single mutation.
147
- */
148
- notifyCollectionChanged(collection: string, changedDocId: string, change: string): void;
149
- /**
150
- * Clear all listeners (useful for testing or when persistence is disabled)
151
- */
163
+ emitCollection(targetKey: string, emission: CollectionEmission): void;
152
164
  clearAllListeners(): void;
153
- /**
154
- * Get current listener count (for debugging / dev tools)
155
- */
156
165
  get listenerCount(): {
157
166
  documents: number;
158
167
  collections: number;
159
168
  };
160
- /**
161
- * Remove all listeners for a specific collection (useful for cleanup)
162
- */
163
- removeCollectionListeners(collection: string): void;
164
- /**
165
- * Remove all listeners for a specific document (useful for cleanup)
166
- */
169
+ removeCollectionListeners(targetKey: string): void;
167
170
  removeDocumentListeners(collection: string, id: string): void;
171
+ private dispatchChildEvent;
168
172
  }
169
173
 
170
174
  type FilterExpression = {
@@ -179,14 +183,18 @@ declare class Query {
179
183
  private localStore;
180
184
  constructor(app: EdmaxLabs, collection: string);
181
185
  where(expression: FilterExpression): Query;
186
+ get(): Promise<DocumentSnapshot[]>;
187
+ update(data: Record<string, any>): Promise<any>;
188
+ onSnapshot(callback: CollectionListener): () => void;
189
+ onChildListener(callbacks: ChildListenerCallbacks): () => void;
182
190
  private buildFilter;
183
191
  private matchesFilter;
184
192
  private filterDocuments;
185
193
  private getLocalFilteredSnapshots;
186
- get(): Promise<DocumentSnapshot[]>;
187
194
  private refreshFromRemote;
188
- update(data: Record<string, any>): Promise<any>;
189
- onSnapshot(callback: CollectionListener): () => void;
195
+ private subscribeOnlineSnapshot;
196
+ private subscribeOnlineChildListener;
197
+ private emitInitialChildEvents;
190
198
  }
191
199
 
192
200
  declare class CollectionRef {
@@ -199,9 +207,14 @@ declare class CollectionRef {
199
207
  doc(id: string): DocumentRef;
200
208
  get query(): Query;
201
209
  get(): Promise<DocumentSnapshot[]>;
202
- private refreshFromRemote;
203
210
  add(data: Record<string, any>): Promise<DocumentSnapshot | null>;
204
211
  onSnapshot(callback: CollectionListener): () => void;
212
+ onChildListener(callbacks: ChildListenerCallbacks): () => void;
213
+ private refreshFromRemote;
214
+ private fetchRemoteSnapshots;
215
+ private subscribeOnlineSnapshot;
216
+ private subscribeOnlineChildListener;
217
+ private emitInitialChildEvents;
205
218
  }
206
219
 
207
220
  declare class Batch {
@@ -327,6 +340,8 @@ declare class Persistence {
327
340
  markDeleted(collection: string, id: string, pending?: number): Promise<LocalDoc>;
328
341
  enqueueMutation(mutation: Omit<MutationRecord, "updatedAt" | "createdAt" | "retryCount" | "status">): Promise<MutationRecord>;
329
342
  getPendingMutations(): Promise<MutationRecord[]>;
343
+ getFailedMutations(): Promise<MutationRecord[]>;
344
+ recoverSyncingMutations(): Promise<number>;
330
345
  getMutation(mutationId: string): Promise<MutationRecord | null>;
331
346
  resetMutation(mutationId: string): Promise<MutationRecord | null>;
332
347
  setMutationStatus(mutationId: string, status: MutationRecord["status"], error?: string): Promise<MutationRecord | null>;
@@ -334,6 +349,7 @@ declare class Persistence {
334
349
  replaceDocId(collection: string, oldId: string, newId: string): Promise<LocalDoc | null>;
335
350
  applyRemoteDoc(collection: string, data: Record<string, any>, revision?: string | number): Promise<LocalDoc | null>;
336
351
  applyRemoteDelete(collection: string, id: string): Promise<LocalDoc | null>;
352
+ reconcileCollectionFromRemote(collection: string, documents: Record<string, any>[]): Promise<void>;
337
353
  createLocalId(): string;
338
354
  createMutationId(): string;
339
355
  clearAll(): Promise<void>;
@@ -344,25 +360,25 @@ declare class RealtimeBridge {
344
360
  private app;
345
361
  private persistence;
346
362
  private store;
347
- private collectionUnsubs;
348
- private documentUnsubs;
363
+ private collectionTargets;
364
+ private documentTargets;
349
365
  constructor(app: EdmaxLabs, persistence: Persistence, store: LocalStore);
350
366
  private docKey;
351
- watchCollection(collection: string, filter?: Record<string, any>): () => void;
367
+ watchCollection(collection: string, filter: Record<string, any> | undefined, read: () => Promise<DocumentSnapshot[]>): () => void;
352
368
  watchDocument(collection: string, id: string): () => void;
353
- private emitCurrentDocument;
354
- private emitCurrentCollection;
355
- private handleRemoteCreateOrUpdate;
356
- private handleRemoteDelete;
357
- /**
358
- * Call this when Socket.IO reconnects or when going online
359
- * Replays pending mutations + refreshes all active subscriptions from cache
360
- */
369
+ emitCurrentCollection(collection: string, filter?: Record<string, any>): Promise<DocumentSnapshot[]>;
370
+ primeCollectionTarget(collection: string, filter: Record<string, any>, snapshots: DocumentSnapshot[]): void;
371
+ emitCurrentDocument(collection: string, id: string): Promise<DocumentSnapshot | null>;
372
+ publishLocalChange(collection: string, id: string, source: SnapshotSource): Promise<void>;
361
373
  onReconnect(): Promise<void>;
362
- /**
363
- * Clean up all subscriptions (call from EdmaxLabs destructor if needed)
364
- */
365
374
  dispose(): void;
375
+ private handleRemoteCreateOrUpdate;
376
+ private handleRemoteDelete;
377
+ private getCurrentDocumentSnapshot;
378
+ private refreshCollectionTargets;
379
+ private refreshCollectionTarget;
380
+ private releaseCollection;
381
+ private releaseDocument;
366
382
  }
367
383
 
368
384
  declare class SyncEngine {
@@ -374,6 +390,8 @@ declare class SyncEngine {
374
390
  private retryTimeout;
375
391
  private readonly MAX_RETRIES;
376
392
  private readonly BASE_RETRY_DELAY;
393
+ private readonly handleOnline;
394
+ private readonly handleVisibilityChange;
377
395
  constructor(app: EdmaxLabs, persistence: Persistence, store: LocalStore, realtimeBridge?: RealtimeBridge);
378
396
  private onNetworkOnline;
379
397
  flush(): Promise<void>;
@@ -504,4 +522,4 @@ declare class ArraySnapshot {
504
522
  toMap(): Record<string, any>;
505
523
  }
506
524
 
507
- export { ArraySnapshot, Authentication, Credentials, DisplayInfo, DocumentSnapshot, EdmaxLabsConfig, StorageSnapshot, Timestamp, EdmaxLabs as default };
525
+ export { ArraySnapshot, Authentication, ChildChange, ChildListenerCallbacks, ChildListenerContext, Credentials, DisplayInfo, DocumentSnapshot, EdmaxLabsConfig, StorageSnapshot, Timestamp, EdmaxLabs as default };
package/dist/index.d.ts CHANGED
@@ -114,57 +114,61 @@ declare class DocumentRef {
114
114
  set(data: Record<string, any>): Promise<DocumentSnapshot | null>;
115
115
  delete(): Promise<boolean>;
116
116
  onSnapshot(callback: (snapshot: DocumentSnapshot | null, change: string) => void): () => void;
117
+ private fetchRemoteSnapshot;
118
+ private refreshFromRemote;
119
+ }
120
+
121
+ type SnapshotSource = "initial" | "insert" | "update" | "delete";
122
+ type ChildChangeType = "added" | "modified" | "removed";
123
+ interface ChildChange {
124
+ type: ChildChangeType;
125
+ doc: DocumentSnapshot;
126
+ previousDoc: DocumentSnapshot | null;
127
+ oldIndex: number;
128
+ newIndex: number;
129
+ }
130
+ interface CollectionEmission {
131
+ snapshots: DocumentSnapshot[];
132
+ source: SnapshotSource;
133
+ changedDocId?: string;
134
+ fromCache?: boolean;
135
+ childChanges?: ChildChange[];
136
+ }
137
+ interface ChildListenerContext {
138
+ snapshots: DocumentSnapshot[];
139
+ source: SnapshotSource;
140
+ changedDocId?: string;
141
+ fromCache: boolean;
142
+ oldIndex: number;
143
+ newIndex: number;
144
+ previousDoc: DocumentSnapshot | null;
145
+ }
146
+ interface ChildListenerCallbacks {
147
+ onChildAdded?: (snapshot: DocumentSnapshot, context: ChildListenerContext) => void;
148
+ onChildUpdated?: (snapshot: DocumentSnapshot, context: ChildListenerContext) => void;
149
+ onChildRemoved?: (snapshot: DocumentSnapshot, context: ChildListenerContext) => void;
117
150
  }
118
151
 
119
152
  type DocListener = (snapshot: DocumentSnapshot | null, change: string) => void;
120
- /**
121
- * For collection listeners we pass:
122
- * - snapshots: all current documents in the collection
123
- * - change: what triggered this emission
124
- * - changedDocId?: which specific document changed (useful for granular updates)
125
- */
126
153
  type CollectionListener = (snapshots: DocumentSnapshot[], change: string, changedDocId?: string) => void;
127
154
  declare class LocalStore {
128
155
  private documentListeners;
129
156
  private collectionListeners;
157
+ private childListeners;
130
158
  private docKey;
131
159
  subscribeToDocument(collection: string, id: string, callback: DocListener): () => void;
132
- subscribeToCollection(collection: string, callback: CollectionListener): () => void;
133
- /**
134
- * Notify all listeners for a specific document
135
- */
160
+ subscribeToCollection(targetKey: string, callback: CollectionListener): () => void;
161
+ subscribeToChildEvents(targetKey: string, callbacks: ChildListenerCallbacks): () => void;
136
162
  emitDocument(collection: string, id: string, snapshot: DocumentSnapshot | null, change: string): void;
137
- /**
138
- * Notify all listeners for a collection.
139
- * This is the most important fix — collection listeners now receive the full list.
140
- */
141
- emitCollection(collection: string, snapshots: DocumentSnapshot[], // ← Changed from single snapshot
142
- change: string, changedDocId?: string): void;
143
- /**
144
- * OPTIMIZED: Notify collection listeners that something changed, without fetching full collection.
145
- * Listeners can call getCollectionSnapshots() themselves if they need the full list.
146
- * This avoids expensive collection queries after every single mutation.
147
- */
148
- notifyCollectionChanged(collection: string, changedDocId: string, change: string): void;
149
- /**
150
- * Clear all listeners (useful for testing or when persistence is disabled)
151
- */
163
+ emitCollection(targetKey: string, emission: CollectionEmission): void;
152
164
  clearAllListeners(): void;
153
- /**
154
- * Get current listener count (for debugging / dev tools)
155
- */
156
165
  get listenerCount(): {
157
166
  documents: number;
158
167
  collections: number;
159
168
  };
160
- /**
161
- * Remove all listeners for a specific collection (useful for cleanup)
162
- */
163
- removeCollectionListeners(collection: string): void;
164
- /**
165
- * Remove all listeners for a specific document (useful for cleanup)
166
- */
169
+ removeCollectionListeners(targetKey: string): void;
167
170
  removeDocumentListeners(collection: string, id: string): void;
171
+ private dispatchChildEvent;
168
172
  }
169
173
 
170
174
  type FilterExpression = {
@@ -179,14 +183,18 @@ declare class Query {
179
183
  private localStore;
180
184
  constructor(app: EdmaxLabs, collection: string);
181
185
  where(expression: FilterExpression): Query;
186
+ get(): Promise<DocumentSnapshot[]>;
187
+ update(data: Record<string, any>): Promise<any>;
188
+ onSnapshot(callback: CollectionListener): () => void;
189
+ onChildListener(callbacks: ChildListenerCallbacks): () => void;
182
190
  private buildFilter;
183
191
  private matchesFilter;
184
192
  private filterDocuments;
185
193
  private getLocalFilteredSnapshots;
186
- get(): Promise<DocumentSnapshot[]>;
187
194
  private refreshFromRemote;
188
- update(data: Record<string, any>): Promise<any>;
189
- onSnapshot(callback: CollectionListener): () => void;
195
+ private subscribeOnlineSnapshot;
196
+ private subscribeOnlineChildListener;
197
+ private emitInitialChildEvents;
190
198
  }
191
199
 
192
200
  declare class CollectionRef {
@@ -199,9 +207,14 @@ declare class CollectionRef {
199
207
  doc(id: string): DocumentRef;
200
208
  get query(): Query;
201
209
  get(): Promise<DocumentSnapshot[]>;
202
- private refreshFromRemote;
203
210
  add(data: Record<string, any>): Promise<DocumentSnapshot | null>;
204
211
  onSnapshot(callback: CollectionListener): () => void;
212
+ onChildListener(callbacks: ChildListenerCallbacks): () => void;
213
+ private refreshFromRemote;
214
+ private fetchRemoteSnapshots;
215
+ private subscribeOnlineSnapshot;
216
+ private subscribeOnlineChildListener;
217
+ private emitInitialChildEvents;
205
218
  }
206
219
 
207
220
  declare class Batch {
@@ -327,6 +340,8 @@ declare class Persistence {
327
340
  markDeleted(collection: string, id: string, pending?: number): Promise<LocalDoc>;
328
341
  enqueueMutation(mutation: Omit<MutationRecord, "updatedAt" | "createdAt" | "retryCount" | "status">): Promise<MutationRecord>;
329
342
  getPendingMutations(): Promise<MutationRecord[]>;
343
+ getFailedMutations(): Promise<MutationRecord[]>;
344
+ recoverSyncingMutations(): Promise<number>;
330
345
  getMutation(mutationId: string): Promise<MutationRecord | null>;
331
346
  resetMutation(mutationId: string): Promise<MutationRecord | null>;
332
347
  setMutationStatus(mutationId: string, status: MutationRecord["status"], error?: string): Promise<MutationRecord | null>;
@@ -334,6 +349,7 @@ declare class Persistence {
334
349
  replaceDocId(collection: string, oldId: string, newId: string): Promise<LocalDoc | null>;
335
350
  applyRemoteDoc(collection: string, data: Record<string, any>, revision?: string | number): Promise<LocalDoc | null>;
336
351
  applyRemoteDelete(collection: string, id: string): Promise<LocalDoc | null>;
352
+ reconcileCollectionFromRemote(collection: string, documents: Record<string, any>[]): Promise<void>;
337
353
  createLocalId(): string;
338
354
  createMutationId(): string;
339
355
  clearAll(): Promise<void>;
@@ -344,25 +360,25 @@ declare class RealtimeBridge {
344
360
  private app;
345
361
  private persistence;
346
362
  private store;
347
- private collectionUnsubs;
348
- private documentUnsubs;
363
+ private collectionTargets;
364
+ private documentTargets;
349
365
  constructor(app: EdmaxLabs, persistence: Persistence, store: LocalStore);
350
366
  private docKey;
351
- watchCollection(collection: string, filter?: Record<string, any>): () => void;
367
+ watchCollection(collection: string, filter: Record<string, any> | undefined, read: () => Promise<DocumentSnapshot[]>): () => void;
352
368
  watchDocument(collection: string, id: string): () => void;
353
- private emitCurrentDocument;
354
- private emitCurrentCollection;
355
- private handleRemoteCreateOrUpdate;
356
- private handleRemoteDelete;
357
- /**
358
- * Call this when Socket.IO reconnects or when going online
359
- * Replays pending mutations + refreshes all active subscriptions from cache
360
- */
369
+ emitCurrentCollection(collection: string, filter?: Record<string, any>): Promise<DocumentSnapshot[]>;
370
+ primeCollectionTarget(collection: string, filter: Record<string, any>, snapshots: DocumentSnapshot[]): void;
371
+ emitCurrentDocument(collection: string, id: string): Promise<DocumentSnapshot | null>;
372
+ publishLocalChange(collection: string, id: string, source: SnapshotSource): Promise<void>;
361
373
  onReconnect(): Promise<void>;
362
- /**
363
- * Clean up all subscriptions (call from EdmaxLabs destructor if needed)
364
- */
365
374
  dispose(): void;
375
+ private handleRemoteCreateOrUpdate;
376
+ private handleRemoteDelete;
377
+ private getCurrentDocumentSnapshot;
378
+ private refreshCollectionTargets;
379
+ private refreshCollectionTarget;
380
+ private releaseCollection;
381
+ private releaseDocument;
366
382
  }
367
383
 
368
384
  declare class SyncEngine {
@@ -374,6 +390,8 @@ declare class SyncEngine {
374
390
  private retryTimeout;
375
391
  private readonly MAX_RETRIES;
376
392
  private readonly BASE_RETRY_DELAY;
393
+ private readonly handleOnline;
394
+ private readonly handleVisibilityChange;
377
395
  constructor(app: EdmaxLabs, persistence: Persistence, store: LocalStore, realtimeBridge?: RealtimeBridge);
378
396
  private onNetworkOnline;
379
397
  flush(): Promise<void>;
@@ -504,4 +522,4 @@ declare class ArraySnapshot {
504
522
  toMap(): Record<string, any>;
505
523
  }
506
524
 
507
- export { ArraySnapshot, Authentication, Credentials, DisplayInfo, DocumentSnapshot, EdmaxLabsConfig, StorageSnapshot, Timestamp, EdmaxLabs as default };
525
+ export { ArraySnapshot, Authentication, ChildChange, ChildListenerCallbacks, ChildListenerContext, Credentials, DisplayInfo, DocumentSnapshot, EdmaxLabsConfig, StorageSnapshot, Timestamp, EdmaxLabs as default };