dexie-cloud-addon 4.2.0 → 4.2.2
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/dexie-cloud-import.json +6 -0
- package/dist/modern/dexie-cloud-addon.js +193 -68
- package/dist/modern/dexie-cloud-addon.js.map +1 -1
- package/dist/modern/dexie-cloud-addon.min.js +1 -1
- package/dist/modern/dexie-cloud-addon.min.js.map +1 -1
- package/dist/modern/service-worker.js +193 -68
- package/dist/modern/service-worker.js.map +1 -1
- package/dist/modern/service-worker.min.js +1 -1
- package/dist/modern/service-worker.min.js.map +1 -1
- package/dist/umd/dexie-cloud-addon.js +194 -69
- package/dist/umd/dexie-cloud-addon.js.map +1 -1
- package/dist/umd/dexie-cloud-addon.min.js +1 -1
- package/dist/umd/dexie-cloud-addon.min.js.map +1 -1
- package/dist/umd/service-worker.js +194 -69
- package/dist/umd/service-worker.js.map +1 -1
- package/dist/umd/service-worker.min.js +1 -1
- package/dist/umd/service-worker.min.js.map +1 -1
- package/package.json +4 -4
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* ==========================================================================
|
|
10
10
|
*
|
|
11
|
-
* Version 4.2.
|
|
11
|
+
* Version 4.2.2, Sat Oct 04 2025
|
|
12
12
|
*
|
|
13
13
|
* https://dexie.org
|
|
14
14
|
*
|
|
@@ -409,17 +409,14 @@
|
|
|
409
409
|
: mutationTable;
|
|
410
410
|
if (limit < Infinity)
|
|
411
411
|
query = query.limit(limit);
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
mut.values = await objTable.bulkGet(mut.keys);
|
|
417
|
-
}
|
|
418
|
-
}*/
|
|
419
|
-
return muts.map((mut) => ({
|
|
412
|
+
let muts = yield query.toArray();
|
|
413
|
+
muts = canonicalizeToUpdateOps(muts);
|
|
414
|
+
muts = removeRedundantUpdateOps(muts);
|
|
415
|
+
const rv = muts.map((mut) => ({
|
|
420
416
|
table: tableName,
|
|
421
417
|
mut,
|
|
422
418
|
}));
|
|
419
|
+
return rv;
|
|
423
420
|
})));
|
|
424
421
|
// Sort by time to get a true order of the operations (between tables)
|
|
425
422
|
const sorted = flatten(allMutsOnTables).sort((a, b) => a.mut.txid === b.mut.txid
|
|
@@ -448,6 +445,69 @@
|
|
|
448
445
|
return result;
|
|
449
446
|
});
|
|
450
447
|
}
|
|
448
|
+
function removeRedundantUpdateOps(muts) {
|
|
449
|
+
const updateCoverage = new Map();
|
|
450
|
+
for (const mut of muts) {
|
|
451
|
+
if (mut.type === 'update') {
|
|
452
|
+
if (mut.keys.length !== 1 || mut.changeSpecs.length !== 1) {
|
|
453
|
+
continue; // Don't optimize multi-key updates
|
|
454
|
+
}
|
|
455
|
+
const strKey = '' + mut.keys[0];
|
|
456
|
+
const changeSpecs = mut.changeSpecs[0];
|
|
457
|
+
if (Object.values(changeSpecs).some(v => typeof v === "object" && v && "@@propmod" in v)) {
|
|
458
|
+
continue; // Cannot optimize if any PropModification is present
|
|
459
|
+
}
|
|
460
|
+
let keyCoverage = updateCoverage.get(strKey);
|
|
461
|
+
if (keyCoverage) {
|
|
462
|
+
keyCoverage.push({ txid: mut.txid, updateSpec: changeSpecs });
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
updateCoverage.set(strKey, [{ txid: mut.txid, updateSpec: changeSpecs }]);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
muts = muts.filter(mut => {
|
|
470
|
+
// Only apply optimization to update mutations that are single-key
|
|
471
|
+
if (mut.type !== 'update')
|
|
472
|
+
return true;
|
|
473
|
+
if (mut.keys.length !== 1 || mut.changeSpecs.length !== 1)
|
|
474
|
+
return true;
|
|
475
|
+
// Keep track of properties that aren't overlapped by later transactions
|
|
476
|
+
const unoverlappedProps = new Set(Object.keys(mut.changeSpecs[0]));
|
|
477
|
+
const strKey = '' + mut.keys[0];
|
|
478
|
+
const keyCoverage = updateCoverage.get(strKey);
|
|
479
|
+
for (let i = keyCoverage.length - 1; i >= 0; --i) {
|
|
480
|
+
const { txid, updateSpec } = keyCoverage[i];
|
|
481
|
+
if (txid === mut.txid)
|
|
482
|
+
break; // Stop when reaching own txid
|
|
483
|
+
// If all changes in updateSpec are covered by all props on all mut.changeSpecs then
|
|
484
|
+
// txid is redundant and can be removed.
|
|
485
|
+
for (const keyPath of Object.keys(updateSpec)) {
|
|
486
|
+
unoverlappedProps.delete(keyPath);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
if (unoverlappedProps.size === 0) {
|
|
490
|
+
// This operation is completely overlapped by later operations. It can be removed.
|
|
491
|
+
return false;
|
|
492
|
+
}
|
|
493
|
+
return true;
|
|
494
|
+
});
|
|
495
|
+
return muts;
|
|
496
|
+
}
|
|
497
|
+
function canonicalizeToUpdateOps(muts) {
|
|
498
|
+
muts = muts.map(mut => {
|
|
499
|
+
if (mut.type === 'modify' && mut.criteria.index === null) {
|
|
500
|
+
// The criteria is on primary key. Convert to an update operation instead.
|
|
501
|
+
// It is simpler for the server to handle and also more efficient.
|
|
502
|
+
const updateMut = Object.assign(Object.assign({}, mut), { criteria: undefined, changeSpec: undefined, type: 'update', keys: mut.keys, changeSpecs: [mut.changeSpec] });
|
|
503
|
+
delete updateMut.criteria;
|
|
504
|
+
delete updateMut.changeSpec;
|
|
505
|
+
return updateMut;
|
|
506
|
+
}
|
|
507
|
+
return mut;
|
|
508
|
+
});
|
|
509
|
+
return muts;
|
|
510
|
+
}
|
|
451
511
|
|
|
452
512
|
function randomString$1(bytes) {
|
|
453
513
|
const buf = new Uint8Array(bytes);
|
|
@@ -13889,7 +13949,7 @@
|
|
|
13889
13949
|
*
|
|
13890
13950
|
* ==========================================================================
|
|
13891
13951
|
*
|
|
13892
|
-
* Version 4.2.
|
|
13952
|
+
* Version 4.2.1, Sat Oct 04 2025
|
|
13893
13953
|
*
|
|
13894
13954
|
* https://dexie.org
|
|
13895
13955
|
*
|
|
@@ -16005,6 +16065,7 @@
|
|
|
16005
16065
|
let values = 'values' in req ? req.values : [];
|
|
16006
16066
|
let changeSpec = 'changeSpec' in req ? req.changeSpec : undefined;
|
|
16007
16067
|
let updates = 'updates' in req ? req.updates : undefined;
|
|
16068
|
+
let upsert = updates && 'upsert' in req ? req.upsert : false;
|
|
16008
16069
|
if (hasFailures) {
|
|
16009
16070
|
keys = keys.filter((_, idx) => !failures[idx]);
|
|
16010
16071
|
values = values.filter((_, idx) => !failures[idx]);
|
|
@@ -16036,29 +16097,32 @@
|
|
|
16036
16097
|
};
|
|
16037
16098
|
const validKeys = new Dexie.RangeSet();
|
|
16038
16099
|
let anyChangeSpecBecameEmpty = false;
|
|
16039
|
-
|
|
16040
|
-
|
|
16041
|
-
|
|
16042
|
-
|
|
16043
|
-
|
|
16044
|
-
|
|
16045
|
-
|
|
16046
|
-
|
|
16100
|
+
if (!upsert) {
|
|
16101
|
+
for (let i = 0, l = strippedChangeSpecs.length; i < l; ++i) {
|
|
16102
|
+
if (Object.keys(strippedChangeSpecs[i]).length > 0) {
|
|
16103
|
+
newUpdates.keys.push(updates.keys[i]);
|
|
16104
|
+
newUpdates.changeSpecs.push(strippedChangeSpecs[i]);
|
|
16105
|
+
validKeys.addKey(updates.keys[i]);
|
|
16106
|
+
}
|
|
16107
|
+
else {
|
|
16108
|
+
anyChangeSpecBecameEmpty = true;
|
|
16109
|
+
}
|
|
16047
16110
|
}
|
|
16048
|
-
|
|
16049
|
-
|
|
16050
|
-
|
|
16051
|
-
|
|
16052
|
-
|
|
16053
|
-
|
|
16054
|
-
|
|
16055
|
-
|
|
16056
|
-
|
|
16057
|
-
|
|
16111
|
+
updates = newUpdates;
|
|
16112
|
+
if (anyChangeSpecBecameEmpty) {
|
|
16113
|
+
// Some keys were stripped. We must also strip them from keys and values
|
|
16114
|
+
// unless this is an upsert operation in which case we want to send them all.
|
|
16115
|
+
let newKeys = [];
|
|
16116
|
+
let newValues = [];
|
|
16117
|
+
for (let i = 0, l = keys.length; i < l; ++i) {
|
|
16118
|
+
if (validKeys.hasKey(keys[i])) {
|
|
16119
|
+
newKeys.push(keys[i]);
|
|
16120
|
+
newValues.push(values[i]);
|
|
16121
|
+
}
|
|
16058
16122
|
}
|
|
16123
|
+
keys = newKeys;
|
|
16124
|
+
values = newValues;
|
|
16059
16125
|
}
|
|
16060
|
-
keys = newKeys;
|
|
16061
|
-
values = newValues;
|
|
16062
16126
|
}
|
|
16063
16127
|
}
|
|
16064
16128
|
}
|
|
@@ -16100,49 +16164,59 @@
|
|
|
16100
16164
|
userId,
|
|
16101
16165
|
values,
|
|
16102
16166
|
}
|
|
16103
|
-
:
|
|
16104
|
-
|
|
16105
|
-
|
|
16106
|
-
|
|
16107
|
-
|
|
16108
|
-
|
|
16109
|
-
|
|
16110
|
-
|
|
16111
|
-
|
|
16112
|
-
|
|
16113
|
-
|
|
16114
|
-
}
|
|
16115
|
-
: changeSpec
|
|
16167
|
+
: upsert ? {
|
|
16168
|
+
type: 'upsert',
|
|
16169
|
+
ts,
|
|
16170
|
+
opNo,
|
|
16171
|
+
keys,
|
|
16172
|
+
values,
|
|
16173
|
+
changeSpecs: updates.changeSpecs.filter((_, idx) => !failures[idx]),
|
|
16174
|
+
txid,
|
|
16175
|
+
userId,
|
|
16176
|
+
}
|
|
16177
|
+
: criteria && changeSpec
|
|
16116
16178
|
? {
|
|
16117
|
-
//
|
|
16118
|
-
type: '
|
|
16179
|
+
// Common changeSpec for all keys
|
|
16180
|
+
type: 'modify',
|
|
16119
16181
|
ts,
|
|
16120
16182
|
opNo,
|
|
16121
16183
|
keys,
|
|
16122
|
-
|
|
16184
|
+
criteria,
|
|
16185
|
+
changeSpec,
|
|
16123
16186
|
txid,
|
|
16124
16187
|
userId,
|
|
16125
16188
|
}
|
|
16126
|
-
:
|
|
16189
|
+
: changeSpec
|
|
16127
16190
|
? {
|
|
16128
|
-
//
|
|
16191
|
+
// In case criteria involved an unsynced property, we go for keys instead.
|
|
16129
16192
|
type: 'update',
|
|
16130
16193
|
ts,
|
|
16131
16194
|
opNo,
|
|
16132
|
-
keys: updates.keys,
|
|
16133
|
-
changeSpecs: updates.changeSpecs,
|
|
16134
|
-
txid,
|
|
16135
|
-
userId,
|
|
16136
|
-
}
|
|
16137
|
-
: {
|
|
16138
|
-
type: 'upsert',
|
|
16139
|
-
ts,
|
|
16140
|
-
opNo,
|
|
16141
16195
|
keys,
|
|
16142
|
-
|
|
16196
|
+
changeSpecs: keys.map(() => changeSpec),
|
|
16143
16197
|
txid,
|
|
16144
16198
|
userId,
|
|
16145
|
-
}
|
|
16199
|
+
}
|
|
16200
|
+
: updates
|
|
16201
|
+
? {
|
|
16202
|
+
// One changeSpec per key
|
|
16203
|
+
type: 'update',
|
|
16204
|
+
ts,
|
|
16205
|
+
opNo,
|
|
16206
|
+
keys: updates.keys,
|
|
16207
|
+
changeSpecs: updates.changeSpecs,
|
|
16208
|
+
txid,
|
|
16209
|
+
userId,
|
|
16210
|
+
}
|
|
16211
|
+
: {
|
|
16212
|
+
type: 'upsert',
|
|
16213
|
+
ts,
|
|
16214
|
+
opNo,
|
|
16215
|
+
keys,
|
|
16216
|
+
values,
|
|
16217
|
+
txid,
|
|
16218
|
+
userId,
|
|
16219
|
+
};
|
|
16146
16220
|
if ('isAdditionalChunk' in req && req.isAdditionalChunk) {
|
|
16147
16221
|
mut.isAdditionalChunk = true;
|
|
16148
16222
|
}
|
|
@@ -17299,34 +17373,85 @@
|
|
|
17299
17373
|
alignItems: "center",
|
|
17300
17374
|
display: "flex",
|
|
17301
17375
|
justifyContent: "center",
|
|
17376
|
+
padding: "16px",
|
|
17377
|
+
boxSizing: "border-box"
|
|
17302
17378
|
},
|
|
17303
17379
|
DialogInner: {
|
|
17304
17380
|
position: "relative",
|
|
17305
17381
|
color: "#222",
|
|
17306
17382
|
backgroundColor: "#fff",
|
|
17307
|
-
padding: "
|
|
17383
|
+
padding: "24px",
|
|
17308
17384
|
marginBottom: "2em",
|
|
17309
|
-
maxWidth: "
|
|
17385
|
+
maxWidth: "400px",
|
|
17386
|
+
width: "100%",
|
|
17310
17387
|
maxHeight: "90%",
|
|
17311
17388
|
overflowY: "auto",
|
|
17312
17389
|
border: "3px solid #3d3d5d",
|
|
17313
17390
|
borderRadius: "8px",
|
|
17314
17391
|
boxShadow: "0 0 80px 10px #666",
|
|
17315
|
-
width: "auto",
|
|
17316
17392
|
fontFamily: "sans-serif",
|
|
17393
|
+
boxSizing: "border-box"
|
|
17317
17394
|
},
|
|
17318
17395
|
Input: {
|
|
17319
17396
|
height: "35px",
|
|
17320
|
-
width: "
|
|
17397
|
+
width: "100%",
|
|
17398
|
+
maxWidth: "100%",
|
|
17321
17399
|
borderColor: "#ccf4",
|
|
17322
17400
|
outline: "none",
|
|
17323
|
-
fontSize: "
|
|
17324
|
-
padding: "8px"
|
|
17401
|
+
fontSize: "16px",
|
|
17402
|
+
padding: "8px",
|
|
17403
|
+
boxSizing: "border-box"
|
|
17404
|
+
},
|
|
17405
|
+
Button: {
|
|
17406
|
+
padding: "10px 20px",
|
|
17407
|
+
margin: "0 4px",
|
|
17408
|
+
border: "1px solid #d1d5db",
|
|
17409
|
+
borderRadius: "6px",
|
|
17410
|
+
backgroundColor: "#ffffff",
|
|
17411
|
+
cursor: "pointer",
|
|
17412
|
+
fontSize: "14px",
|
|
17413
|
+
fontWeight: "500",
|
|
17414
|
+
color: "#374151",
|
|
17415
|
+
transition: "all 0.2s ease"
|
|
17416
|
+
},
|
|
17417
|
+
PrimaryButton: {
|
|
17418
|
+
padding: "10px 20px",
|
|
17419
|
+
margin: "0 4px",
|
|
17420
|
+
border: "1px solid #3b82f6",
|
|
17421
|
+
borderRadius: "6px",
|
|
17422
|
+
backgroundColor: "#3b82f6",
|
|
17423
|
+
color: "white",
|
|
17424
|
+
cursor: "pointer",
|
|
17425
|
+
fontSize: "14px",
|
|
17426
|
+
fontWeight: "500",
|
|
17427
|
+
transition: "all 0.2s ease"
|
|
17428
|
+
},
|
|
17429
|
+
ButtonsDiv: {
|
|
17430
|
+
display: "flex",
|
|
17431
|
+
justifyContent: "flex-end",
|
|
17432
|
+
gap: "12px",
|
|
17433
|
+
marginTop: "24px",
|
|
17434
|
+
paddingTop: "20px"
|
|
17435
|
+
},
|
|
17436
|
+
Label: {
|
|
17437
|
+
display: "block",
|
|
17438
|
+
marginBottom: "12px",
|
|
17439
|
+
fontSize: "14px",
|
|
17440
|
+
fontWeight: "500",
|
|
17441
|
+
color: "#333"
|
|
17442
|
+
},
|
|
17443
|
+
WindowHeader: {
|
|
17444
|
+
margin: "0 0 20px 0",
|
|
17445
|
+
fontSize: "18px",
|
|
17446
|
+
fontWeight: "600",
|
|
17447
|
+
color: "#333",
|
|
17448
|
+
borderBottom: "1px solid #eee",
|
|
17449
|
+
paddingBottom: "10px"
|
|
17325
17450
|
}
|
|
17326
17451
|
};
|
|
17327
17452
|
|
|
17328
17453
|
function Dialog({ children, className }) {
|
|
17329
|
-
return (h("div", { className: className },
|
|
17454
|
+
return (h("div", { className: `dexie-dialog ${className || ''}` },
|
|
17330
17455
|
h("div", { style: Styles.Darken }),
|
|
17331
17456
|
h("div", { style: Styles.DialogOuter },
|
|
17332
17457
|
h("div", { style: Styles.DialogInner }, children))));
|
|
@@ -17378,7 +17503,7 @@
|
|
|
17378
17503
|
} })))))),
|
|
17379
17504
|
h("div", { style: Styles.ButtonsDiv },
|
|
17380
17505
|
h(p$1, null,
|
|
17381
|
-
h("button", { type: "submit", style: Styles.
|
|
17506
|
+
h("button", { type: "submit", style: Styles.PrimaryButton, onClick: () => onSubmit(params) }, submitLabel),
|
|
17382
17507
|
cancelLabel && (h("button", { style: Styles.Button, onClick: onCancel }, cancelLabel))))));
|
|
17383
17508
|
}
|
|
17384
17509
|
function valueTransformer(type, value) {
|
|
@@ -18009,7 +18134,7 @@
|
|
|
18009
18134
|
const syncComplete = new rxjs.Subject();
|
|
18010
18135
|
dexie.cloud = {
|
|
18011
18136
|
// @ts-ignore
|
|
18012
|
-
version: "4.2.
|
|
18137
|
+
version: "4.2.2",
|
|
18013
18138
|
options: Object.assign({}, DEFAULT_OPTIONS),
|
|
18014
18139
|
schema: null,
|
|
18015
18140
|
get currentUserId() {
|
|
@@ -18326,7 +18451,7 @@
|
|
|
18326
18451
|
}
|
|
18327
18452
|
}
|
|
18328
18453
|
// @ts-ignore
|
|
18329
|
-
dexieCloud.version = "4.2.
|
|
18454
|
+
dexieCloud.version = "4.2.2";
|
|
18330
18455
|
Dexie.Cloud = dexieCloud;
|
|
18331
18456
|
|
|
18332
18457
|
// In case the SW lives for a while, let it reuse already opened connections:
|