dexie 4.0.8 → 4.0.9-alpha.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.
package/dist/dexie.js CHANGED
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * By David Fahlander, david.fahlander@gmail.com
6
6
  *
7
- * Version 4.0.8, Wed Jul 10 2024
7
+ * Version 4.0.9-alpha.1, Fri Aug 23 2024
8
8
  *
9
9
  * https://dexie.org
10
10
  *
@@ -1150,7 +1150,7 @@
1150
1150
  }
1151
1151
  }
1152
1152
 
1153
- var DEXIE_VERSION = '4.0.8';
1153
+ var DEXIE_VERSION = '4.0.9-alpha.1';
1154
1154
  var maxString = String.fromCharCode(65535);
1155
1155
  var minKey = -Infinity;
1156
1156
  var INVALID_KEY_ARGUMENT = "Invalid key provided. Keys must be of type string, number, Date or Array<string | number | Date>.";
@@ -1268,6 +1268,95 @@
1268
1268
  return new Uint8Array(a);
1269
1269
  }
1270
1270
 
1271
+ function getDocCache(db) {
1272
+ var _a;
1273
+ var _b;
1274
+ return (_a = (_b = db._novip)['_docCache']) !== null && _a !== void 0 ? _a : (_b['_docCache'] = {
1275
+ cache: {},
1276
+ get size() {
1277
+ return Object.keys(this.cache).length;
1278
+ },
1279
+ find: function (table, primaryKey, ydocProp) {
1280
+ var cacheKey = getYDocCacheKey(table, primaryKey, ydocProp);
1281
+ var docRef = this.cache[cacheKey];
1282
+ return docRef ? docRef.deref() : undefined;
1283
+ },
1284
+ add: function (doc) {
1285
+ var _a = doc.meta, parentTable = _a.parentTable, parentId = _a.parentId, parentProp = _a.parentProp;
1286
+ if (!parentTable || !parentProp || parentId == null)
1287
+ throw new Error("Missing Dexie-related metadata in Y.Doc");
1288
+ var cacheKey = getYDocCacheKey(parentTable, parentId, parentProp);
1289
+ this.cache[cacheKey] = new WeakRef(doc);
1290
+ docRegistry.register(doc, { cache: this.cache, key: cacheKey });
1291
+ },
1292
+ delete: function (doc) {
1293
+ docRegistry.unregister(doc);
1294
+ delete this.cache[getYDocCacheKey(doc.meta.parentTable, doc.meta.parentId, doc.meta.parentProp)];
1295
+ },
1296
+ });
1297
+ }
1298
+ var docRegistry = new FinalizationRegistry(function (_a) {
1299
+ var cache = _a.cache, key = _a.key;
1300
+ delete cache[key];
1301
+ });
1302
+ var destroyed = new WeakSet();
1303
+ function throwIfDestroyed(doc) {
1304
+ if (destroyed.has(doc))
1305
+ throw new Error('Y.Doc has been destroyed');
1306
+ }
1307
+ function getYDocCacheKey(table, primaryKey, ydocProp) {
1308
+ return "".concat(table, "[").concat(primaryKey, "].").concat(ydocProp);
1309
+ }
1310
+
1311
+ function createYDocProperty(db, Y, table, prop, updatesTable) {
1312
+ var pkKeyPath = table.schema.primKey.keyPath;
1313
+ var docCache = getDocCache(db);
1314
+ return {
1315
+ get: function () {
1316
+ var id = getByKeyPath(this, pkKeyPath);
1317
+ var doc = docCache.find(table.name, id, prop);
1318
+ if (doc)
1319
+ return doc;
1320
+ doc = new Y.Doc({
1321
+ meta: {
1322
+ db: db,
1323
+ updatesTable: updatesTable,
1324
+ parentProp: prop,
1325
+ parentTable: table.name,
1326
+ parentId: id
1327
+ },
1328
+ });
1329
+ docCache.add(doc);
1330
+ doc.on('destroy', function () {
1331
+ destroyed.add(doc);
1332
+ docCache.delete(doc);
1333
+ });
1334
+ return doc;
1335
+ },
1336
+ };
1337
+ }
1338
+
1339
+ function builtInDeletionTrigger(table, keys, res) {
1340
+ var yProps = table.schema.yProps;
1341
+ if (!yProps)
1342
+ return res;
1343
+ if (keys && res.numFailures > 0)
1344
+ keys = keys.filter(function (_, i) { return !res.failures[i]; });
1345
+ return Promise.all(yProps.map(function (_a) {
1346
+ var updatesTable = _a.updatesTable;
1347
+ return keys
1348
+ ? table.db.table(updatesTable).where('k').anyOf(keys).delete()
1349
+ : table.db.table(updatesTable).clear();
1350
+ })).then(function () { return res; });
1351
+ }
1352
+
1353
+ function getYLibrary(db) {
1354
+ var Y = db._options.Y;
1355
+ if (!Y)
1356
+ throw new exceptions.MissingAPI('Y library not supplied to Dexie constructor');
1357
+ return Y;
1358
+ }
1359
+
1271
1360
  var Table = (function () {
1272
1361
  function Table() {
1273
1362
  }
@@ -1399,6 +1488,7 @@
1399
1488
  return this.toCollection().reverse();
1400
1489
  };
1401
1490
  Table.prototype.mapToClass = function (constructor) {
1491
+ var _this = this;
1402
1492
  var _a = this, db = _a.db, tableName = _a.name;
1403
1493
  this.schema.mappedClass = constructor;
1404
1494
  if (constructor.prototype instanceof Entity) {
@@ -1416,6 +1506,20 @@
1416
1506
  return class_1;
1417
1507
  }(constructor));
1418
1508
  }
