dexie-cloud-addon 4.1.0-beta.38 → 4.1.0-beta.40

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.
@@ -1,4 +1,3 @@
1
1
  import dexieCloudAddon from './dexie-cloud-client';
2
2
  export * from './dexie-cloud-client';
3
- export { defineYDocTrigger } from './define-ydoc-trigger';
4
3
  export default dexieCloudAddon;
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * ==========================================================================
10
10
  *
11
- * Version 4.1.0-beta.38, Fri Dec 06 2024
11
+ * Version 4.1.0-beta.40, Mon Jan 20 2025
12
12
  *
13
13
  * https://dexie.org
14
14
  *
@@ -4225,7 +4225,7 @@
4225
4225
  },
4226
4226
  };
4227
4227
 
4228
- const bigIntDef = {
4228
+ const bigIntDef$1 = {
4229
4229
  bigint: {
4230
4230
  replace: (realVal) => {
4231
4231
  return { $t: "bigint", v: "" + realVal };
@@ -4468,7 +4468,7 @@
4468
4468
 
4469
4469
  const builtin = {
4470
4470
  ...numberDef,
4471
- ...bigIntDef,
4471
+ ...bigIntDef$1,
4472
4472
  ...DateDef,
4473
4473
  ...SetDef,
4474
4474
  ...MapDef,
@@ -4578,7 +4578,7 @@
4578
4578
  this.v = value;
4579
4579
  }
4580
4580
  }
4581
- const defs = Object.assign(Object.assign(Object.assign({}, undefinedDef), (hasBigIntSupport
4581
+ const bigIntDef = hasBigIntSupport
4582
4582
  ? {}
4583
4583
  : {
4584
4584
  bigint: {
@@ -4586,17 +4586,19 @@
4586
4586
  replace: (fakeBigInt) => {
4587
4587
  return Object.assign({ $t: 'bigint' }, fakeBigInt);
4588
4588
  },
4589
- revive: ({ v, }) => new FakeBigInt(v)
4590
- }
4591
- })), { PropModification: {
4589
+ revive: ({ v }) => new FakeBigInt(v),
4590
+ },
4591
+ };
4592
+ const defs = Object.assign(Object.assign(Object.assign({}, undefinedDef), bigIntDef), { PropModification: {
4592
4593
  test: (val) => val instanceof Dexie.PropModification,
4593
4594
  replace: (propModification) => {
4594
- return Object.assign({ $t: 'PropModification' }, propModification);
4595
+ return Object.assign({ $t: 'PropModification' }, propModification['@@propmod']);
4595
4596
  },
4596
4597
  revive: (_a) => {
4597
- var propModification = __rest(_a, ["$t"]);
4598
- return new Dexie.PropModification(propModification);
4599
- }
4598
+ var propModSpec = __rest(_a, ["$t"]) // keep the rest
4599
+ ;
4600
+ return new Dexie.PropModification(propModSpec);
4601
+ },
4600
4602
  } });
4601
4603
  const TSON = TypesonSimplified(builtin, defs);
4602
4604
  const BISON = Bison(defs);
@@ -4744,11 +4746,12 @@
4744
4746
  db.syncStateChangedEvent.next({
4745
4747
  phase: 'pushing',
4746
4748
  });
4749
+ const body = TSON.stringify(syncRequest);
4747
4750
  const res = yield fetch(`${databaseUrl}/sync`, {
4748
4751
  method: 'post',
4749
4752
  headers,
4750
4753
  credentials: 'include', // For Arr Affinity cookie only, for better Rate-Limit counting only.
4751
- body: TSON.stringify(syncRequest),
4754
+ body,
4752
4755
  });
4753
4756
  //const contentLength = Number(res.headers.get('content-length'));
4754
4757
  db.syncStateChangedEvent.next({
@@ -5583,7 +5586,12 @@
5583
5586
  const usingYProps = Object.values(schema).some(tbl => { var _a; return (_a = tbl.yProps) === null || _a === void 0 ? void 0 : _a.length; });
5584
5587
  const serverSupportsYprops = !!res.yMessages;
5585
5588
  if (usingYProps && serverSupportsYprops) {
5586
- yield downloadYDocsFromServer(db, databaseUrl, newSyncState);
5589
+ try {
5590
+ yield downloadYDocsFromServer(db, databaseUrl, newSyncState);
5591
+ }
5592
+ catch (error) {
5593
+ console.error('Failed to download Yjs documents from server', error);
5594
+ }
5587
5595
  }
5588
5596
  console.debug('SYNC DONE', { isInitialSync });
5589
5597
  db.syncCompleteEvent.next();
@@ -8120,6 +8128,162 @@
8120
8128
  return realmId.startsWith('rlm~') ? realmId.substr(4) : null;
8121
8129
  }
8122
8130
 
8131
+ const ydocTriggers = {};
8132
+ const docIsAlreadyHooked = new WeakSet();
8133
+ const middlewares = new WeakMap();
8134
+ const createMiddleware = (db) => ({
8135
+ stack: 'dbcore',
8136
+ level: 10,
8137
+ name: 'yTriggerMiddleware',
8138
+ create: (down) => {
8139
+ return Object.assign(Object.assign({}, down), { transaction: (stores, mode, options) => {
8140
+ const idbtrans = down.transaction(stores, mode, options);
8141
+ idbtrans.addEventListener('complete', onTransactionCommitted);
8142
+ return idbtrans;
8143
+ }, table: (tblName) => {
8144
+ const coreTable = down.table(tblName);
8145
+ const triggerSpec = ydocTriggers[tblName];
8146
+ if (!triggerSpec)
8147
+ return coreTable;
8148
+ const { trigger, parentTable, prop } = triggerSpec;
8149
+ return Object.assign(Object.assign({}, coreTable), { mutate(req) {
8150
+ switch (req.type) {
8151
+ case 'add': {
8152
+ for (const yUpdateRow of req.values) {
8153
+ if (yUpdateRow.k == undefined)
8154
+ continue; // A syncer or garbage collection state does not point to a key
8155
+ const primaryKey = yUpdateRow.k;
8156
+ const doc = Dexie.DexieYProvider.getDocCache(db).find(parentTable, primaryKey, prop);
8157
+ if (doc) {
8158
+ if (!docIsAlreadyHooked.has(doc)) {
8159
+ hookToDoc(doc, primaryKey, trigger);
8160
+ docIsAlreadyHooked.add(doc);
8161
+ }
8162
+ }
8163
+ else {
8164
+ enqueueTrigger(db, tblName, primaryKey, trigger);
8165
+ }
8166
+ }
8167
+ break;
8168
+ }
8169
+ case 'delete':
8170
+ // @ts-ignore
8171
+ if (req.trans._rejecting_y_ypdate) {
8172
+ // The deletion came from a rejection, not garbage collection.
8173
+ // When that happens, let the triggers run to compute new values
8174
+ // based on the deleted updates.
8175
+ coreTable
8176
+ .getMany({
8177
+ keys: req.keys,
8178
+ trans: req.trans,
8179
+ cache: 'immutable',
8180
+ })
8181
+ .then((updates) => {
8182
+ const keySet = new Dexie.RangeSet();
8183
+ for (const { k } of updates) {
8184
+ if (k != undefined)
8185
+ keySet.addKey(k);
8186
+ }
8187
+ for (const interval of keySet) {
8188
+ enqueueTrigger(db, tblName, interval.from, trigger);
8189
+ }
8190
+ });
8191
+ }
8192
+ break;
8193
+ }
8194
+ return coreTable.mutate(req);
8195
+ } });
8196
+ } });
8197
+ },
8198
+ });
8199
+ let triggerExecPromise = null;
8200
+ let triggerScheduled = false;
8201
+ let scheduledTriggers = [];
8202
+ function $Y(db) {
8203
+ const $Y = db._options.Y;
8204
+ if (!$Y)
8205
+ throw new Error('Y library not supplied to Dexie constructor');
8206
+ return $Y;
8207
+ }
8208
+ function executeTriggers(triggersToRun) {
8209
+ return __awaiter(this, void 0, void 0, function* () {
8210
+ for (const { db, parentId, trigger, updatesTable } of triggersToRun) {
8211
+ // Load entire document into an Y.Doc instance:
8212
+ const updates = yield db
8213
+ .table(updatesTable)
8214
+ .where({ k: parentId })
8215
+ .toArray();
8216
+ const Y = $Y(db);
8217
+ const yDoc = new Y.Doc();
8218
+ for (const update of updates) {
8219
+ Y.applyUpdateV2(yDoc, update.u);
8220
+ }
8221
+ try {
8222
+ yield trigger(yDoc, parentId);
8223
+ }
8224
+ catch (error) {
8225
+ console.error(`Error in YDocTrigger ${error}`);
8226
+ }
8227
+ }
8228
+ });
8229
+ }
8230
+ function enqueueTrigger(db, updatesTable, parentId, trigger) {
8231
+ scheduledTriggers.push({
8232
+ db,
8233
+ updatesTable,
8234
+ parentId,
8235
+ trigger,
8236
+ });
8237
+ }
8238
+ function onTransactionCommitted() {
8239
+ return __awaiter(this, void 0, void 0, function* () {
8240
+ if (!triggerScheduled && scheduledTriggers.length > 0) {
8241
+ triggerScheduled = true;
8242
+ if (triggerExecPromise)
8243
+ yield triggerExecPromise.catch(() => { });
8244
+ setTimeout(() => {
8245
+ // setTimeout() is to escape from Promise.PSD zones and never run within liveQueries or transaction scopes
8246
+ triggerScheduled = false;
8247
+ const triggersToRun = scheduledTriggers;
8248
+ scheduledTriggers = [];
8249
+ triggerExecPromise = executeTriggers(triggersToRun).finally(() => (triggerExecPromise = null));
8250
+ }, 0);
8251
+ }
8252
+ });
8253
+ }
8254
+ function hookToDoc(doc, parentId, trigger) {
8255
+ // From now on, keep listening to doc updates and execute the trigger when it happens there instead
8256
+ doc.on('updateV2', (update, origin) => {
8257
+ //Dexie.ignoreTransaction(()=>{
8258
+ trigger(doc, parentId);
8259
+ //});
8260
+ });
8261
+ /*
8262
+ NOT NEEDED because DexieYProvider's docCache will also listen to destroy and remove it from its cache:
8263
+ doc.on('destroy', ()=>{
8264
+ docIsAlreadyHooked.delete(doc);
8265
+ })
8266
+ */
8267
+ }
8268
+ function defineYDocTrigger(table, prop, trigger) {
8269
+ var _a, _b;
8270
+ const updatesTable = (_b = (_a = table.schema.yProps) === null || _a === void 0 ? void 0 : _a.find((p) => p.prop === prop)) === null || _b === void 0 ? void 0 : _b.updatesTable;
8271
+ if (!updatesTable)
8272
+ throw new Error(`Table ${table.name} does not have a Yjs property named ${prop}`);
8273
+ ydocTriggers[updatesTable] = {
8274
+ trigger,
8275
+ parentTable: table.name,
8276
+ prop,
8277
+ };
8278
+ const db = table.db._novip;
8279
+ let mw = middlewares.get(db);
8280
+ if (!mw) {
8281
+ mw = createMiddleware(db);
8282
+ middlewares.set(db, mw);
8283
+ }
8284
+ db.use(mw);
8285
+ }
8286
+
8123
8287
  const DEFAULT_OPTIONS = {
8124
8288
  nameSuffix: true,
8125
8289
  };
@@ -8160,7 +8324,7 @@
8160
8324
  const syncComplete = new rxjs.Subject();
8161
8325
  dexie.cloud = {
8162
8326
  // @ts-ignore
8163
- version: "4.1.0-beta.38",
8327
+ version: "4.1.0-beta.40",
8164
8328
  options: Object.assign({}, DEFAULT_OPTIONS),
8165
8329
  schema: null,
8166
8330
  get currentUserId() {
@@ -8478,165 +8642,9 @@
8478
8642
  }
8479
8643
  }
8480
8644
  // @ts-ignore
8481
- dexieCloud.version = "4.1.0-beta.38";
8645
+ dexieCloud.version = "4.1.0-beta.40";
8482
8646
  Dexie.Cloud = dexieCloud;
8483
8647
 
8484
- const ydocTriggers = {};
8485
- const docIsAlreadyHooked = new WeakSet();
8486
- const middlewares = new WeakMap();
8487
- const createMiddleware = (db) => ({
8488
- stack: 'dbcore',
8489
- level: 10,
8490
- name: 'yTriggerMiddleware',
8491
- create: (down) => {
8492
- return Object.assign(Object.assign({}, down), { transaction: (stores, mode, options) => {
8493
- const idbtrans = down.transaction(stores, mode, options);
8494
- idbtrans.addEventListener('complete', onTransactionCommitted);
8495
- return idbtrans;
8496
- }, table: (tblName) => {
8497
- const coreTable = down.table(tblName);
8498
- const triggerSpec = ydocTriggers[tblName];
8499
- if (!triggerSpec)
8500
- return coreTable;
8501
- const { trigger, parentTable, prop } = triggerSpec;
8502
- return Object.assign(Object.assign({}, coreTable), { mutate(req) {
8503
- switch (req.type) {
8504
- case 'add': {
8505
- for (const yUpdateRow of req.values) {
8506
- if (yUpdateRow.k == undefined)
8507
- continue; // A syncer or garbage collection state does not point to a key
8508
- const primaryKey = yUpdateRow.k;
8509
- const doc = Dexie.DexieYProvider.getDocCache(db).find(parentTable, primaryKey, prop);
8510
- if (doc) {
8511
- if (!docIsAlreadyHooked.has(doc)) {
8512
- hookToDoc(doc, primaryKey, trigger);
8513
- docIsAlreadyHooked.add(doc);
8514
- }
8515
- }
8516
- else {
8517
- enqueueTrigger(db, tblName, primaryKey, trigger);
8518
- }
8519
- }
8520
- break;
8521
- }
8522
- case 'delete':
8523
- // @ts-ignore
8524
- if (req.trans._rejecting_y_ypdate) {
8525
- // The deletion came from a rejection, not garbage collection.
8526
- // When that happens, let the triggers run to compute new values
8527
- // based on the deleted updates.
8528
- coreTable
8529
- .getMany({
8530
- keys: req.keys,
8531
- trans: req.trans,
8532
- cache: 'immutable',
8533
- })
8534
- .then((updates) => {
8535
- const keySet = new Dexie.RangeSet();
8536
- for (const { k } of updates) {
8537
- if (k != undefined)
8538
- keySet.addKey(k);
8539
- }
8540
- for (const interval of keySet) {
8541
- enqueueTrigger(db, tblName, interval.from, trigger);
8542
- }
8543
- });
8544
- }
8545
- break;
8546
- }
8547
- return coreTable.mutate(req);
8548
- } });
8549
- } });
8550
- },
8551
- });
8552
- let triggerExecPromise = null;
8553
- let triggerScheduled = false;
8554
- let scheduledTriggers = [];
8555
- function $Y(db) {
8556
- const $Y = db._options.Y;
8557
- if (!$Y)
8558
- throw new Error('Y library not supplied to Dexie constructor');
8559
- return $Y;
8560
- }
8561
- function executeTriggers(triggersToRun) {
8562
- return __awaiter(this, void 0, void 0, function* () {
8563
- for (const { db, parentId, trigger, updatesTable } of triggersToRun) {
8564
- // Load entire document into an Y.Doc instance:
8565
- const updates = yield db
8566
- .table(updatesTable)
8567
- .where({ k: parentId })
8568
- .toArray();
8569
- const Y = $Y(db);
8570
- const yDoc = new Y.Doc();
8571
- for (const update of updates) {
8572
- Y.applyUpdateV2(yDoc, update.u);
8573
- }
8574
- try {
8575
- yield trigger(yDoc, parentId);
8576
- }
8577
- catch (error) {
8578
- console.error(`Error in YDocTrigger ${error}`);
8579
- }
8580
- }
8581
- });
8582
- }
8583
- function enqueueTrigger(db, updatesTable, parentId, trigger) {
8584
- scheduledTriggers.push({
8585
- db,
8586
- updatesTable,
8587
- parentId,
8588
- trigger,
8589
- });
8590
- }
8591
- function onTransactionCommitted() {
8592
- return __awaiter(this, void 0, void 0, function* () {
8593
- if (!triggerScheduled && scheduledTriggers.length > 0) {
8594
- triggerScheduled = true;
8595
- if (triggerExecPromise)
8596
- yield triggerExecPromise.catch(() => { });
8597
- setTimeout(() => {
8598
- // setTimeout() is to escape from Promise.PSD zones and never run within liveQueries or transaction scopes
8599
- triggerScheduled = false;
8600
- const triggersToRun = scheduledTriggers;
8601
- scheduledTriggers = [];
8602
- triggerExecPromise = executeTriggers(triggersToRun).finally(() => (triggerExecPromise = null));
8603
- }, 0);
8604
- }
8605
- });
8606
- }
8607
- function hookToDoc(doc, parentId, trigger) {
8608
- // From now on, keep listening to doc updates and execute the trigger when it happens there instead
8609
- doc.on('updateV2', (update, origin) => {
8610
- //Dexie.ignoreTransaction(()=>{
8611
- trigger(doc, parentId);
8612
- //});
8613
- });
8614
- /*
8615
- NOT NEEDED because DexieYProvider's docCache will also listen to destroy and remove it from its cache:
8616
- doc.on('destroy', ()=>{
8617
- docIsAlreadyHooked.delete(doc);
8618
- })
8619
- */
8620
- }
8621
- function defineYDocTrigger(table, prop, trigger) {
8622
- var _a, _b;
8623
- const updatesTable = (_b = (_a = table.schema.yProps) === null || _a === void 0 ? void 0 : _a.find((p) => p.prop === prop)) === null || _b === void 0 ? void 0 : _b.updatesTable;
8624
- if (!updatesTable)
8625
- throw new Error(`Table ${table.name} does not have a Yjs property named ${prop}`);
8626
- ydocTriggers[updatesTable] = {
8627
- trigger,
8628
- parentTable: table.name,
8629
- prop,
8630
- };
8631
- const db = table.db._novip;
8632
- let mw = middlewares.get(db);
8633
- if (!mw) {
8634
- mw = createMiddleware(db);
8635
- middlewares.set(db, mw);
8636
- }
8637
- db.use(mw);
8638
- }
8639
-
8640
8648
  exports.default = dexieCloud;
8641
8649
  exports.defineYDocTrigger = defineYDocTrigger;
8642
8650
  exports.dexieCloud = dexieCloud;