dexie 4.2.0 → 4.2.1

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.
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * By David Fahlander, david.fahlander@gmail.com
6
6
  *
7
- * Version 4.2.0, Wed Aug 13 2025
7
+ * Version 4.2.1, Sat Oct 04 2025
8
8
  *
9
9
  * https://dexie.org
10
10
  *
@@ -1096,7 +1096,7 @@ function tempTransaction(db, mode, storeNames, fn) {
1096
1096
  }
1097
1097
  }
1098
1098
 
1099
- const DEXIE_VERSION = '4.2.0';
1099
+ const DEXIE_VERSION = '4.2.1';
1100
1100
  const maxString = String.fromCharCode(65535);
1101
1101
  const minKey = -Infinity;
1102
1102
  const INVALID_KEY_ARGUMENT = "Invalid key provided. Keys must be of type string, number, Date or Array<string | number | Date>.";
@@ -1225,6 +1225,74 @@ function builtInDeletionTrigger(table, keys, res) {
1225
1225
  : table.db.table(updatesTable).clear())).then(() => res);
1226
1226
  }
1227
1227
 
1228
+ class PropModification {
1229
+ execute(value) {
1230
+ const spec = this["@@propmod"];
1231
+ if (spec.add !== undefined) {
1232
+ const term = spec.add;
1233
+ if (isArray(term)) {
1234
+ return [...(isArray(value) ? value : []), ...term].sort();
1235
+ }
1236
+ if (typeof term === 'number')
1237
+ return (Number(value) || 0) + term;
1238
+ if (typeof term === 'bigint') {
1239
+ try {
1240
+ return BigInt(value) + term;
1241
+ }
1242
+ catch {
1243
+ return BigInt(0) + term;
1244
+ }
1245
+ }
1246
+ throw new TypeError(`Invalid term ${term}`);
1247
+ }
1248
+ if (spec.remove !== undefined) {
1249
+ const subtrahend = spec.remove;
1250
+ if (isArray(subtrahend)) {
1251
+ return isArray(value) ? value.filter(item => !subtrahend.includes(item)).sort() : [];
1252
+ }
1253
+ if (typeof subtrahend === 'number')
1254
+ return Number(value) - subtrahend;
1255
+ if (typeof subtrahend === 'bigint') {
1256
+ try {
1257
+ return BigInt(value) - subtrahend;
1258
+ }
1259
+ catch {
1260
+ return BigInt(0) - subtrahend;
1261
+ }
1262
+ }
1263
+ throw new TypeError(`Invalid subtrahend ${subtrahend}`);
1264
+ }
1265
+ const prefixToReplace = spec.replacePrefix?.[0];
1266
+ if (prefixToReplace && typeof value === 'string' && value.startsWith(prefixToReplace)) {
1267
+ return spec.replacePrefix[1] + value.substring(prefixToReplace.length);
1268
+ }
1269
+ return value;
1270
+ }
1271
+ constructor(spec) {
1272
+ this["@@propmod"] = spec;
1273
+ }
1274
+ }
1275
+
1276
+ function applyUpdateSpec(obj, changes) {
1277
+ const keyPaths = keys(changes);
1278
+ const numKeys = keyPaths.length;
1279
+ let anythingModified = false;
1280
+ for (let i = 0; i < numKeys; ++i) {
1281
+ const keyPath = keyPaths[i];
1282
+ const value = changes[keyPath];
1283
+ const origValue = getByKeyPath(obj, keyPath);
1284
+ if (value instanceof PropModification) {
1285
+ setByKeyPath(obj, keyPath, value.execute(origValue));
1286
+ anythingModified = true;
1287
+ }
1288
+ else if (origValue !== value) {
1289
+ setByKeyPath(obj, keyPath, value);
1290
+ anythingModified = true;
1291
+ }
1292
+ }
1293
+ return anythingModified;
1294
+ }
1295
+
1228
1296
  class Table {
1229
1297
  _trans(mode, fn, writeLocked) {
1230
1298
  const trans = this._tx || PSD.trans;
@@ -1407,6 +1475,25 @@ class Table {
1407
1475
  return lastResult;
1408
1476
  });
1409
1477
  }
