dexie-cloud-addon 4.1.0-alpha.10 → 4.1.0-alpha.12
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/modern/define-ydoc-trigger.d.ts +2 -0
- package/dist/modern/dexie-cloud-addon.d.ts +1 -0
- package/dist/modern/dexie-cloud-addon.js +295 -113
- 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 +139 -109
- 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/define-ydoc-trigger.d.ts +2 -0
- package/dist/umd/dexie-cloud-addon.d.ts +1 -0
- package/dist/umd/dexie-cloud-addon.js +294 -111
- 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 +139 -109
- 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 +2 -2
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* ==========================================================================
|
|
10
10
|
*
|
|
11
|
-
* Version 4.1.0-alpha.
|
|
11
|
+
* Version 4.1.0-alpha.12, Wed Oct 16 2024
|
|
12
12
|
*
|
|
13
13
|
* https://dexie.org
|
|
14
14
|
*
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
*
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import Dexie, { PropModification, cmp, DexieYProvider, liveQuery } from 'dexie';
|
|
19
|
+
import Dexie, { PropModification, cmp, DexieYProvider, liveQuery, RangeSet } from 'dexie';
|
|
20
20
|
import { firstValueFrom, from as from$1, filter as filter$1, Observable as Observable$1, BehaviorSubject, Subject, fromEvent, of, merge, switchMap as switchMap$1, tap as tap$1, mergeMap as mergeMap$1, Subscription as Subscription$1, throwError, combineLatest, map as map$1, share, timer as timer$1 } from 'rxjs';
|
|
21
21
|
|
|
22
22
|
/******************************************************************************
|
|
@@ -4944,7 +4944,7 @@ function listUpdatesSince(yTable, sinceIncluding) {
|
|
|
4944
4944
|
.toArray();
|
|
4945
4945
|
}
|
|
4946
4946
|
|
|
4947
|
-
function $Y(db) {
|
|
4947
|
+
function $Y$1(db) {
|
|
4948
4948
|
const $Y = db.dx._options.Y;
|
|
4949
4949
|
if (!$Y)
|
|
4950
4950
|
throw new Error('Y library not supplied to Dexie constructor');
|
|
@@ -4974,7 +4974,7 @@ function listYClientMessagesAndStateVector(db, tablesToSync) {
|
|
|
4974
4974
|
for (const table of tablesToSync) {
|
|
4975
4975
|
if (table.schema.yProps) {
|
|
4976
4976
|
for (const yProp of table.schema.yProps) {
|
|
4977
|
-
const Y = $Y(db); // This is how we retrieve the user-provided Y library
|
|
4977
|
+
const Y = $Y$1(db); // This is how we retrieve the user-provided Y library
|
|
4978
4978
|
const yTable = db.table(yProp.updatesTable); // the updates-table for this combo of table+propName
|
|
4979
4979
|
const syncState = (yield yTable.get(DEXIE_CLOUD_SYNCER_ID));
|
|
4980
4980
|
// unsentFrom = the `i` value of updates that aren't yet sent to server (or at least not acked by the server yet)
|
|
@@ -5058,6 +5058,7 @@ function getUpdatesTable(db, table, ydocProp) {
|
|
|
5058
5058
|
}
|
|
5059
5059
|
|
|
5060
5060
|
function applyYServerMessages(yMessages, db) {
|
|
5061
|
+
var _a;
|
|
5061
5062
|
return __awaiter(this, void 0, void 0, function* () {
|
|
5062
5063
|
const result = {};
|
|
5063
5064
|
for (const m of yMessages) {
|
|
@@ -5089,7 +5090,24 @@ function applyYServerMessages(yMessages, db) {
|
|
|
5089
5090
|
// See my question in https://discuss.yjs.dev/t/generate-an-inverse-update/2765
|
|
5090
5091
|
console.debug(`Y update rejected. Deleting it.`);
|
|
5091
5092
|
const utbl = getUpdatesTable(db, m.table, m.prop);
|
|
5092
|
-
|
|
5093
|
+
// Delete the rejected update and all local updates since (avoid holes in the CRDT)
|
|
5094
|
+
// and destroy it's open document if there is one.
|
|
5095
|
+
const primaryKey = (_a = (yield utbl.get(m.i))) === null || _a === void 0 ? void 0 : _a.k;
|
|
5096
|
+
if (primaryKey != null) {
|
|
5097
|
+
yield db.transaction('rw', utbl, tx => {
|
|
5098
|
+
// @ts-ignore
|
|
5099
|
+
tx.idbtrans._rejecting_y_ypdate = true; // Inform ydoc triggers that we delete because of a rejection and not GC
|
|
5100
|
+
return utbl
|
|
5101
|
+
.where('i')
|
|
5102
|
+
.aboveOrEqual(m.i)
|
|
5103
|
+
.filter(u => cmp(u.k, primaryKey) === 0 && ((u.f || 0) & 1) === 1)
|
|
5104
|
+
.delete();
|
|
5105
|
+
});
|
|
5106
|
+
// Destroy active doc
|
|
5107
|
+
const activeDoc = DexieYProvider.getDocCache(db.dx).find(m.table, primaryKey, m.prop);
|
|
5108
|
+
if (activeDoc)
|
|
5109
|
+
activeDoc.destroy(); // Destroy the document so that editors don't continue to work on it
|
|
5110
|
+
}
|
|
5093
5111
|
break;
|
|
5094
5112
|
}
|
|
5095
5113
|
case 'in-sync': {
|
|
@@ -7804,125 +7822,137 @@ const getInvitesObservable = associate((db) => {
|
|
|
7804
7822
|
function createYHandler(db) {
|
|
7805
7823
|
return (provider) => {
|
|
7806
7824
|
var _a;
|
|
7807
|
-
const awap = getAwarenessLibrary(db);
|
|
7808
7825
|
const doc = provider.doc;
|
|
7809
|
-
const { parentTable
|
|
7826
|
+
const { parentTable } = doc.meta || {};
|
|
7810
7827
|
if (!((_a = db.cloud.schema) === null || _a === void 0 ? void 0 : _a[parentTable].markedForSync)) {
|
|
7811
7828
|
return; // The table that holds the doc is not marked for sync - leave it to dexie. No syncing, no awareness.
|
|
7812
7829
|
}
|
|
7813
|
-
let awareness
|
|
7814
|
-
|
|
7815
|
-
|
|
7816
|
-
|
|
7817
|
-
|
|
7818
|
-
|
|
7819
|
-
|
|
7820
|
-
|
|
7821
|
-
|
|
7830
|
+
let awareness;
|
|
7831
|
+
Object.defineProperty(provider, "awareness", {
|
|
7832
|
+
get() {
|
|
7833
|
+
if (awareness)
|
|
7834
|
+
return awareness;
|
|
7835
|
+
awarenessWeakMap.set(doc, awareness);
|
|
7836
|
+
awareness = createAwareness(db, doc, provider);
|
|
7837
|
+
return awareness;
|
|
7838
|
+
}
|
|
7839
|
+
});
|
|
7840
|
+
};
|
|
7841
|
+
}
|
|
7842
|
+
function createAwareness(db, doc, provider) {
|
|
7843
|
+
const { parentTable, parentId, parentProp, updatesTable } = doc.meta;
|
|
7844
|
+
const awap = getAwarenessLibrary(db);
|
|
7845
|
+
const awareness = new awap.Awareness(doc);
|
|
7846
|
+
awareness.on('update', ({ added, updated, removed }, origin) => {
|
|
7847
|
+
// Send the update
|
|
7848
|
+
const changedClients = added.concat(updated).concat(removed);
|
|
7849
|
+
const user = db.cloud.currentUser.value;
|
|
7850
|
+
if (origin !== 'server' && user.isLoggedIn && !isEagerSyncDisabled(db)) {
|
|
7851
|
+
const update = awap.encodeAwarenessUpdate(awareness, changedClients);
|
|
7852
|
+
db.messageProducer.next({
|
|
7853
|
+
type: 'aware',
|
|
7854
|
+
table: parentTable,
|
|
7855
|
+
prop: parentProp,
|
|
7856
|
+
k: doc.meta.parentId,
|
|
7857
|
+
u: update,
|
|
7858
|
+
});
|
|
7859
|
+
if (provider.destroyed) {
|
|
7860
|
+
// We're called from awareness.on('destroy') that did
|
|
7861
|
+
// removeAwarenessStates.
|
|
7862
|
+
// It's time to also send the doc-close message that dexie-cloud understands
|
|
7863
|
+
// and uses to stop subscribing for updates and awareness updates and brings
|
|
7864
|
+
// down the cached information in memory on the WS connection for this.
|
|
7822
7865
|
db.messageProducer.next({
|
|
7823
|
-
type: '
|
|
7866
|
+
type: 'doc-close',
|
|
7824
7867
|
table: parentTable,
|
|
7825
7868
|
prop: parentProp,
|
|
7826
|
-
k: doc.meta.parentId
|
|
7827
|
-
u: update,
|
|
7869
|
+
k: doc.meta.parentId
|
|
7828
7870
|
});
|
|
7829
|
-
if (provider.destroyed) {
|
|
7830
|
-
// We're called from awareness.on('destroy') that did
|
|
7831
|
-
// removeAwarenessStates.
|
|
7832
|
-
// It's time to also send the doc-close message that dexie-cloud understands
|
|
7833
|
-
// and uses to stop subscribing for updates and awareness updates and brings
|
|
7834
|
-
// down the cached information in memory on the WS connection for this.
|
|
7835
|
-
db.messageProducer.next({
|
|
7836
|
-
type: 'doc-close',
|
|
7837
|
-
table: parentTable,
|
|
7838
|
-
prop: parentProp,
|
|
7839
|
-
k: doc.meta.parentId
|
|
7840
|
-
});
|
|
7841
|
-
}
|
|
7842
7871
|
}
|
|
7843
|
-
}
|
|
7844
|
-
|
|
7845
|
-
|
|
7846
|
-
|
|
7847
|
-
|
|
7848
|
-
|
|
7849
|
-
|
|
7850
|
-
|
|
7872
|
+
}
|
|
7873
|
+
});
|
|
7874
|
+
awareness.on('destroy', () => {
|
|
7875
|
+
// Signal to server that this provider is destroyed (the update event will be triggered, which
|
|
7876
|
+
// in turn will trigger db.messageProducer that will send the message to the server if WS is connected)
|
|
7877
|
+
awap.removeAwarenessStates(awareness, [doc.clientID], 'provider destroyed');
|
|
7878
|
+
});
|
|
7879
|
+
// Open the document on the server
|
|
7880
|
+
(() => __awaiter(this, void 0, void 0, function* () {
|
|
7881
|
+
if (provider.destroyed)
|
|
7882
|
+
return;
|
|
7883
|
+
let connected = false;
|
|
7884
|
+
let currentFlowId = 1;
|
|
7885
|
+
const subscription = db.cloud.webSocketStatus.subscribe((wsStatus) => {
|
|
7851
7886
|
if (provider.destroyed)
|
|
7852
7887
|
return;
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
|
|
7856
|
-
|
|
7888
|
+
// Keep "connected" state in a variable so we can check it after async operations
|
|
7889
|
+
connected = wsStatus === 'connected';
|
|
7890
|
+
// We are or got connected. Open the document on the server.
|
|
7891
|
+
const user = db.cloud.currentUser.value;
|
|
7892
|
+
if (wsStatus === "connected" && user.isLoggedIn && !isEagerSyncDisabled(db)) {
|
|
7893
|
+
++currentFlowId;
|
|
7894
|
+
openDocumentOnServer().catch(error => {
|
|
7895
|
+
console.warn(`Error catched in createYHandler.ts: ${error}`);
|
|
7896
|
+
});
|
|
7897
|
+
}
|
|
7898
|
+
});
|
|
7899
|
+
// Wait until WebSocket is connected
|
|
7900
|
+
provider.addCleanupHandler(subscription);
|
|
7901
|
+
/** Sends an 'doc-open' message to server whenever websocket becomes
|
|
7902
|
+
* connected, or if it is already connected.
|
|
7903
|
+
* The flow is aborted in case websocket is disconnected while querying
|
|
7904
|
+
* information required to compute the state vector. Flow is also
|
|
7905
|
+
* aborted in case document or provider has been destroyed during
|
|
7906
|
+
* the async parts of the task.
|
|
7907
|
+
*
|
|
7908
|
+
* The state vector is only computed from the updates that have occured
|
|
7909
|
+
* after the last full sync - which could very often be zero - in which
|
|
7910
|
+
* case no state vector is sent (then the server already knows us by
|
|
7911
|
+
* revision)
|
|
7912
|
+
*
|
|
7913
|
+
* When server gets the doc-open message, it will authorized us for
|
|
7914
|
+
* whether we are allowed to read / write to this document, and then
|
|
7915
|
+
* keep the cached information in memory on the WS connection for this
|
|
7916
|
+
* particular document, as well as subscribe to updates and awareness updates
|
|
7917
|
+
* from other clients on the document.
|
|
7918
|
+
*/
|
|
7919
|
+
function openDocumentOnServer(wsStatus) {
|
|
7920
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
7921
|
+
const myFlow = currentFlowId; // So we can abort when a new flow is started
|
|
7922
|
+
const yTbl = db.table(updatesTable);
|
|
7923
|
+
const syncState = yield yTbl.get(DEXIE_CLOUD_SYNCER_ID);
|
|
7924
|
+
// After every await, check if we still should be working on this task.
|
|
7925
|
+
if (provider.destroyed || currentFlowId !== myFlow || !connected)
|
|
7857
7926
|
return;
|
|
7858
|
-
|
|
7859
|
-
|
|
7860
|
-
|
|
7861
|
-
|
|
7862
|
-
|
|
7863
|
-
|
|
7864
|
-
|
|
7865
|
-
|
|
7866
|
-
|
|
7927
|
+
const receivedUntil = (syncState === null || syncState === void 0 ? void 0 : syncState.receivedUntil) || 0;
|
|
7928
|
+
const docOpenMsg = {
|
|
7929
|
+
type: 'doc-open',
|
|
7930
|
+
table: parentTable,
|
|
7931
|
+
prop: parentProp,
|
|
7932
|
+
k: parentId,
|
|
7933
|
+
serverRev: syncState === null || syncState === void 0 ? void 0 : syncState.serverRev,
|
|
7934
|
+
};
|
|
7935
|
+
const serverUpdatesSinceLastSync = yield yTbl
|
|
7936
|
+
.where('i')
|
|
7937
|
+
.between(receivedUntil, Infinity, false)
|
|
7938
|
+
.filter((update) => cmp(update.k, parentId) === 0 && // Only updates for this document
|
|
7939
|
+
((update.f || 0) & 1) === 0 // Don't include local changes
|
|
7940
|
+
)
|
|
7941
|
+
.toArray();
|
|
7942
|
+
// After every await, check if we still should be working on this task.
|
|
7943
|
+
if (provider.destroyed || currentFlowId !== myFlow || !connected)
|
|
7944
|
+
return;
|
|
7945
|
+
if (serverUpdatesSinceLastSync.length > 0) {
|
|
7946
|
+
const Y = $Y$1(db); // Get the Yjs library from Dexie constructor options
|
|
7947
|
+
const mergedUpdate = Y.mergeUpdatesV2(serverUpdatesSinceLastSync.map((update) => update.u));
|
|
7948
|
+
const stateVector = Y.encodeStateVectorFromUpdateV2(mergedUpdate);
|
|
7949
|
+
docOpenMsg.sv = stateVector;
|
|
7867
7950
|
}
|
|
7951
|
+
db.messageProducer.next(docOpenMsg);
|
|
7868
7952
|
});
|
|
7869
|
-
|
|
7870
|
-
|
|
7871
|
-
|
|
7872
|
-
* connected, or if it is already connected.
|
|
7873
|
-
* The flow is aborted in case websocket is disconnected while querying
|
|
7874
|
-
* information required to compute the state vector. Flow is also
|
|
7875
|
-
* aborted in case document or provider has been destroyed during
|
|
7876
|
-
* the async parts of the task.
|
|
7877
|
-
*
|
|
7878
|
-
* The state vector is only computed from the updates that have occured
|
|
7879
|
-
* after the last full sync - which could very often be zero - in which
|
|
7880
|
-
* case no state vector is sent (then the server already knows us by
|
|
7881
|
-
* revision)
|
|
7882
|
-
*
|
|
7883
|
-
* When server gets the doc-open message, it will authorized us for
|
|
7884
|
-
* whether we are allowed to read / write to this document, and then
|
|
7885
|
-
* keep the cached information in memory on the WS connection for this
|
|
7886
|
-
* particular document, as well as subscribe to updates and awareness updates
|
|
7887
|
-
* from other clients on the document.
|
|
7888
|
-
*/
|
|
7889
|
-
function openDocumentOnServer(wsStatus) {
|
|
7890
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
7891
|
-
const myFlow = currentFlowId; // So we can abort when a new flow is started
|
|
7892
|
-
const yTbl = db.table(updatesTable);
|
|
7893
|
-
const syncState = yield yTbl.get(DEXIE_CLOUD_SYNCER_ID);
|
|
7894
|
-
// After every await, check if we still should be working on this task.
|
|
7895
|
-
if (provider.destroyed || currentFlowId !== myFlow || !connected)
|
|
7896
|
-
return;
|
|
7897
|
-
const receivedUntil = (syncState === null || syncState === void 0 ? void 0 : syncState.receivedUntil) || 0;
|
|
7898
|
-
const docOpenMsg = {
|
|
7899
|
-
type: 'doc-open',
|
|
7900
|
-
table: parentTable,
|
|
7901
|
-
prop: parentProp,
|
|
7902
|
-
k: parentId,
|
|
7903
|
-
serverRev: syncState === null || syncState === void 0 ? void 0 : syncState.serverRev,
|
|
7904
|
-
};
|
|
7905
|
-
const serverUpdatesSinceLastSync = yield yTbl
|
|
7906
|
-
.where('i')
|
|
7907
|
-
.between(receivedUntil, Infinity, false)
|
|
7908
|
-
.filter((update) => cmp(update.k, parentId) === 0 && // Only updates for this document
|
|
7909
|
-
((update.f || 0) & 1) === 0 // Don't include local changes
|
|
7910
|
-
)
|
|
7911
|
-
.toArray();
|
|
7912
|
-
// After every await, check if we still should be working on this task.
|
|
7913
|
-
if (provider.destroyed || currentFlowId !== myFlow || !connected)
|
|
7914
|
-
return;
|
|
7915
|
-
if (serverUpdatesSinceLastSync.length > 0) {
|
|
7916
|
-
const Y = $Y(db); // Get the Yjs library from Dexie constructor options
|
|
7917
|
-
const mergedUpdate = Y.mergeUpdatesV2(serverUpdatesSinceLastSync.map((update) => update.u));
|
|
7918
|
-
const stateVector = Y.encodeStateVectorFromUpdateV2(mergedUpdate);
|
|
7919
|
-
docOpenMsg.sv = stateVector;
|
|
7920
|
-
}
|
|
7921
|
-
db.messageProducer.next(docOpenMsg);
|
|
7922
|
-
});
|
|
7923
|
-
}
|
|
7924
|
-
}));
|
|
7925
|
-
};
|
|
7953
|
+
}
|
|
7954
|
+
}))();
|
|
7955
|
+
return awareness;
|
|
7926
7956
|
}
|
|
7927
7957
|
|
|
7928
7958
|
function getTiedRealmId(objectId) {
|
|
@@ -7972,7 +8002,7 @@ function dexieCloud(dexie) {
|
|
|
7972
8002
|
const syncComplete = new Subject();
|
|
7973
8003
|
dexie.cloud = {
|
|
7974
8004
|
// @ts-ignore
|
|
7975
|
-
version: "4.1.0-alpha.
|
|
8005
|
+
version: "4.1.0-alpha.12",
|
|
7976
8006
|
options: Object.assign({}, DEFAULT_OPTIONS),
|
|
7977
8007
|
schema: null,
|
|
7978
8008
|
get currentUserId() {
|
|
@@ -8274,8 +8304,160 @@ function dexieCloud(dexie) {
|
|
|
8274
8304
|
}
|
|
8275
8305
|
}
|
|
8276
8306
|
// @ts-ignore
|
|
8277
|
-
dexieCloud.version = "4.1.0-alpha.
|
|
8307
|
+
dexieCloud.version = "4.1.0-alpha.12";
|
|
8278
8308
|
Dexie.Cloud = dexieCloud;
|
|
8279
8309
|
|
|
8280
|
-
|
|
8310
|
+
const ydocTriggers = {};
|
|
8311
|
+
const docIsAlreadyHooked = new WeakSet();
|
|
8312
|
+
const middlewares = new WeakMap();
|
|
8313
|
+
const createMiddleware = (db) => ({
|
|
8314
|
+
stack: 'dbcore',
|
|
8315
|
+
level: 10,
|
|
8316
|
+
name: 'yTriggerMiddleware',
|
|
8317
|
+
create: (down) => {
|
|
8318
|
+
return Object.assign(Object.assign({}, down), { transaction: (stores, mode, options) => {
|
|
8319
|
+
const idbtrans = down.transaction(stores, mode, options);
|
|
8320
|
+
idbtrans.addEventListener('complete', onTransactionCommitted);
|
|
8321
|
+
return idbtrans;
|
|
8322
|
+
}, table: (tblName) => {
|
|
8323
|
+
const coreTable = down.table(tblName);
|
|
8324
|
+
const triggerSpec = ydocTriggers[tblName];
|
|
8325
|
+
if (!triggerSpec)
|
|
8326
|
+
return coreTable;
|
|
8327
|
+
const { trigger, parentTable, prop } = triggerSpec;
|
|
8328
|
+
return Object.assign(Object.assign({}, coreTable), { mutate(req) {
|
|
8329
|
+
switch (req.type) {
|
|
8330
|
+
case 'add': {
|
|
8331
|
+
for (const obj of req.values) {
|
|
8332
|
+
const primaryKey = coreTable.schema.primaryKey.extractKey(obj);
|
|
8333
|
+
const doc = DexieYProvider.getDocCache(db).find(parentTable, primaryKey, prop);
|
|
8334
|
+
if (doc) {
|
|
8335
|
+
if (!docIsAlreadyHooked.has(doc)) {
|
|
8336
|
+
hookToDoc(doc, primaryKey, trigger);
|
|
8337
|
+
docIsAlreadyHooked.add(doc);
|
|
8338
|
+
}
|
|
8339
|
+
}
|
|
8340
|
+
else {
|
|
8341
|
+
enqueueTrigger(tblName, primaryKey, trigger);
|
|
8342
|
+
}
|
|
8343
|
+
}
|
|
8344
|
+
break;
|
|
8345
|
+
}
|
|
8346
|
+
case 'delete':
|
|
8347
|
+
// @ts-ignore
|
|
8348
|
+
if (req.trans._rejecting_y_ypdate) {
|
|
8349
|
+
// The deletion came from a rejection, not garbage collection.
|
|
8350
|
+
// When that happens, let the triggers run to compute new values
|
|
8351
|
+
// based on the deleted updates.
|
|
8352
|
+
coreTable
|
|
8353
|
+
.getMany({
|
|
8354
|
+
keys: req.keys,
|
|
8355
|
+
trans: req.trans,
|
|
8356
|
+
cache: 'immutable',
|
|
8357
|
+
})
|
|
8358
|
+
.then((updates) => {
|
|
8359
|
+
const keySet = new RangeSet();
|
|
8360
|
+
for (const { k } of updates) {
|
|
8361
|
+
keySet.addKey(k);
|
|
8362
|
+
}
|
|
8363
|
+
for (const key of keySet) {
|
|
8364
|
+
enqueueTrigger(tblName, key, trigger);
|
|
8365
|
+
}
|
|
8366
|
+
});
|
|
8367
|
+
}
|
|
8368
|
+
break;
|
|
8369
|
+
}
|
|
8370
|
+
return coreTable.mutate(req);
|
|
8371
|
+
} });
|
|
8372
|
+
} });
|
|
8373
|
+
},
|
|
8374
|
+
});
|
|
8375
|
+
let triggerExecPromise = null;
|
|
8376
|
+
let triggerScheduled = false;
|
|
8377
|
+
let scheduledTriggers = [];
|
|
8378
|
+
function $Y(db) {
|
|
8379
|
+
const $Y = db._options.Y;
|
|
8380
|
+
if (!$Y)
|
|
8381
|
+
throw new Error('Y library not supplied to Dexie constructor');
|
|
8382
|
+
return $Y;
|
|
8383
|
+
}
|
|
8384
|
+
function executeTriggers(triggersToRun) {
|
|
8385
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
8386
|
+
for (const { db, parentId, trigger, updatesTable } of triggersToRun) {
|
|
8387
|
+
// Load entire document into an Y.Doc instance:
|
|
8388
|
+
const updates = yield db
|
|
8389
|
+
.table(updatesTable)
|
|
8390
|
+
.where({ k: parentId })
|
|
8391
|
+
.toArray();
|
|
8392
|
+
const Y = $Y(db);
|
|
8393
|
+
const yDoc = new Y.Doc();
|
|
8394
|
+
for (const update of updates) {
|
|
8395
|
+
Y.applyUpdateV2(yDoc, update);
|
|
8396
|
+
}
|
|
8397
|
+
try {
|
|
8398
|
+
yield trigger(yDoc, parentId);
|
|
8399
|
+
}
|
|
8400
|
+
catch (error) {
|
|
8401
|
+
console.error(`Error in YDocTrigger ${error}`);
|
|
8402
|
+
}
|
|
8403
|
+
}
|
|
8404
|
+
});
|
|
8405
|
+
}
|
|
8406
|
+
function enqueueTrigger(updatesTable, parentId, trigger) {
|
|
8407
|
+
var _a;
|
|
8408
|
+
((_a = scheduledTriggers[updatesTable]) !== null && _a !== void 0 ? _a : (scheduledTriggers[updatesTable] = [])).push({
|
|
8409
|
+
parentId,
|
|
8410
|
+
trigger,
|
|
8411
|
+
});
|
|
8412
|
+
}
|
|
8413
|
+
function onTransactionCommitted() {
|
|
8414
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
8415
|
+
if (!triggerScheduled && scheduledTriggers.length > 0) {
|
|
8416
|
+
triggerScheduled = true;
|
|
8417
|
+
if (triggerExecPromise)
|
|
8418
|
+
yield triggerExecPromise.catch(() => { });
|
|
8419
|
+
setTimeout(() => {
|
|
8420
|
+
// setTimeout() is to escape from Promise.PSD zones and never run within liveQueries or transaction scopes
|
|
8421
|
+
triggerScheduled = false;
|
|
8422
|
+
const triggersToRun = scheduledTriggers;
|
|
8423
|
+
scheduledTriggers = [];
|
|
8424
|
+
triggerExecPromise = executeTriggers(triggersToRun).finally(() => (triggerExecPromise = null));
|
|
8425
|
+
}, 0);
|
|
8426
|
+
}
|
|
8427
|
+
});
|
|
8428
|
+
}
|
|
8429
|
+
function hookToDoc(doc, parentId, trigger) {
|
|
8430
|
+
// From now on, keep listening to doc updates and execute the trigger when it happens there instead
|
|
8431
|
+
doc.on('updateV2', (update, origin) => {
|
|
8432
|
+
//Dexie.ignoreTransaction(()=>{
|
|
8433
|
+
trigger(doc, parentId);
|
|
8434
|
+
//});
|
|
8435
|
+
});
|
|
8436
|
+
/*
|
|
8437
|
+
NOT NEEDED because DexieYProvider's docCache will also listen to destroy and remove it from its cache:
|
|
8438
|
+
doc.on('destroy', ()=>{
|
|
8439
|
+
docIsAlreadyHooked.delete(doc);
|
|
8440
|
+
})
|
|
8441
|
+
*/
|
|
8442
|
+
}
|
|
8443
|
+
function defineYDocTrigger(table, prop, trigger) {
|
|
8444
|
+
var _a, _b;
|
|
8445
|
+
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;
|
|
8446
|
+
if (!updatesTable)
|
|
8447
|
+
throw new Error(`Table ${table.name} does not have a Yjs property named ${prop}`);
|
|
8448
|
+
ydocTriggers[updatesTable] = {
|
|
8449
|
+
trigger,
|
|
8450
|
+
parentTable: table.name,
|
|
8451
|
+
prop,
|
|
8452
|
+
};
|
|
8453
|
+
const db = table.db._novip;
|
|
8454
|
+
let mw = middlewares.get(db);
|
|
8455
|
+
if (!mw) {
|
|
8456
|
+
mw = createMiddleware(db);
|
|
8457
|
+
middlewares.set(db, mw);
|
|
8458
|
+
}
|
|
8459
|
+
db.use(mw);
|
|
8460
|
+
}
|
|
8461
|
+
|
|
8462
|
+
export { dexieCloud as default, defineYDocTrigger, dexieCloud, getTiedObjectId, getTiedRealmId, resolveText };
|
|
8281
8463
|
//# sourceMappingURL=dexie-cloud-addon.js.map
|