@jcbuisson/express-x-client 3.1.14 → 3.1.15
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/package.json +1 -1
- package/src/client.mts +30 -5
package/package.json
CHANGED
package/src/client.mts
CHANGED
|
@@ -199,8 +199,9 @@ export function offlinePlugin(app) {
|
|
|
199
199
|
|
|
200
200
|
app.service(modelName).on('createWithMeta', async ([value, meta]) => {
|
|
201
201
|
console.log(`${modelName} EVENT createWithMeta`, value);
|
|
202
|
-
await
|
|
203
|
-
await db.
|
|
202
|
+
if (await isIncomingEventStale(value?.uid ?? meta?.uid, meta)) return
|
|
203
|
+
if (value?.uid) await db.values.put(value);
|
|
204
|
+
if (meta?.uid) await db.metadata.put({ ...meta, __dirty__: false });
|
|
204
205
|
});
|
|
205
206
|
|
|
206
207
|
app.service(modelName).on('updateWithMeta', async ([value, meta]) => {
|
|
@@ -209,21 +210,31 @@ export function offlinePlugin(app) {
|
|
|
209
210
|
// (concurrent delete race: record was removed between the sync's findMany
|
|
210
211
|
// snapshot and the actual update). Guard to avoid a TypeError crash that
|
|
211
212
|
// would prevent db.metadata.put(meta) from running.
|
|
213
|
+
if (await isIncomingEventStale(value?.uid ?? meta?.uid, meta)) return
|
|
212
214
|
if (value?.uid) await db.values.put(value);
|
|
213
|
-
await db.metadata.put(meta);
|
|
215
|
+
if (meta?.uid) await db.metadata.put({ ...meta, __dirty__: false });
|
|
214
216
|
});
|
|
215
217
|
|
|
216
218
|
app.service(modelName).on('deleteWithMeta', async ([value, meta]) => {
|
|
217
219
|
console.log(`${modelName} EVENT deleteWithMeta`, value)
|
|
218
220
|
// value may be undefined when the server's delete yielded 0 rows
|
|
219
221
|
// (double-delete race).
|
|
220
|
-
if (value?.uid) await db.values.delete(value.uid)
|
|
221
222
|
// delete, not put: synchronize() step 2 also deletes idbMetadata for the same
|
|
222
223
|
// uid. If the pub/sub handler fires AFTER step 2, put() would re-create the
|
|
223
224
|
// metadata row as a permanent orphan. delete() is idempotent regardless of order.
|
|
224
|
-
|
|
225
|
+
const uid = value?.uid ?? meta?.uid
|
|
226
|
+
if (await isIncomingEventStale(uid, meta)) return
|
|
227
|
+
if (value?.uid) await db.values.delete(value.uid)
|
|
228
|
+
if (uid) await db.metadata.delete(uid)
|
|
225
229
|
});
|
|
226
230
|
|
|
231
|
+
async function isIncomingEventStale(uid, incomingMeta) {
|
|
232
|
+
if (!uid || !incomingMeta) return false
|
|
233
|
+
const currentMeta = await db.metadata.get(uid)
|
|
234
|
+
if (!currentMeta) return false
|
|
235
|
+
return compareMetadataTime(currentMeta, incomingMeta) > 0
|
|
236
|
+
}
|
|
237
|
+
|
|
227
238
|
|
|
228
239
|
///////////// CREATE/UPDATE/REMOVE /////////////
|
|
229
240
|
|
|
@@ -664,6 +675,20 @@ function sameTimestamp(a, b) {
|
|
|
664
675
|
return new Date(a).getTime() === new Date(b).getTime()
|
|
665
676
|
}
|
|
666
677
|
|
|
678
|
+
function compareMetadataTime(a, b) {
|
|
679
|
+
const aTime = metadataTime(a)
|
|
680
|
+
const bTime = metadataTime(b)
|
|
681
|
+
if (aTime == null || bTime == null) return 0
|
|
682
|
+
return aTime - bTime
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
function metadataTime(meta) {
|
|
686
|
+
const value = meta?.deleted_at ?? meta?.updated_at ?? meta?.created_at
|
|
687
|
+
if (!value) return null
|
|
688
|
+
const time = new Date(value).getTime()
|
|
689
|
+
return Number.isNaN(time) ? null : time
|
|
690
|
+
}
|
|
691
|
+
|
|
667
692
|
export class Mutex {
|
|
668
693
|
constructor() {
|
|
669
694
|
this.locked = false;
|