1509
+ if (this.schema.yProps) {
1510
+ var Y_1 = getYLibrary(db);
1511
+ constructor = (function (_super) {
1512
+ __extends(class_2, _super);
1513
+ function class_2() {
1514
+ return _super !== null && _super.apply(this, arguments) || this;
1515
+ }
1516
+ return class_2;
1517
+ }(constructor));
1518
+ this.schema.yProps.forEach(function (_a) {
1519
+ var prop = _a.prop, updatesTable = _a.updatesTable;
1520
+ Object.defineProperty(constructor.prototype, prop, createYDocProperty(db, Y_1, _this, prop, updatesTable));
1521
+ });
1522
+ }
1419
1523
  var inheritedProps = new Set();
1420
1524
  for (var proto = constructor.prototype; proto; proto = getProto(proto)) {
1421
1525
  Object.getOwnPropertyNames(proto).forEach(function (propName) { return inheritedProps.add(propName); });
@@ -1497,12 +1601,14 @@
1497
1601
  };
1498
1602
  Table.prototype.delete = function (key) {
1499
1603
  var _this = this;
1500
- return this._trans('readwrite', function (trans) { return _this.core.mutate({ trans: trans, type: 'delete', keys: [key] }); })
1501
- .then(function (res) { return res.numFailures ? DexiePromise.reject(res.failures[0]) : undefined; });
1604
+ return this._trans('readwrite', function (trans) { return _this.core.mutate({ trans: trans, type: 'delete', keys: [key] })
1605
+ .then(function (res) { return builtInDeletionTrigger(_this, [key], res); })
1606
+ .then(function (res) { return res.numFailures ? DexiePromise.reject(res.failures[0]) : undefined; }); });
1502
1607
  };
1503
1608
  Table.prototype.clear = function () {
1504
1609
  var _this = this;
1505
- return this._trans('readwrite', function (trans) { return _this.core.mutate({ trans: trans, type: 'deleteRange', range: AnyRange }); })
1610
+ return this._trans('readwrite', function (trans) { return _this.core.mutate({ trans: trans, type: 'deleteRange', range: AnyRange })
1611
+ .then(function (res) { return builtInDeletionTrigger(_this, null, res); }); })
1506
1612
  .then(function (res) { return res.numFailures ? DexiePromise.reject(res.failures[0]) : undefined; });
1507
1613
  };
