@jcbuisson/express-x-client 3.1.12 → 3.1.13

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 +41 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jcbuisson/express-x-client",
3
- "version": "3.1.12",
3
+ "version": "3.1.13",
4
4
  "type": "module",
5
5
  "description": "Client library for ExpressX framework",
6
6
  "main": "src/client.mts",
package/src/client.mts CHANGED
@@ -233,10 +233,16 @@ export function offlinePlugin(app) {
233
233
  // optimistic update
234
234
  const now = new Date()
235
235
  await db.values.add({ uid, ...data })
236
- await db.metadata.add({ uid, created_at: now })
236
+ await db.metadata.add({ uid, created_at: now, __dirty__: true })
237
237
  // execute on server, asynchronously, if connection is active
238
238
  if (app.isConnected) {
239
239
  app.service(modelName).createWithMeta(uid, data, now)
240
+ .then(async result => {
241
+ const [value, meta] = Array.isArray(result) ? result : []
242
+ if (value?.uid) await db.values.put(value)
243
+ if (meta?.uid) await db.metadata.put({ ...meta, __dirty__: false })
244
+ else await db.metadata.update(uid, { __dirty__: false })
245
+ })
240
246
  .catch(async err => {
241
247
  console.log(`*** err sync ${modelName} create`, err)
242
248
  // rollback
@@ -253,10 +259,16 @@ export function offlinePlugin(app) {
253
259
  // optimistic update of cache
254
260
  const now = new Date()
255
261
  await db.values.update(uid, data)
256
- await db.metadata.update(uid, { updated_at: now })
262
+ await db.metadata.update(uid, { updated_at: now, __dirty__: true })
257
263
  // execute on server, asynchronously, if connection is active
258
264
  if (app.isConnected) {
259
265
  app.service(modelName).updateWithMeta(uid, data, now)
266
+ .then(async result => {
267
+ const [value, meta] = Array.isArray(result) ? result : []
268
+ if (value?.uid) await db.values.put(value)
269
+ if (meta?.uid) await db.metadata.put({ ...meta, __dirty__: false })
270
+ else await db.metadata.update(uid, { __dirty__: false })
271
+ })
260
272
  .catch(async err => {
261
273
  console.log(`*** err sync ${modelName} update`, err)
262
274
  // rollback
@@ -266,7 +278,10 @@ export function offlinePlugin(app) {
266
278
  // Restoring the full previousMetadata snapshot would overwrite any
267
279
  // deleted_at that remove() set while the socket round-trip was in flight,
268
280
  // silently un-deleting the record.
269
- await db.metadata.update(uid, { updated_at: previousMetadata.updated_at ?? null })
281
+ await db.metadata.update(uid, {
282
+ updated_at: previousMetadata.updated_at ?? null,
283
+ __dirty__: previousMetadata.__dirty__ ?? false,
284
+ })
270
285
  })
271
286
  }
272
287
  return await db.values.get(uid)
@@ -276,15 +291,20 @@ export function offlinePlugin(app) {
276
291
  const deleted_at = new Date()
277
292
  // optimistic delete in cache
278
293
  await db.values.update(uid, { __deleted__: true })
279
- await db.metadata.update(uid, { deleted_at })
294
+ await db.metadata.update(uid, { deleted_at, __dirty__: true })
280
295
  // and in database, if connected
281
296
  if (app.isConnected) {
282
297
  app.service(modelName).deleteWithMeta(uid, deleted_at)
298
+ .then(async result => {
299
+ const [, meta] = Array.isArray(result) ? result : []
300
+ if (meta?.uid) await db.metadata.put({ ...meta, __dirty__: false })
301
+ else await db.metadata.update(uid, { __dirty__: false })
302
+ })
283
303
  .catch(async err => {
284
304
  console.log(`*** err sync ${modelName} remove`, err)
285
305
  // rollback
286
306
  await db.values.update(uid, { __deleted__: null })
287
- await db.metadata.update(uid, { deleted_at: null })
307
+ await db.metadata.update(uid, { deleted_at: null, __dirty__: false })
288
308
  })
289
309
  }
290
310
  }
@@ -439,6 +459,12 @@ export function offlinePlugin(app) {
439
459
  clientMetadataDict[value.uid] = {}
440
460
  }
441
461
  }
462
+ const dirtyMetadataList = await idbMetadata.filter(metadata => metadata.__dirty__).toArray()
463
+ for (const metadata of dirtyMetadataList) {
464
+ if (metadata.uid in clientMetadataDict) continue
465
+ const value = await idbValues.get(metadata.uid)
466
+ if (value || metadata.deleted_at) clientMetadataDict[metadata.uid] = metadata
467
+ }
442
468
 
443
469
  // call sync service on `where` perimeter
444
470
  const { addClient, updateClient, deleteClient, addDatabase, updateDatabase } =
@@ -458,7 +484,7 @@ export function offlinePlugin(app) {
458
484
  // add() would throw ConstraintError and abort the entire transaction,
459
485
  // silently dropping every other addClient record in the batch.
460
486
  await idbValues.put(value)
461
- await idbMetadata.put(metaData)
487
+ await idbMetadata.put({ ...metaData, __dirty__: false })
462
488
  }
463
489
  })
464
490
  }
@@ -476,7 +502,7 @@ export function offlinePlugin(app) {
476
502
  const value = { ...elt }
477
503
  delete value.__deleted__
478
504
  await idbValues.put(value)
479
- await idbMetadata.put({ uid: elt.uid, ...serverMeta })
505
+ await idbMetadata.put({ uid: elt.uid, ...serverMeta, __dirty__: false })
480
506
  }
481
507
 
482
508
  // 4- create elements of `addDatabase` with full data from cache
@@ -491,7 +517,10 @@ export function offlinePlugin(app) {
491
517
  delete fullValue.uid
492
518
  delete fullValue.__deleted__
493
519
  try {
494
- await app.service(modelName).createWithMeta(elt.uid, fullValue, elt.created_at)
520
+ const result = await app.service(modelName).createWithMeta(elt.uid, fullValue, elt.created_at)
521
+ const serverMeta = Array.isArray(result) ? result[1] : null
522
+ if (serverMeta?.uid) await idbMetadata.put({ ...serverMeta, __dirty__: false })
523
+ else await idbMetadata.update(elt.uid, { __dirty__: false })
495
524
  } catch(err) {
496
525
  console.log("*** err sync user addDatabase", err, elt.uid, fullValue, elt.created_at)
497
526
  // rollback
@@ -508,7 +537,10 @@ export function offlinePlugin(app) {
508
537
  delete fullValue.uid
509
538
  delete fullValue.__deleted__
510
539
  try {
511
- await app.service(modelName).updateWithMeta(elt.uid, fullValue, elt.updated_at)
540
+ const result = await app.service(modelName).updateWithMeta(elt.uid, fullValue, elt.updated_at)
541
+ const serverMeta = Array.isArray(result) ? result[1] : null
542
+ if (serverMeta?.uid) await idbMetadata.put({ ...serverMeta, __dirty__: false })
543
+ else await idbMetadata.update(elt.uid, { __dirty__: false })
512
544
  } catch(err) {
513
545
  console.log("*** err sync user updateDatabase", err)
514
546
  // Leave client's local version intact; it will be retried on the next sync.