@jcbuisson/express-x-client 3.1.7 → 3.1.9

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/client.mts +23 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jcbuisson/express-x-client",
3
- "version": "3.1.7",
3
+ "version": "3.1.9",
4
4
  "type": "module",
5
5
  "description": "Client library for ExpressX framework",
6
6
  "main": "src/client.mts",
package/src/client.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import Dexie from "dexie";
2
- import { from } from 'rxjs';
3
- import { distinctUntilChanged, startWith } from 'rxjs/operators';
2
+ import { from, defer } from 'rxjs';
3
+ import { distinctUntilChanged, startWith, switchMap } from 'rxjs/operators';
4
4
  import { liveQuery } from "dexie";
5
5
  // uuidv7 are monotonically increasing and much improve database performance amid B-tree indexes
6
6
  import { v7 as uuidv7 } from 'uuid';
@@ -297,19 +297,33 @@ export function offlinePlugin(app) {
297
297
  ///////////// REAL-TIME OBSERVABLE /////////////
298
298
 
299
299
  function getObservable(where = {}) {
300
- addSynchroWhere(where).then((isNew: boolean) => {
301
- if (isNew && app.isConnected) {
302
- synchronize(modelName, db.values, db.metadata, where, app.disconnectedDate)
303
- }
304
- })
305
300
  const predicate = wherePredicate(where)
306
- return from(liveQuery(() => db.values.filter(value => !value.__deleted__ && predicate(value)).toArray())).pipe(
307
- startWith(undefined),
301
+ const liveQuery$ = from(liveQuery(() => db.values.filter(value => !value.__deleted__ && predicate(value)).toArray())).pipe(
308
302
  distinctUntilChanged((prev, curr) => {
309
303
  // Deep equality check to prevent unnecessary emissions (in particular on database write)
310
304
  return JSON.stringify(prev) === JSON.stringify(curr)
311
305
  })
312
306
  )
307
+
308
+ // Delay subscribing to liveQuery until the cache is up to date: if `where` is a
309
+ // newly-registered filter and we're online, wait for synchronize() to complete
310
+ // first, so the first emission is already the fully synced data (or [] if truly
311
+ // empty). Otherwise (warm cache or offline) there's nothing to wait for.
312
+ //
313
+ // defer() gates the liveQuery subscription:
314
+ // - defer re-runs the setup on each subscription, calling addSynchroWhere(where) to get isNew.
315
+ // - If isNew && app.isConnected, it chains synchronize(...) before switching to liveQuery$, so the first emission already reflects
316
+ // the fully-synced cache ([] only if genuinely empty).
317
+ // - If !isNew or offline, the .then resolves to undefined immediately and switchMap subscribes to liveQuery$ right away — same
318
+ // behavior as before.
319
+ return defer(() => {
320
+ const ready = addSynchroWhere(where).then((isNew: boolean) => {
321
+ if (isNew && app.isConnected) {
322
+ return synchronize(modelName, db.values, db.metadata, where, app.disconnectedDate)
323
+ }
324
+ })
325
+ return from(ready).pipe(switchMap(() => liveQuery$))
326
+ })
313
327
  }
314
328
 
315
329
  let count = 0;