dexie-cloud-addon 4.1.0-beta.41 → 4.1.0-beta.43
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/dexie-cloud-addon.js +137 -107
- 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/helpers/dbOnClosed.d.ts +2 -0
- package/dist/modern/service-worker.js +54 -24
- 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 +137 -107
- 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/helpers/dbOnClosed.d.ts +2 -0
- package/dist/umd/service-worker.js +54 -24
- 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 +3 -3
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* ==========================================================================
|
|
10
10
|
*
|
|
11
|
-
* Version 4.1.0-beta.
|
|
11
|
+
* Version 4.1.0-beta.43, Fri Feb 07 2025
|
|
12
12
|
*
|
|
13
13
|
* https://dexie.org
|
|
14
14
|
*
|
|
@@ -3038,19 +3038,25 @@
|
|
|
3038
3038
|
}
|
|
3039
3039
|
}
|
|
3040
3040
|
|
|
3041
|
+
const hasArrayBufferB64 = "fromBase64" in Uint8Array; // https://github.com/tc39/proposal-arraybuffer-base64;
|
|
3041
3042
|
const b64decode = typeof Buffer !== "undefined"
|
|
3042
|
-
? (base64) => Buffer.from(base64, "base64")
|
|
3043
|
-
:
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3043
|
+
? (base64) => Buffer.from(base64, "base64") // Node
|
|
3044
|
+
: hasArrayBufferB64
|
|
3045
|
+
? // @ts-ignore: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array/fromBase64
|
|
3046
|
+
(base64) => Uint8Array.fromBase64(base64) // Modern javascript standard
|
|
3047
|
+
: (base64) => {
|
|
3048
|
+
// Legacy DOM workaround
|
|
3049
|
+
const binary_string = atob(base64);
|
|
3050
|
+
const len = binary_string.length;
|
|
3051
|
+
const bytes = new Uint8Array(len);
|
|
3052
|
+
for (var i = 0; i < len; i++) {
|
|
3053
|
+
bytes[i] = binary_string.charCodeAt(i);
|
|
3054
|
+
}
|
|
3055
|
+
return bytes;
|
|
3056
|
+
};
|
|
3052
3057
|
const b64encode = typeof Buffer !== "undefined"
|
|
3053
3058
|
? (b) => {
|
|
3059
|
+
// Node
|
|
3054
3060
|
if (ArrayBuffer.isView(b)) {
|
|
3055
3061
|
return Buffer.from(b.buffer, b.byteOffset, b.byteLength).toString("base64");
|
|
3056
3062
|
}
|
|
@@ -3058,16 +3064,20 @@
|
|
|
3058
3064
|
return Buffer.from(b).toString("base64");
|
|
3059
3065
|
}
|
|
3060
3066
|
}
|
|
3061
|
-
:
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
const
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3067
|
+
: hasArrayBufferB64
|
|
3068
|
+
? // @ts-ignore https://github.com/tc39/proposal-arraybuffer-base64
|
|
3069
|
+
(b) => b.toBase64() // Modern Javascript standard
|
|
3070
|
+
: (b) => {
|
|
3071
|
+
// Legacy DOM workaround
|
|
3072
|
+
const u8a = ArrayBuffer.isView(b) ? b : new Uint8Array(b);
|
|
3073
|
+
const CHUNK_SIZE = 0x1000;
|
|
3074
|
+
const strs = [];
|
|
3075
|
+
for (let i = 0, l = u8a.length; i < l; i += CHUNK_SIZE) {
|
|
3076
|
+
const chunk = u8a.subarray(i, i + CHUNK_SIZE);
|
|
3077
|
+
strs.push(String.fromCharCode.apply(null, chunk));
|
|
3078
|
+
}
|
|
3079
|
+
return btoa(strs.join(""));
|
|
3080
|
+
};
|
|
3071
3081
|
|
|
3072
3082
|
class TokenErrorResponseError extends Error {
|
|
3073
3083
|
constructor({ title, message, messageCode, messageParams, }) {
|
|
@@ -4554,6 +4564,26 @@
|
|
|
4554
4564
|
},
|
|
4555
4565
|
};
|
|
4556
4566
|
|
|
4567
|
+
var FileDef = {
|
|
4568
|
+
File: {
|
|
4569
|
+
test: (file, toStringTag) => toStringTag === "File",
|
|
4570
|
+
replace: (file) => ({
|
|
4571
|
+
$t: "File",
|
|
4572
|
+
v: b64encode(string2ArrayBuffer(readBlobSync(file))),
|
|
4573
|
+
type: file.type,
|
|
4574
|
+
name: file.name,
|
|
4575
|
+
lastModified: new Date(file.lastModified).toISOString(),
|
|
4576
|
+
}),
|
|
4577
|
+
revive: ({ type, v, name, lastModified }) => {
|
|
4578
|
+
const ab = b64decode(v);
|
|
4579
|
+
return new File([ab], name, {
|
|
4580
|
+
type,
|
|
4581
|
+
lastModified: new Date(lastModified).getTime(),
|
|
4582
|
+
});
|
|
4583
|
+
},
|
|
4584
|
+
},
|
|
4585
|
+
};
|
|
4586
|
+
|
|
4557
4587
|
// Since server revisions are stored in bigints, we need to handle clients without
|
|
4558
4588
|
// bigint support to not fail when serverRevision is passed over to client.
|
|
4559
4589
|
// We need to not fail when reviving it and we need to somehow store the information.
|
|
@@ -4589,7 +4619,7 @@
|
|
|
4589
4619
|
revive: ({ v }) => new FakeBigInt(v),
|
|
4590
4620
|
},
|
|
4591
4621
|
};
|
|
4592
|
-
const defs = Object.assign(Object.assign(Object.assign({}, undefinedDef), bigIntDef), { PropModification: {
|
|
4622
|
+
const defs = Object.assign(Object.assign(Object.assign(Object.assign({}, undefinedDef), bigIntDef), FileDef), { PropModification: {
|
|
4593
4623
|
test: (val) => val instanceof Dexie.PropModification,
|
|
4594
4624
|
replace: (propModification) => {
|
|
4595
4625
|
return Object.assign({ $t: 'PropModification' }, propModification['@@propmod']);
|
|
@@ -4964,7 +4994,7 @@
|
|
|
4964
4994
|
.toArray();
|
|
4965
4995
|
}
|
|
4966
4996
|
|
|
4967
|
-
function $Y
|
|
4997
|
+
function $Y(db) {
|
|
4968
4998
|
const $Y = db.dx._options.Y;
|
|
4969
4999
|
if (!$Y)
|
|
4970
5000
|
throw new Error('Y library not supplied to Dexie constructor');
|
|
@@ -4994,7 +5024,7 @@
|
|
|
4994
5024
|
for (const table of tablesToSync) {
|
|
4995
5025
|
if (table.schema.yProps) {
|
|
4996
5026
|
for (const yProp of table.schema.yProps) {
|
|
4997
|
-
const Y = $Y
|
|
5027
|
+
const Y = $Y(db); // This is how we retrieve the user-provided Y library
|
|
4998
5028
|
const yTable = db.table(yProp.updatesTable); // the updates-table for this combo of table+propName
|
|
4999
5029
|
const syncState = (yield yTable.get(DEXIE_CLOUD_SYNCER_ID));
|
|
5000
5030
|
// unsentFrom = the `i` value of updates that aren't yet sent to server (or at least not acked by the server yet)
|
|
@@ -8109,7 +8139,7 @@
|
|
|
8109
8139
|
if (provider.destroyed || currentFlowId !== myFlow || !connected)
|
|
8110
8140
|
return;
|
|
8111
8141
|
if (serverUpdatesSinceLastSync.length > 0) {
|
|
8112
|
-
const Y = $Y
|
|
8142
|
+
const Y = $Y(db); // Get the Yjs library from Dexie constructor options
|
|
8113
8143
|
const mergedUpdate = Y.mergeUpdatesV2(serverUpdatesSinceLastSync.map((update) => update.u));
|
|
8114
8144
|
const stateVector = Y.encodeStateVectorFromUpdateV2(mergedUpdate);
|
|
8115
8145
|
docOpenMsg.sv = stateVector;
|
|
@@ -8129,8 +8159,68 @@
|
|
|
8129
8159
|
}
|
|
8130
8160
|
|
|
8131
8161
|
const ydocTriggers = {};
|
|
8132
|
-
const docIsAlreadyHooked = new WeakSet();
|
|
8133
8162
|
const middlewares = new WeakMap();
|
|
8163
|
+
const txRunner = TriggerRunner("tx");
|
|
8164
|
+
const unloadRunner = TriggerRunner("unload");
|
|
8165
|
+
function TriggerRunner(name) {
|
|
8166
|
+
let triggerExecPromise = null;
|
|
8167
|
+
let triggerScheduled = false;
|
|
8168
|
+
let registry = new Map();
|
|
8169
|
+
function execute(registryCopy) {
|
|
8170
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
8171
|
+
for (const { db, parentId, triggers, parentTable, prop, } of registryCopy.values()) {
|
|
8172
|
+
const yDoc = Dexie.DexieYProvider.getOrCreateDocument(db, parentTable, prop, parentId);
|
|
8173
|
+
try {
|
|
8174
|
+
Dexie.DexieYProvider.load(yDoc); // If doc is open, this would just be a ++refount
|
|
8175
|
+
yield yDoc.whenLoaded; // If doc is loaded, this would resolve immediately
|
|
8176
|
+
for (const trigger of triggers) {
|
|
8177
|
+
yield trigger(yDoc, parentId);
|
|
8178
|
+
}
|
|
8179
|
+
}
|
|
8180
|
+
catch (error) {
|
|
8181
|
+
console.error(`Error in YDocTrigger ${error}`);
|
|
8182
|
+
}
|
|
8183
|
+
finally {
|
|
8184
|
+
Dexie.DexieYProvider.release(yDoc);
|
|
8185
|
+
}
|
|
8186
|
+
}
|
|
8187
|
+
});
|
|
8188
|
+
}
|
|
8189
|
+
return {
|
|
8190
|
+
name,
|
|
8191
|
+
run() {
|
|
8192
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
8193
|
+
if (!triggerScheduled && registry.size > 0) {
|
|
8194
|
+
triggerScheduled = true;
|
|
8195
|
+
if (triggerExecPromise)
|
|
8196
|
+
yield triggerExecPromise.catch(() => { });
|
|
8197
|
+
setTimeout(() => {
|
|
8198
|
+
// setTimeout() is to escape from Promise.PSD zones and never run within liveQueries or transaction scopes
|
|
8199
|
+
triggerScheduled = false;
|
|
8200
|
+
const registryCopy = registry;
|
|
8201
|
+
registry = new Map();
|
|
8202
|
+
triggerExecPromise = execute(registryCopy).finally(() => (triggerExecPromise = null));
|
|
8203
|
+
}, 0);
|
|
8204
|
+
}
|
|
8205
|
+
});
|
|
8206
|
+
},
|
|
8207
|
+
enqueue(db, parentTable, parentId, prop, trigger) {
|
|
8208
|
+
const key = `${db.name}:${parentTable}:${parentId}:${prop}`;
|
|
8209
|
+
let entry = registry.get(key);
|
|
8210
|
+
if (!entry) {
|
|
8211
|
+
entry = {
|
|
8212
|
+
db,
|
|
8213
|
+
parentTable,
|
|
8214
|
+
parentId,
|
|
8215
|
+
prop,
|
|
8216
|
+
triggers: new Set(),
|
|
8217
|
+
};
|
|
8218
|
+
registry.set(key, entry);
|
|
8219
|
+
}
|
|
8220
|
+
entry.triggers.add(trigger);
|
|
8221
|
+
},
|
|
8222
|
+
};
|
|
8223
|
+
}
|
|
8134
8224
|
const createMiddleware = (db) => ({
|
|
8135
8225
|
stack: 'dbcore',
|
|
8136
8226
|
level: 10,
|
|
@@ -8138,15 +8228,20 @@
|
|
|
8138
8228
|
create: (down) => {
|
|
8139
8229
|
return Object.assign(Object.assign({}, down), { transaction: (stores, mode, options) => {
|
|
8140
8230
|
const idbtrans = down.transaction(stores, mode, options);
|
|
8231
|
+
if (mode === 'readonly')
|
|
8232
|
+
return idbtrans;
|
|
8233
|
+
if (!stores.some((store) => ydocTriggers[store]))
|
|
8234
|
+
return idbtrans;
|
|
8141
8235
|
idbtrans.addEventListener('complete', onTransactionCommitted);
|
|
8142
8236
|
return idbtrans;
|
|
8143
|
-
}, table: (
|
|
8144
|
-
const coreTable = down.table(
|
|
8145
|
-
const triggerSpec = ydocTriggers[
|
|
8237
|
+
}, table: (updatesTable) => {
|
|
8238
|
+
const coreTable = down.table(updatesTable);
|
|
8239
|
+
const triggerSpec = ydocTriggers[updatesTable];
|
|
8146
8240
|
if (!triggerSpec)
|
|
8147
8241
|
return coreTable;
|
|
8148
8242
|
const { trigger, parentTable, prop } = triggerSpec;
|
|
8149
8243
|
return Object.assign(Object.assign({}, coreTable), { mutate(req) {
|
|
8244
|
+
var _a;
|
|
8150
8245
|
switch (req.type) {
|
|
8151
8246
|
case 'add': {
|
|
8152
8247
|
for (const yUpdateRow of req.values) {
|
|
@@ -8154,15 +8249,10 @@
|
|
|
8154
8249
|
continue; // A syncer or garbage collection state does not point to a key
|
|
8155
8250
|
const primaryKey = yUpdateRow.k;
|
|
8156
8251
|
const doc = Dexie.DexieYProvider.getDocCache(db).find(parentTable, primaryKey, prop);
|
|
8157
|
-
|
|
8158
|
-
|
|
8159
|
-
|
|
8160
|
-
|
|
8161
|
-
}
|
|
8162
|
-
}
|
|
8163
|
-
else {
|
|
8164
|
-
enqueueTrigger(db, tblName, primaryKey, trigger);
|
|
8165
|
-
}
|
|
8252
|
+
const runner = doc && ((_a = Dexie.DexieYProvider.for(doc)) === null || _a === void 0 ? void 0 : _a.refCount)
|
|
8253
|
+
? unloadRunner // Document is open. Wait with trigger until it's closed.
|
|
8254
|
+
: txRunner; // Document is closed. Run trigger immediately after transaction commits.
|
|
8255
|
+
runner.enqueue(db, parentTable, primaryKey, prop, trigger);
|
|
8166
8256
|
}
|
|
8167
8257
|
break;
|
|
8168
8258
|
}
|
|
@@ -8185,7 +8275,7 @@
|
|
|
8185
8275
|
keySet.addKey(k);
|
|
8186
8276
|
}
|
|
8187
8277
|
for (const interval of keySet) {
|
|
8188
|
-
|
|
8278
|
+
txRunner.enqueue(db, parentTable, interval.from, prop, trigger);
|
|
8189
8279
|
}
|
|
8190
8280
|
});
|
|
8191
8281
|
}
|
|
@@ -8196,74 +8286,11 @@
|
|
|
8196
8286
|
} });
|
|
8197
8287
|
},
|
|
8198
8288
|
});
|
|
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
8289
|
function onTransactionCommitted() {
|
|
8239
|
-
|
|
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
|
-
});
|
|
8290
|
+
txRunner.run();
|
|
8253
8291
|
}
|
|
8254
|
-
function
|
|
8255
|
-
|
|
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
|
-
*/
|
|
8292
|
+
function beforeProviderUnload() {
|
|
8293
|
+
unloadRunner.run();
|
|
8267
8294
|
}
|
|
8268
8295
|
function defineYDocTrigger(table, prop, trigger) {
|
|
8269
8296
|
var _a, _b;
|
|
@@ -8282,6 +8309,9 @@
|
|
|
8282
8309
|
middlewares.set(db, mw);
|
|
8283
8310
|
}
|
|
8284
8311
|
db.use(mw);
|
|
8312
|
+
{
|
|
8313
|
+
Dexie.DexieYProvider.on('beforeunload', beforeProviderUnload);
|
|
8314
|
+
}
|
|
8285
8315
|
}
|
|
8286
8316
|
|
|
8287
8317
|
const DEFAULT_OPTIONS = {
|
|
@@ -8324,7 +8354,7 @@
|
|
|
8324
8354
|
const syncComplete = new rxjs.Subject();
|
|
8325
8355
|
dexie.cloud = {
|
|
8326
8356
|
// @ts-ignore
|
|
8327
|
-
version: "4.1.0-beta.
|
|
8357
|
+
version: "4.1.0-beta.43",
|
|
8328
8358
|
options: Object.assign({}, DEFAULT_OPTIONS),
|
|
8329
8359
|
schema: null,
|
|
8330
8360
|
get currentUserId() {
|
|
@@ -8642,7 +8672,7 @@
|
|
|
8642
8672
|
}
|
|
8643
8673
|
}
|
|
8644
8674
|
// @ts-ignore
|
|
8645
|
-
dexieCloud.version = "4.1.0-beta.
|
|
8675
|
+
dexieCloud.version = "4.1.0-beta.43";
|
|
8646
8676
|
Dexie.Cloud = dexieCloud;
|
|
8647
8677
|
|
|
8648
8678
|
exports.default = dexieCloud;
|