1478
+ upsert(key, modifications) {
1479
+ const { keyPath } = this.schema.primKey;
1480
+ return this._trans('readwrite', trans => {
1481
+ return this.core.get({ trans, key }).then(existing => {
1482
+ const obj = existing ?? {};
1483
+ applyUpdateSpec(obj, modifications);
1484
+ if (keyPath)
1485
+ setByKeyPath(obj, keyPath, key);
1486
+ return this.core.mutate({
1487
+ trans,
1488
+ type: 'put',
1489
+ values: [obj],
1490
+ keys: [key],
1491
+ upsert: true,
1492
+ updates: { keys: [key], changeSpecs: [modifications] }
1493
+ }).then(res => res.numFailures ? DexiePromise.reject(res.failures[0]) : !!existing);
1494
+ });
1495
+ });
1496
+ }
1410
1497
  update(keyOrObject, modifications) {
1411
1498
  if (typeof keyOrObject === 'object' && !isArray(keyOrObject)) {
1412
1499
  const key = getByKeyPath(keyOrObject, this.schema.primKey.keyPath);
@@ -1732,54 +1819,6 @@ function iterate(cursorPromise, filter, fn, valueMapper) {
1732
1819
  });
1733
1820
  }
1734
1821
 
1735
- class PropModification {
1736
- execute(value) {
1737
- const spec = this["@@propmod"];
1738
- if (spec.add !== undefined) {
1739
- const term = spec.add;
1740
- if (isArray(term)) {
1741
- return [...(isArray(value) ? value : []), ...term].sort();
1742
- }
1743
- if (typeof term === 'number')
1744
- return (Number(value) || 0) + term;
1745
- if (typeof term === 'bigint') {
1746
- try {
1747
- return BigInt(value) + term;
1748
- }
1749
- catch {
1750
- return BigInt(0) + term;
1751
- }
1752
- }
1753
- throw new TypeError(`Invalid term ${term}`);
1754
- }
1755
- if (spec.remove !== undefined) {
1756
- const subtrahend = spec.remove;
1757
- if (isArray(subtrahend)) {
1758
- return isArray(value) ? value.filter(item => !subtrahend.includes(item)).sort() : [];
1759
- }
1760
- if (typeof subtrahend === 'number')
1761
- return Number(value) - subtrahend;
1762
- if (typeof subtrahend === 'bigint') {
1763
- try {
1764
- return BigInt(value) - subtrahend;
1765
- }
1766
- catch {
1767
- return BigInt(0) - subtrahend;
1768
- }
1769
- }
1770
- throw new TypeError(`Invalid subtrahend ${subtrahend}`);
1771
- }
1772
- const prefixToReplace = spec.replacePrefix?.[0];
1773
- if (prefixToReplace && typeof value === 'string' && value.startsWith(prefixToReplace)) {
1774
- return spec.replacePrefix[1] + value.substring(prefixToReplace.length);
1775
- }
1776
- return value;
1777
- }
1778
- constructor(spec) {
1779
- this["@@propmod"] = spec;
1780
- }
1781
- }
1782
-
1783
1822
  class Collection {
1784
1823
  _read(fn, cb) {
1785
1824
  var ctx = this._ctx;
@@ -2035,25 +2074,7 @@ class Collection {
2035
2074
  modifyer = changes;
2036
2075
  }
2037
2076
  else {
2038
- var keyPaths = keys(changes);
2039
- var numKeys = keyPaths.length;
2040
- modifyer = function (item) {
2041
- let anythingModified = false;
2042
- for (let i = 0; i < numKeys; ++i) {
2043
- let keyPath = keyPaths[i];
2044
- let val = changes[keyPath];
2045
- let origVal = getByKeyPath(item, keyPath);
2046
- if (val instanceof PropModification) {
2047
- setByKeyPath(item, keyPath, val.execute(origVal));
2048
- anythingModified = true;
2049
- }
2050
- else if (origVal !== val) {
2051
- setByKeyPath(item, keyPath, val);
2052
- anythingModified = true;
2053
- }
2054
- }
2055
- return anythingModified;
2056
- };
2077
+ modifyer = item => applyUpdateSpec(item, changes);
2057
2078
  }
2058
2079
  const coreTable = ctx.table.core;
2059
2080
  const { outbound, extractKey } = coreTable.schema.primaryKey;
@@ -3986,8 +4007,8 @@ function dexieOpen(db) {
3986
4007
  state.vcFired = true;
3987
4008
  db.on("versionchange").fire(ev);
3988
4009
  });
3989
- idbdb.onclose = wrap(ev => {
3990
- db.on("close").fire(ev);
4010
+ idbdb.onclose = wrap(() => {
4011
+ db.close({ disableAutoOpen: false });
3991
4012
  });
3992
4013
  if (wasCreated)
3993
4014
  _onDatabaseCreated(db._deps, dbName);