1508
1614
  Table.prototype.bulkGet = function (keys) {
@@ -1629,7 +1735,8 @@
1629
1735
  var _this = this;
1630
1736
  var numKeys = keys.length;
1631
1737
  return this._trans('readwrite', function (trans) {
1632
- return _this.core.mutate({ trans: trans, type: 'delete', keys: keys });
1738
+ return _this.core.mutate({ trans: trans, type: 'delete', keys: keys })
1739
+ .then(function (res) { return builtInDeletionTrigger(_this, keys, res); });
1633
1740
  }).then(function (_a) {
1634
1741
  var numFailures = _a.numFailures, lastResult = _a.lastResult, failures = _a.failures;
1635
1742
  if (numFailures === 0)
@@ -2153,45 +2260,48 @@
2153
2260
  totalFailures.push(failures[pos]);
2154
2261
  }
2155
2262
  };
2263
+ var isUnconditionalDelete = changes === deleteCallback;
2156
2264
  return _this.clone().primaryKeys().then(function (keys) {
2157
2265
  var criteria = isPlainKeyRange(ctx) &&
2158
2266
  ctx.limit === Infinity &&
2159
- (typeof changes !== 'function' || changes === deleteCallback) && {
2267
+ (typeof changes !== 'function' || isUnconditionalDelete) && {
2160
2268
  index: ctx.index,
2161
2269
  range: ctx.range
2162
2270
  };
2163
2271
  var nextChunk = function (offset) {
2164
2272
  var count = Math.min(limit, keys.length - offset);
2165
- return coreTable.getMany({
2273
+ var keysInChunk = keys.slice(offset, offset + count);
2274
+ return (isUnconditionalDelete ? Promise.resolve([]) : coreTable.getMany({
2166
2275
  trans: trans,
2167
- keys: keys.slice(offset, offset + count),
2276
+ keys: keysInChunk,
2168
2277
  cache: "immutable"
2169
- }).then(function (values) {
2278
+ })).then(function (values) {
2170
2279
  var addValues = [];
2171
2280
  var putValues = [];
2172
2281
  var putKeys = outbound ? [] : null;
2173
- var deleteKeys = [];
2174
- for (var i = 0; i < count; ++i) {
2175
- var origValue = values[i];
2176
- var ctx_1 = {
2177
- value: deepClone(origValue),
2178
- primKey: keys[offset + i]
2179
- };
2180
- if (modifyer.call(ctx_1, ctx_1.value, ctx_1) !== false) {
2181
- if (ctx_1.value == null) {
2182
- deleteKeys.push(keys[offset + i]);
2183
- }
2184
- else if (!outbound && cmp(extractKey(origValue), extractKey(ctx_1.value)) !== 0) {
2185
- deleteKeys.push(keys[offset + i]);
2186
- addValues.push(ctx_1.value);
2187
- }
2188
- else {
2189
- putValues.push(ctx_1.value);
2190
- if (outbound)
2191
- putKeys.push(keys[offset + i]);
2282
+ var deleteKeys = isUnconditionalDelete ? keysInChunk : [];
2283
+ if (!isUnconditionalDelete)
2284
+ for (var i = 0; i < count; ++i) {
2285
+ var origValue = values[i];
2286
+ var ctx_1 = {
2287
+ value: deepClone(origValue),
2288
+ primKey: keys[offset + i]
2289
+ };
2290
+ if (modifyer.call(ctx_1, ctx_1.value, ctx_1) !== false) {
2291
+ if (ctx_1.value == null) {
2292
+ deleteKeys.push(keys[offset + i]);
2293
+ }
2294
+ else if (!outbound && cmp(extractKey(origValue), extractKey(ctx_1.value)) !== 0) {
2295
+ deleteKeys.push(keys[offset + i]);
2296
+ addValues.push(ctx_1.value);
2297
+ }
2298
+ else {
2299
+ putValues.push(ctx_1.value);
2300
+ if (outbound)
2301
+ putKeys.push(keys[offset + i]);
2302
+ }
2192
2303
  }
2193
2304
  }
2194
- }
2195
2305
  return Promise.resolve(addValues.length > 0 &&
2196
2306
  coreTable.mutate({ trans: trans, type: 'add', values: addValues })
2197
2307
  .then(function (res) {
@@ -2209,14 +2319,15 @@
2209
2319
  changeSpec: typeof changes !== 'function'
2210
2320
  && changes,
2211
2321
  isAdditionalChunk: offset > 0
2212
- }).then(function (res) { return applyMutateResult(putValues.length, res); }); }).then(function () { return (deleteKeys.length > 0 || (criteria && changes === deleteCallback)) &&
2322
+ }).then(function (res) { return applyMutateResult(putValues.length, res); }); }).then(function () { return (deleteKeys.length > 0 || (criteria && isUnconditionalDelete)) &&
2213
2323
  coreTable.mutate({
2214
2324
  trans: trans,
2215
2325
  type: 'delete',
2216
2326
  keys: deleteKeys,
2217
2327
  criteria: criteria,
2218
2328
  isAdditionalChunk: offset > 0
2219
- }).then(function (res) { return applyMutateResult(deleteKeys.length, res); }); }).then(function () {
2329
+ }).then(function (res) { return builtInDeletionTrigger(ctx.table, deleteKeys, res); })
2330
+ .then(function (res) { return applyMutateResult(deleteKeys.length, res); }); }).then(function () {
2220
2331
  return keys.length > offset + count && nextChunk(offset + limit);
2221
2332
  });
2222
2333
  });
@@ -2232,6 +2343,7 @@
2232
2343
  Collection.prototype.delete = function () {
2233
2344
  var ctx = this._ctx, range = ctx.range;
2234
2345
  if (isPlainKeyRange(ctx) &&
2346
+ !ctx.table.schema.yProps &&
2235
2347
  (ctx.isPrimKey || range.type === 3 ))
2236
2348
  {
2237
2349
  return this._write(function (trans) {
@@ -2240,7 +2352,7 @@
2240
2352
  return ctx.table.core.count({ trans: trans, query: { index: primaryKey, range: coreRange } }).then(function (count) {
2241
2353
  return ctx.table.core.mutate({ trans: trans, type: 'deleteRange', range: coreRange })
2242
2354
  .then(function (_a) {
2243
- var failures = _a.failures; _a.lastResult; _a.results; var numFailures = _a.numFailures;
2355
+ var failures = _a.failures, numFailures = _a.numFailures;
2244
2356
  if (numFailures)
2245
2357
  throw new ModifyError("Could not delete some values", Object.keys(failures).map(function (pos) { return failures[pos]; }), count - numFailures);
2246
2358
  return count - numFailures;
@@ -2842,6 +2954,13 @@
2842
2954
  function createTransactionConstructor(db) {
2843
2955
  return makeClassConstructor(Transaction.prototype, function Transaction(mode, storeNames, dbschema, chromeTransactionDurability, parent) {
2844
2956
  var _this = this;
2957
+ if (mode !== 'readonly')
2958
+ storeNames.forEach(function (storeName) {
2959
+ var _a;
2960
+ var yProps = (_a = dbschema[storeName]) === null || _a === void 0 ? void 0 : _a.yProps;
2961
+ if (yProps)
2962
+ storeNames = storeNames.concat(yProps.map(function (p) { return p.updatesTable; }));
2963
+ });
2845
2964
  this.db = db;
2846
2965
  this.mode = mode;
2847
2966
  this.storeNames = storeNames;
@@ -2877,7 +2996,7 @@
2877
2996
  });
2878
2997
  }
2879
2998
 
2880
- function createIndexSpec(name, keyPath, unique, multi, auto, compound, isPrimKey) {
2999
+ function createIndexSpec(name, keyPath, unique, multi, auto, compound, isPrimKey, type) {
2881
3000
  return {
2882
3001
  name: name,
2883
3002
  keyPath: keyPath,
@@ -2885,7 +3004,8 @@
2885
3004
  multi: multi,
2886
3005
  auto: auto,
2887
3006
  compound: compound,
2888
- src: (unique && !isPrimKey ? '&' : '') + (multi ? '*' : '') + (auto ? "++" : "") + nameFromKeyPath(keyPath)
3007
+ src: (unique && !isPrimKey ? '&' : '') + (multi ? '*' : '') + (auto ? "++" : "") + nameFromKeyPath(keyPath),
3008
+ type: type
2889
3009
  };
2890
3010
  }
2891
3011
  function nameFromKeyPath(keyPath) {
@@ -2894,13 +3014,17 @@
2894
3014
  keyPath ? ('[' + [].join.call(keyPath, '+') + ']') : "";
2895
3015
  }
2896
3016
 
2897
- function createTableSchema(name, primKey, indexes) {
3017
+ function createTableSchema(name, primKey, indexes, yProps) {
2898
3018
  return {
2899
3019
  name: name,
2900
3020
  primKey: primKey,
2901
3021
  indexes: indexes,
2902
3022
  mappedClass: null,
2903
- idxByName: arrayToObject(indexes, function (index) { return [index.name, index]; })
3023
+ yProps: yProps === null || yProps === void 0 ? void 0 : yProps.map(function (prop) { return ({
3024
+ prop: prop,
3025
+ updatesTable: "$".concat(name, ".").concat(prop, "_updates"),
3026
+ }); }),
3027
+ idxByName: arrayToObject(indexes, function (index) { return [index.name, index]; }),
2904
3028
  };
2905
3029
  }
2906
3030
 
@@ -3644,10 +3768,15 @@
3644
3768
  }
3645
3769
  function parseIndexSyntax(primKeyAndIndexes) {
3646
3770
  return primKeyAndIndexes.split(',').map(function (index, indexNum) {
3647
- index = index.trim();
3771
+ var _a;
3772
+ var typeSplit = index.split(':');
3773
+ var type = (_a = typeSplit[1]) === null || _a === void 0 ? void 0 : _a.trim();
3774
+ index = typeSplit[0].trim();
3775
+ if (type && type !== 'Y')
3776
+ throw new exceptions.Schema("Unsupported type '".concat(type, "'"));
3648
3777
  var name = index.replace(/([&*]|\+\+)/g, "");
3649
3778
  var keyPath = /^\[/.test(name) ? name.match(/^\[(.*)\]$/)[1].split('+') : name;
3650
- return createIndexSpec(name, keyPath || null, /\&/.test(index), /\*/.test(index), /\+\+/.test(index), isArray(keyPath), indexNum === 0);
3779
+ return createIndexSpec(name, keyPath || null, /\&/.test(index), /\*/.test(index), /\+\+/.test(index), isArray(keyPath), indexNum === 0, type);
3651
3780
  });
3652
3781
  }
3653
3782
 
@@ -3655,40 +3784,57 @@
3655
3784
  function Version() {
3656
3785
  }
3657
3786
  Version.prototype._parseStoresSpec = function (stores, outSchema) {
3787
+ var _this = this;
3658
3788
  keys(stores).forEach(function (tableName) {
3789
+ var _a;
3659
3790
  if (stores[tableName] !== null) {
3660
3791
  var indexes = parseIndexSyntax(stores[tableName]);
3792
+ var yProps = indexes.filter(function (idx) { return idx.type === 'Y'; }).map(function (idx) { return idx.name; });
3793
+ indexes = indexes.filter(function (idx) { return idx.type !== 'Y'; });
3661
3794
  var primKey = indexes.shift();
3795
+ if (!primKey) {
3796
+ throw new exceptions.Schema('Invalid schema for table ' + tableName + ': ' + stores[tableName]);
3797
+ }
3662
3798
  primKey.unique = true;
3663
3799
  if (primKey.multi)
3664
- throw new exceptions.Schema("Primary key cannot be multi-valued");
3800
+ throw new exceptions.Schema('Primary key cannot be multiEntry*');
3665
3801
  indexes.forEach(function (idx) {
3666
3802
  if (idx.auto)
3667
- throw new exceptions.Schema("Only primary key can be marked as autoIncrement (++)");
3803
+ throw new exceptions.Schema('Only primary key can be marked as autoIncrement (++)');
3668
3804
  if (!idx.keyPath)
3669
- throw new exceptions.Schema("Index must have a name and cannot be an empty string");
3805
+ throw new exceptions.Schema('Index must have a name and cannot be an empty string');
3670
3806
  });
3671
- outSchema[tableName] = createTableSchema(tableName, primKey, indexes);
3807
+ var tblSchema = createTableSchema(tableName, primKey, indexes, yProps.length ? yProps : undefined);
3808
+ outSchema[tableName] = tblSchema;
3809
+ for (var _i = 0, _b = tblSchema.yProps || []; _i < _b.length; _i++) {
3810
+ var yProp = _b[_i];
3811
+ _this._parseStoresSpec((_a = {}, _a[yProp.updatesTable] = '++i,k', _a), outSchema);
3812
+ }
3672
3813
  }
3673
3814
  });
3674
3815
  };
3675
3816
  Version.prototype.stores = function (stores) {
3676
3817
  var db = this.db;
3677
- this._cfg.storesSource = this._cfg.storesSource ?
3678
- extend(this._cfg.storesSource, stores) :
3679
- stores;
3818
+ this._cfg.storesSource = this._cfg.storesSource
3819
+ ? extend(this._cfg.storesSource, stores)
3820
+ : stores;
3680
3821
  var versions = db._versions;
3681
3822
  var storesSpec = {};
3682
3823
  var dbschema = {};
3683
3824
  versions.forEach(function (version) {
3684
3825
  extend(storesSpec, version._cfg.storesSource);
3685
- dbschema = (version._cfg.dbschema = {});
3826
+ dbschema = version._cfg.dbschema = {};
3686
3827
  version._parseStoresSpec(storesSpec, dbschema);
3687
3828
  });
3688
3829
  db._dbSchema = dbschema;
3689
3830
  removeTablesApi(db, [db._allTables, db, db.Transaction.prototype]);
3690
3831
  setApiOnPlace(db, [db._allTables, db, db.Transaction.prototype, this._cfg.tables], keys(dbschema), dbschema);
3691
3832
  db._storeNames = keys(dbschema);
3833
+ db._storeNames.forEach(function (tableName) {
3834
+ if (dbschema[tableName].yProps) {
3835
+ db.table(tableName).mapToClass(dbschema[tableName].mappedClass || Object);
3836
+ }
3837
+ });
3692
3838
  return this;
3693
3839
  };
3694
3840
  Version.prototype.upgrade = function (upgradeFunction) {
@@ -5235,6 +5381,140 @@
5235
5381
  });
5236
5382
  }
5237
5383
 
5384
+ function compressYDocs(db, interval) {
5385
+ var p = Promise.resolve();
5386
+ for (var _i = 0, _a = db.tables; _i < _a.length; _i++) {
5387
+ var table = _a[_i];
5388
+ var _loop_1 = function (yProp) {
5389
+ p = p.then(function () { return compressYDocsTable(db, yProp, interval); });
5390
+ };
5391
+ for (var _b = 0, _c = table.schema.yProps || []; _b < _c.length; _b++) {
5392
+ var yProp = _c[_b];
5393
+ _loop_1(yProp);
5394
+ }
5395
+ }
5396
+ return p;
5397
+ }
5398
+ function compressYDocsTable(db, _a, skipIfRunnedSince
5399
+ ) {
5400
+ var updatesTable = _a.updatesTable;
5401
+ var updTbl = db.table(updatesTable);
5402
+ return Promise.all([
5403
+ updTbl
5404
+ .where('i')
5405
+ .startsWith('')
5406
+ .toArray(),
5407
+ db.transaction('rw', updatesTable, function () {
5408
+ return updTbl.get(0).then(function (lastCompressed) {
5409
+ if (lastCompressed &&
5410
+ skipIfRunnedSince &&
5411
+ lastCompressed.lastRun.getTime() > Date.now() - skipIfRunnedSince) {
5412
+ return null;
5413
+ }
5414
+ lastCompressed = lastCompressed || { i: 0, lastCompressed: 0 };
5415
+ return updTbl
5416
+ .put(__assign(__assign({}, lastCompressed), { lastRun: new Date() }))
5417
+ .then(function () { return lastCompressed; });
5418
+ });
5419
+ }),
5420
+ ]).then(function (_a) {
5421
+ var syncers = _a[0], stamp = _a[1];
5422
+ if (!stamp)
5423
+ return;
5424
+ var lastCompressedUpdate = stamp.lastCompressed;
5425
+ var unsentFrom = Math.min.apply(Math, syncers.map(function (s) { return s.unsentFrom || Infinity; }));
5426
+ return updTbl
5427
+ .where('i')
5428
+ .between(lastCompressedUpdate, Infinity, false)
5429
+ .toArray(function (addedUpdates) {
5430
+ if (addedUpdates.length <= 1)
5431
+ return;
5432
+ var docsToCompress = [];
5433
+ var lastUpdateToCompress = lastCompressedUpdate + 1;
5434
+ var _loop_2 = function (j) {
5435
+ var updateRow = addedUpdates[j];
5436
+ var i = updateRow.i, f = updateRow.f, k = updateRow.k;
5437
+ if (i >= unsentFrom && (f & 0x01))
5438
+ return "break";
5439
+ var entry = docsToCompress.find(function (entry) { return cmp(entry.docId, k) === 0; });
5440
+ if (entry)
5441
+ entry.updates.push(updateRow);
5442
+ else
5443
+ docsToCompress.push({ docId: k, updates: [updateRow] });
5444
+ lastUpdateToCompress = i;
5445
+ };
5446
+ for (var j = 0; j < addedUpdates.length; ++j) {
5447
+ var state_1 = _loop_2(j);
5448
+ if (state_1 === "break")
5449
+ break;
5450
+ }
5451
+ var p = Promise.resolve();
5452
+ var _loop_3 = function (docId, updates) {
5453
+ p = p.then(function () { return compressUpdatesForDoc(db, updatesTable, docId, updates); });
5454
+ };
5455
+ for (var _i = 0, docsToCompress_1 = docsToCompress; _i < docsToCompress_1.length; _i++) {
5456
+ var _a = docsToCompress_1[_i], docId = _a.docId, updates = _a.updates;
5457
+ _loop_3(docId, updates);
5458
+ }
5459
+ return p.then(function () {
5460
+ return db.transaction('rw', updTbl, function () {
5461
+ return updTbl.get(0).then(function (current) {
5462
+ return updTbl.put(__assign(__assign({}, current), { lastCompressed: Math.max(lastUpdateToCompress, (current === null || current === void 0 ? void 0 : current.lastCompressed) || 0) }));
5463
+ });
5464
+ });
5465
+ });
5466
+ });
5467
+ });
5468
+ }
5469
+ function compressUpdatesForDoc(db, updatesTable, parentId, addedUpdatesToCompress) {
5470
+ if (addedUpdatesToCompress.length < 1)
5471
+ throw new Error('Invalid input');
5472
+ return db.transaction('rw', updatesTable, function (tx) {
5473
+ var updTbl = tx.table(updatesTable);
5474
+ return updTbl.where({ k: parentId }).first(function (mainUpdate) {
5475
+ var updates = [mainUpdate].concat(addedUpdatesToCompress);
5476
+ var Y = getYLibrary(db);
5477
+ var doc = new Y.Doc({ gc: true });
5478
+ updates.forEach(function (update) {
5479
+ Y.applyUpdateV2(doc, update.u);
5480
+ });
5481
+ var compressedUpdate = Y.encodeStateAsUpdateV2(doc);
5482
+ var lastUpdate = updates.pop();
5483
+ return updTbl
5484
+ .put({
5485
+ i: lastUpdate.i,
5486
+ k: parentId,
5487
+ u: compressedUpdate,
5488
+ })
5489
+ .then(function () { return updTbl.bulkDelete(updates.map(function (update) { return update.i; })); });
5490
+ });
5491
+ });
5492
+ }
5493
+
5494
+ var INTERVAL = 10000;
5495
+ function periodicGC(db) {
5496
+ var timer = null;
5497
+ db.on('ready', function (db) {
5498
+ if (db.tables.some(function (tbl) { return tbl.schema.yProps; })) {
5499
+ var gc_1 = function () {
5500
+ if (!db.isOpen())
5501
+ return;
5502
+ compressYDocs(db, INTERVAL).catch(function (err) {
5503
+ console.debug('Error during periodic GC', err);
5504
+ }).then(function () {
5505
+ timer = setTimeout(gc_1, INTERVAL);
5506
+ });
5507
+ };
5508
+ timer = setTimeout(gc_1, INTERVAL);
5509
+ }
5510
+ }, true);
5511
+ db.on('close', function () {
5512
+ if (timer)
5513
+ clearTimeout(timer);
5514
+ timer = null;
5515
+ });
5516
+ }
5517
+
5238
5518
  var Dexie$1 = (function () {
5239
5519
  function Dexie(name, options) {
5240
5520
  var _this = this;
@@ -5276,7 +5556,18 @@
5276
5556
  });
5277
5557
  this._state = state;
5278
5558
  this.name = name;
5279
- this.on = Events(this, "populate", "blocked", "versionchange", "close", { ready: [promisableChain, nop] });
5559
+ this.on = Events(this, "populate", "blocked", "versionchange", "close", "y", { ready: [promisableChain, nop] });
5560
+ this.once = function (event, callback) {
5561
+ var fn = function () {
5562
+ var args = [];
5563
+ for (var _i = 0; _i < arguments.length; _i++) {
5564
+ args[_i] = arguments[_i];
5565
+ }
5566
+ _this.on(event).unsubscribe(fn);
5567
+ callback.apply(_this, args);
5568
+ };
5569
+ return _this.on(event, fn);
5570
+ };
5280
5571
  this.on.ready.subscribe = override(this.on.ready.subscribe, function (subscribe) {
5281
5572
  return function (subscriber, bSticky) {
5282
5573
  Dexie.vip(function () {
@@ -5355,6 +5646,8 @@
5355
5646
  }
5356
5647
  });
5357
5648
  this.vip = vipDB;
5649
+ if (options === null || options === void 0 ? void 0 : options.Y)
5650
+ periodicGC(this);
5358
5651
  addons.forEach(function (addon) { return addon(_this); });
5359
5652
  }
5360
5653
  Dexie.prototype.version = function (versionNumber) {
@@ -5417,6 +5710,7 @@
5417
5710
  function () { return dexieOpen(_this); });
5418
5711
  };
5419
5712
  Dexie.prototype._close = function () {
5713
+ this.on.close.fire(new CustomEvent('close'));
5420
5714
  var state = this._state;
5421
5715
  var idx = connections.indexOf(this);
5422
5716
  if (idx >= 0)
@@ -5574,6 +5868,9 @@
5574
5868
  }
5575
5869
  return this._allTables[tableName];
5576
5870
  };
5871
+ Dexie.prototype.gc = function () {
5872
+ return compressYDocs(this);
5873
+ };
5577
5874
  return Dexie;
5578
5875
  }());
5579
5876
 
@@ -5874,6 +6171,116 @@
5874
6171
  return new PropModification({ replacePrefix: [a, b] });
5875
6172
  }
5876
6173
 
6174
+ function observeYDocUpdates(provider, doc, db, parentTableName, updatesTableName, parentId, Y) {
6175
+ var lastUpdateId = 0;
6176
+ var initial = true;
6177
+ var subscription = liveQuery(function () {
6178
+ throwIfDestroyed(doc);
6179
+ var updatesTable = db.table(updatesTableName);
6180
+ return Promise.all([
6181
+ (lastUpdateId > 0
6182
+ ? updatesTable
6183
+ .where('i')
6184
+ .between(lastUpdateId, Infinity, false)
6185
+ .toArray()
6186
+ .then(function (updates) {
6187
+ return updates.filter(function (update) { return cmp(update.k, parentId) === 0; });
6188
+ })
6189
+ : updatesTable.where({ k: parentId }).toArray()).then(function (updates) {
6190
+ if (updates.length > 0)
6191
+ lastUpdateId = updates[updates.length - 1].i;
6192
+ return updates;
6193
+ }),
6194
+ db.table(parentTableName).where(':id').equals(parentId).toArray(),
6195
+ ]);
6196
+ }).subscribe(function (_a) {
6197
+ var updates = _a[0], parentRow = _a[1];
6198
+ if (parentRow.length === 0) {
6199
+ doc.destroy();
6200
+ return;
6201
+ }
6202
+ throwIfDestroyed(doc);
6203
+ if (updates.length > 0) {
6204
+ Y.transact(doc, function () {
6205
+ updates.forEach(function (update) {
6206
+ Y.applyUpdateV2(doc, update.u);
6207
+ });
6208
+ }, provider, false);
6209
+ }
6210
+ if (initial) {
6211
+ initial = false;
6212
+ provider.on('load').fire(provider);
6213
+ doc.emit('load', [doc]);
6214
+ }
6215
+ }, function (error) {
6216
+ provider.on('error').fire(error);
6217
+ });
6218
+ var onUpdate = function (update, origin) {
6219
+ if (origin === provider)
6220
+ return;
6221
+ db.table(updatesTableName)
6222
+ .add({
6223
+ k: parentId,
6224
+ u: update,
6225
+ f: 1,
6226
+ })
6227
+ .then(function (i) {
6228
+ if (i === lastUpdateId - 1)
6229
+ ++lastUpdateId;
6230
+ })
6231
+ .catch(function (error) {
6232
+ provider.on('error').fire(error);
6233
+ });
6234
+ };
6235
+ var stopObserving = function () {
6236
+ subscription.unsubscribe();
6237
+ doc.off('updateV2', onUpdate);
6238
+ doc.off('destroy', stopObserving);
6239
+ };
6240
+ doc.on('updateV2', onUpdate);
6241
+ doc.on('destroy', stopObserving);
6242
+ return stopObserving;
6243
+ }
6244
+
6245
+ function DexieYProvider(doc) {
6246
+ var _a = (doc || {}).meta, db = _a.db, parentTable = _a.parentTable, parentId = _a.parentId, updatesTable = _a.updatesTable;
6247
+ if (!db || !parentTable || !updatesTable)
6248
+ throw new Error('Y.Doc not generated by Dexie');
6249
+ if (!db.table(parentTable) || !db.table(updatesTable)) {
6250
+ throw new Error("Table ".concat(parentTable, " or ").concat(updatesTable, " not found in db"));
6251
+ }
6252
+ throwIfDestroyed(doc);
6253
+ var Y = getYLibrary(db);
6254
+ function createEvents() {
6255
+ return Events(null, "load", "sync", "error");
6256
+ }
6257
+ var on = createEvents();
6258
+ var provider = {
6259
+ destroyed: false,
6260
+ doc: doc,
6261
+ on: on,
6262
+ off: function (name, f) { var _a; (_a = on[name]) === null || _a === void 0 ? void 0 : _a.unsubscribe(f); },
6263
+ whenLoaded: new Promise(function (resolve, reject) {
6264
+ on('load', resolve);
6265
+ on('error', reject);
6266
+ }),
6267
+ whenSynced: new Promise(function (resolve, reject) {
6268
+ on('sync', resolve);
6269
+ on('error', reject);
6270
+ }),
6271
+ destroy: function () {
6272
+ this.destroyed = true;
6273
+ stopObserving();
6274
+ on = this.on = createEvents();
6275
+ }
6276
+ };
6277
+ var stopObserving = observeYDocUpdates(provider, doc, db, parentTable, updatesTable, parentId, Y);
6278
+ doc.on('destroy', provider.destroy.bind(provider));
6279
+ db.on.y.fire(provider, Y);
6280
+ return provider;
6281
+ }
6282
+ DexieYProvider.getDocCache = getDocCache;
6283
+
5877
6284
  DexiePromise.rejectionMapper = mapError;
5878
6285
  setDebug(debug);
5879
6286
 
@@ -5891,7 +6298,8 @@
5891
6298
  'default': Dexie$1,
5892
6299
  RangeSet: RangeSet,
5893
6300
  mergeRanges: mergeRanges,
5894
- rangesOverlap: rangesOverlap
6301
+ rangesOverlap: rangesOverlap,
6302
+ DexieYProvider: DexieYProvider
5895
6303
  });
5896
6304
 
5897
6305
  __assign(Dexie$1, namedExports, { default: Dexie$1 });