dexie-cloud-addon 4.4.5 → 4.4.7
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/DXCWebSocketStatus.d.ts +1 -1
- package/dist/modern/DexieCloudAPI.d.ts +1 -1
- package/dist/modern/authentication/AuthPersistedContext.d.ts +2 -2
- package/dist/modern/currentUserEmitter.d.ts +3 -3
- package/dist/modern/db/entities/Member.d.ts +3 -3
- package/dist/modern/db/entities/PersistedSyncState.d.ts +1 -1
- package/dist/modern/db/entities/Role.d.ts +3 -3
- package/dist/modern/default-ui/Dialog.d.ts +1 -1
- package/dist/modern/default-ui/index.d.ts +5 -5
- package/dist/modern/dexie-cloud-addon.js +646 -526
- 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/dexie-cloud-client.d.ts +1 -1
- package/dist/modern/helpers/BroadcastedAndLocalEvent.d.ts +2 -2
- package/dist/modern/helpers/getSyncableTables.d.ts +3 -3
- package/dist/modern/helpers/resolveText.d.ts +1 -1
- package/dist/modern/middleware-helpers/guardedTable.d.ts +1 -1
- package/dist/modern/service-worker.js +648 -528
- 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/modern/sync/BlobDownloadTracker.d.ts +2 -2
- package/dist/modern/sync/extractRealm.d.ts +1 -1
- package/dist/modern/sync/getTablesToSyncify.d.ts +2 -2
- package/dist/modern/sync/isSyncNeeded.d.ts +1 -1
- package/dist/modern/sync/messageConsumerIsReady.d.ts +1 -1
- package/dist/modern/sync/modifyLocalObjectsWithNewUserId.d.ts +3 -3
- package/dist/modern/sync/numUnsyncedMutations.d.ts +1 -1
- package/dist/modern/sync/performGuardedJob.d.ts +1 -1
- package/dist/modern/sync/registerSyncEvent.d.ts +1 -1
- package/dist/modern/sync/triggerSync.d.ts +2 -2
- package/dist/modern/types/DXCUserInteraction.d.ts +2 -2
- package/dist/modern/types/SyncState.d.ts +2 -2
- package/dist/modern/types/TXExpandos.d.ts +1 -1
- package/dist/modern/updateSchemaFromOptions.d.ts +2 -2
- package/dist/modern/verifyConfig.d.ts +1 -1
- package/dist/modern/verifySchema.d.ts +1 -1
- package/dist/modern/yjs/YTable.d.ts +3 -3
- package/dist/modern/yjs/getUpdatesTable.d.ts +2 -2
- package/dist/modern/yjs/reopenDocSignal.d.ts +2 -2
- package/dist/umd/dexie-cloud-addon.js +654 -534
- 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 +656 -536
- 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
- package/dist/modern/default-ui/AuthProviderButton.d.ts +0 -21
- package/dist/modern/default-ui/ProviderSelectionDialog.d.ts +0 -7
- package/dist/modern/default-ui/SelectDialog.d.ts +0 -10
- package/dist/modern/dexie-cloud-addon.min.js.gz +0 -0
- package/dist/umd/DISABLE_SERVICEWORKER_STRATEGY.d.ts +0 -1
- package/dist/umd/DXCWebSocketStatus.d.ts +0 -1
- package/dist/umd/DexieCloudAPI.d.ts +0 -75
- package/dist/umd/DexieCloudOptions.d.ts +0 -27
- package/dist/umd/DexieCloudSyncOptions.d.ts +0 -4
- package/dist/umd/DexieCloudTable.d.ts +0 -18
- package/dist/umd/InvalidLicenseError.d.ts +0 -5
- package/dist/umd/Invite.d.ts +0 -8
- package/dist/umd/PermissionChecker.d.ts +0 -15
- package/dist/umd/TSON.d.ts +0 -17
- package/dist/umd/WSObservable.d.ts +0 -72
- package/dist/umd/associate.d.ts +0 -1
- package/dist/umd/authentication/AuthPersistedContext.d.ts +0 -9
- package/dist/umd/authentication/TokenErrorResponseError.d.ts +0 -10
- package/dist/umd/authentication/TokenExpiredError.d.ts +0 -3
- package/dist/umd/authentication/UNAUTHORIZED_USER.d.ts +0 -2
- package/dist/umd/authentication/authenticate.d.ts +0 -13
- package/dist/umd/authentication/currentUserObservable.d.ts +0 -1
- package/dist/umd/authentication/interactWithUser.d.ts +0 -21
- package/dist/umd/authentication/login.d.ts +0 -3
- package/dist/umd/authentication/logout.d.ts +0 -5
- package/dist/umd/authentication/otpFetchTokenCallback.d.ts +0 -3
- package/dist/umd/authentication/setCurrentUser.d.ts +0 -14
- package/dist/umd/authentication/waitUntil.d.ts +0 -3
- package/dist/umd/computeSyncState.d.ts +0 -4
- package/dist/umd/createSharedValueObservable.d.ts +0 -3
- package/dist/umd/currentUserEmitter.d.ts +0 -3
- package/dist/umd/db/DexieCloudDB.d.ts +0 -61
- package/dist/umd/db/entities/BaseRevisionMapEntry.d.ts +0 -5
- package/dist/umd/db/entities/EntityCommon.d.ts +0 -5
- package/dist/umd/db/entities/GuardedJob.d.ts +0 -5
- package/dist/umd/db/entities/Member.d.ts +0 -19
- package/dist/umd/db/entities/PersistedSyncState.d.ts +0 -22
- package/dist/umd/db/entities/Realm.d.ts +0 -14
- package/dist/umd/db/entities/Role.d.ts +0 -11
- package/dist/umd/db/entities/UserLogin.d.ts +0 -23
- package/dist/umd/default-ui/Dialog.d.ts +0 -5
- package/dist/umd/default-ui/LoginDialog.d.ts +0 -3
- package/dist/umd/default-ui/Styles.d.ts +0 -3
- package/dist/umd/default-ui/index.d.ts +0 -24
- package/dist/umd/define-ydoc-trigger.d.ts +0 -3
- package/dist/umd/dexie-cloud-addon.d.ts +0 -3
- package/dist/umd/dexie-cloud-addon.js.gz +0 -0
- package/dist/umd/dexie-cloud-addon.min.js.gz +0 -0
- package/dist/umd/dexie-cloud-client.d.ts +0 -23
- package/dist/umd/errors/HttpError.d.ts +0 -5
- package/dist/umd/extend-dexie-interface.d.ts +0 -23
- package/dist/umd/getGlobalRolesObservable.d.ts +0 -5
- package/dist/umd/getInternalAccessControlObservable.d.ts +0 -12
- package/dist/umd/getInvitesObservable.d.ts +0 -23
- package/dist/umd/getPermissionsLookupObservable.d.ts +0 -16
- package/dist/umd/getTiedRealmId.d.ts +0 -2
- package/dist/umd/helpers/BroadcastedAndLocalEvent.d.ts +0 -8
- package/dist/umd/helpers/CancelToken.d.ts +0 -4
- package/dist/umd/helpers/IS_SERVICE_WORKER.d.ts +0 -1
- package/dist/umd/helpers/SWBroadcastChannel.d.ts +0 -12
- package/dist/umd/helpers/allSettled.d.ts +0 -1
- package/dist/umd/helpers/bulkUpdate.d.ts +0 -4
- package/dist/umd/helpers/computeRealmSetHash.d.ts +0 -2
- package/dist/umd/helpers/date-constants.d.ts +0 -5
- package/dist/umd/helpers/flatten.d.ts +0 -1
- package/dist/umd/helpers/getMutationTable.d.ts +0 -1
- package/dist/umd/helpers/getSyncableTables.d.ts +0 -4
- package/dist/umd/helpers/getTableFromMutationTable.d.ts +0 -1
- package/dist/umd/helpers/makeArray.d.ts +0 -1
- package/dist/umd/helpers/randomString.d.ts +0 -1
- package/dist/umd/helpers/resolveText.d.ts +0 -16
- package/dist/umd/helpers/throwVersionIncrementNeeded.d.ts +0 -1
- package/dist/umd/helpers/visibilityState.d.ts +0 -1
- package/dist/umd/isEagerSyncDisabled.d.ts +0 -2
- package/dist/umd/isFirefox.d.ts +0 -1
- package/dist/umd/isSafari.d.ts +0 -2
- package/dist/umd/mapValueObservable.d.ts +0 -5
- package/dist/umd/mergePermissions.d.ts +0 -2
- package/dist/umd/middleware-helpers/guardedTable.d.ts +0 -11
- package/dist/umd/middleware-helpers/idGenerationHelpers.d.ts +0 -18
- package/dist/umd/middlewares/createIdGenerationMiddleware.d.ts +0 -3
- package/dist/umd/middlewares/createImplicitPropSetterMiddleware.d.ts +0 -3
- package/dist/umd/middlewares/createMutationTrackingMiddleware.d.ts +0 -17
- package/dist/umd/middlewares/outstandingTransaction.d.ts +0 -4
- package/dist/umd/overrideParseStoresSpec.d.ts +0 -4
- package/dist/umd/performInitialSync.d.ts +0 -4
- package/dist/umd/permissions.d.ts +0 -9
- package/dist/umd/prodLog.d.ts +0 -9
- package/dist/umd/service-worker.d.ts +0 -1
- package/dist/umd/sync/DEXIE_CLOUD_SYNCER_ID.d.ts +0 -1
- package/dist/umd/sync/LocalSyncWorker.d.ts +0 -7
- package/dist/umd/sync/SyncRequiredError.d.ts +0 -3
- package/dist/umd/sync/applyServerChanges.d.ts +0 -3
- package/dist/umd/sync/connectWebSocket.d.ts +0 -2
- package/dist/umd/sync/encodeIdsForServer.d.ts +0 -4
- package/dist/umd/sync/extractRealm.d.ts +0 -2
- package/dist/umd/sync/getLatestRevisionsPerTable.d.ts +0 -6
- package/dist/umd/sync/getTablesToSyncify.d.ts +0 -3
- package/dist/umd/sync/isOnline.d.ts +0 -1
- package/dist/umd/sync/isSyncNeeded.d.ts +0 -2
- package/dist/umd/sync/listClientChanges.d.ts +0 -9
- package/dist/umd/sync/listSyncifiedChanges.d.ts +0 -5
- package/dist/umd/sync/messageConsumerIsReady.d.ts +0 -2
- package/dist/umd/sync/messagesFromServerQueue.d.ts +0 -8
- package/dist/umd/sync/modifyLocalObjectsWithNewUserId.d.ts +0 -4
- package/dist/umd/sync/myId.d.ts +0 -1
- package/dist/umd/sync/numUnsyncedMutations.d.ts +0 -2
- package/dist/umd/sync/old_startSyncingClientChanges.d.ts +0 -39
- package/dist/umd/sync/performGuardedJob.d.ts +0 -2
- package/dist/umd/sync/ratelimit.d.ts +0 -3
- package/dist/umd/sync/registerSyncEvent.d.ts +0 -3
- package/dist/umd/sync/sync.d.ts +0 -15
- package/dist/umd/sync/syncIfPossible.d.ts +0 -5
- package/dist/umd/sync/syncWithServer.d.ts +0 -6
- package/dist/umd/sync/triggerSync.d.ts +0 -2
- package/dist/umd/sync/updateBaseRevs.d.ts +0 -5
- package/dist/umd/types/DXCAlert.d.ts +0 -25
- package/dist/umd/types/DXCInputField.d.ts +0 -11
- package/dist/umd/types/DXCUserInteraction.d.ts +0 -93
- package/dist/umd/types/NewIdOptions.d.ts +0 -3
- package/dist/umd/types/SWMessageEvent.d.ts +0 -3
- package/dist/umd/types/SWSyncEvent.d.ts +0 -4
- package/dist/umd/types/SyncState.d.ts +0 -9
- package/dist/umd/types/TXExpandos.d.ts +0 -11
- package/dist/umd/updateSchemaFromOptions.d.ts +0 -3
- package/dist/umd/userIsActive.d.ts +0 -7
- package/dist/umd/verifyConfig.d.ts +0 -2
- package/dist/umd/verifySchema.d.ts +0 -2
- package/dist/umd/yjs/YDexieCloudSyncState.d.ts +0 -3
- package/dist/umd/yjs/YTable.d.ts +0 -3
- package/dist/umd/yjs/applyYMessages.d.ts +0 -9
- package/dist/umd/yjs/awareness.d.ts +0 -3
- package/dist/umd/yjs/createYClientUpdateObservable.d.ts +0 -4
- package/dist/umd/yjs/createYHandler.d.ts +0 -2
- package/dist/umd/yjs/downloadYDocsFromServer.d.ts +0 -3
- package/dist/umd/yjs/getUpdatesTable.d.ts +0 -3
- package/dist/umd/yjs/listUpdatesSince.d.ts +0 -3
- package/dist/umd/yjs/listYClientMessagesAndStateVector.d.ts +0 -26
- package/dist/umd/yjs/reopenDocSignal.d.ts +0 -10
- package/dist/umd/yjs/updateYSyncStates.d.ts +0 -6
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* ==========================================================================
|
|
10
10
|
*
|
|
11
|
-
* Version 4.4.
|
|
11
|
+
* Version 4.4.7, Fri Mar 27 2026
|
|
12
12
|
*
|
|
13
13
|
* https://dexie.org
|
|
14
14
|
*
|
|
@@ -104,12 +104,12 @@
|
|
|
104
104
|
};
|
|
105
105
|
|
|
106
106
|
const UNAUTHORIZED_USER = {
|
|
107
|
-
userId:
|
|
108
|
-
name:
|
|
107
|
+
userId: 'unauthorized',
|
|
108
|
+
name: 'Unauthorized',
|
|
109
109
|
claims: {
|
|
110
|
-
sub:
|
|
110
|
+
sub: 'unauthorized',
|
|
111
111
|
},
|
|
112
|
-
lastLogin: new Date(0)
|
|
112
|
+
lastLogin: new Date(0),
|
|
113
113
|
};
|
|
114
114
|
try {
|
|
115
115
|
Object.freeze(UNAUTHORIZED_USER);
|
|
@@ -118,8 +118,10 @@
|
|
|
118
118
|
catch (_a) { }
|
|
119
119
|
|
|
120
120
|
const swHolder = {};
|
|
121
|
-
const swContainer = typeof self !== 'undefined' &&
|
|
122
|
-
|
|
121
|
+
const swContainer = typeof self !== 'undefined' &&
|
|
122
|
+
self.document && // self.document is to verify we're not the SW ourself
|
|
123
|
+
typeof navigator !== 'undefined' &&
|
|
124
|
+
navigator.serviceWorker;
|
|
123
125
|
if (swContainer)
|
|
124
126
|
swContainer.ready.then((registration) => (swHolder.registration = registration));
|
|
125
127
|
if (typeof self !== 'undefined' && 'clients' in self && !self.document) {
|
|
@@ -173,7 +175,8 @@
|
|
|
173
175
|
}
|
|
174
176
|
}
|
|
175
177
|
|
|
176
|
-
const events = globalThis['lbc-events'] ||
|
|
178
|
+
const events = globalThis['lbc-events'] ||
|
|
179
|
+
(globalThis['lbc-events'] = new Map());
|
|
177
180
|
function addListener(name, listener) {
|
|
178
181
|
if (events.has(name)) {
|
|
179
182
|
events.get(name).push(listener);
|
|
@@ -194,25 +197,25 @@
|
|
|
194
197
|
function dispatch(ev) {
|
|
195
198
|
const listeners = events.get(ev.type);
|
|
196
199
|
if (listeners) {
|
|
197
|
-
listeners.forEach(listener => {
|
|
200
|
+
listeners.forEach((listener) => {
|
|
198
201
|
try {
|
|
199
202
|
listener(ev);
|
|
200
203
|
}
|
|
201
|
-
catch (_a) {
|
|
202
|
-
}
|
|
204
|
+
catch (_a) { }
|
|
203
205
|
});
|
|
204
206
|
}
|
|
205
207
|
}
|
|
206
208
|
class BroadcastedAndLocalEvent extends rxjs.Observable {
|
|
207
209
|
constructor(name) {
|
|
208
|
-
const bc = typeof BroadcastChannel ===
|
|
209
|
-
? new SWBroadcastChannel(name)
|
|
210
|
-
|
|
210
|
+
const bc = typeof BroadcastChannel === 'undefined'
|
|
211
|
+
? new SWBroadcastChannel(name)
|
|
212
|
+
: new BroadcastChannel(name);
|
|
213
|
+
super((subscriber) => {
|
|
211
214
|
function onCustomEvent(ev) {
|
|
212
215
|
subscriber.next(ev.detail);
|
|
213
216
|
}
|
|
214
217
|
function onMessageEvent(ev) {
|
|
215
|
-
console.debug(
|
|
218
|
+
console.debug('BroadcastedAndLocalEvent: onMessageEvent', ev);
|
|
216
219
|
subscriber.next(ev.data);
|
|
217
220
|
}
|
|
218
221
|
let unsubscribe;
|
|
@@ -220,11 +223,11 @@
|
|
|
220
223
|
addListener(`lbc-${name}`, onCustomEvent); // Works better in service worker
|
|
221
224
|
try {
|
|
222
225
|
if (bc instanceof SWBroadcastChannel) {
|
|
223
|
-
unsubscribe = bc.subscribe(message => subscriber.next(message));
|
|
226
|
+
unsubscribe = bc.subscribe((message) => subscriber.next(message));
|
|
224
227
|
}
|
|
225
228
|
else {
|
|
226
|
-
console.debug(
|
|
227
|
-
bc.addEventListener(
|
|
229
|
+
console.debug('BroadcastedAndLocalEvent: bc.addEventListener()', name, 'bc is a', bc);
|
|
230
|
+
bc.addEventListener('message', onMessageEvent);
|
|
228
231
|
}
|
|
229
232
|
}
|
|
230
233
|
catch (err) {
|
|
@@ -238,7 +241,7 @@
|
|
|
238
241
|
unsubscribe();
|
|
239
242
|
}
|
|
240
243
|
else {
|
|
241
|
-
bc.removeEventListener(
|
|
244
|
+
bc.removeEventListener('message', onMessageEvent);
|
|
242
245
|
}
|
|
243
246
|
};
|
|
244
247
|
});
|
|
@@ -246,7 +249,7 @@
|
|
|
246
249
|
this.bc = bc;
|
|
247
250
|
}
|
|
248
251
|
next(message) {
|
|
249
|
-
console.debug(
|
|
252
|
+
console.debug('BroadcastedAndLocalEvent: bc.postMessage()', Object.assign({}, message), 'bc is a', this.bc);
|
|
250
253
|
this.bc.postMessage(message);
|
|
251
254
|
const ev = new CustomEvent(`lbc-${this.name}`, { detail: message });
|
|
252
255
|
//self.dispatchEvent(ev);
|
|
@@ -261,7 +264,7 @@
|
|
|
261
264
|
try {
|
|
262
265
|
// Send sync event to SW:
|
|
263
266
|
const sw = yield navigator.serviceWorker.ready;
|
|
264
|
-
if (purpose ===
|
|
267
|
+
if (purpose === 'push' && sw.sync) {
|
|
265
268
|
yield sw.sync.register(`dexie-cloud:${db.name}`);
|
|
266
269
|
}
|
|
267
270
|
if (sw.active) {
|
|
@@ -270,7 +273,7 @@
|
|
|
270
273
|
sw.active.postMessage({
|
|
271
274
|
type: 'dexie-cloud-sync',
|
|
272
275
|
dbName: db.name,
|
|
273
|
-
purpose
|
|
276
|
+
purpose,
|
|
274
277
|
});
|
|
275
278
|
}
|
|
276
279
|
else {
|
|
@@ -330,7 +333,7 @@
|
|
|
330
333
|
const keys = Object.keys(value);
|
|
331
334
|
let dollarKeys = null;
|
|
332
335
|
for (let i = 0, l = keys.length; i < l; ++i) {
|
|
333
|
-
if (keys[i][0] ===
|
|
336
|
+
if (keys[i][0] === '$') {
|
|
334
337
|
dollarKeys = dollarKeys || [];
|
|
335
338
|
dollarKeys.push(keys[i]);
|
|
336
339
|
}
|
|
@@ -342,7 +345,7 @@
|
|
|
342
345
|
delete clone[k];
|
|
343
346
|
}
|
|
344
347
|
for (const k of dollarKeys) {
|
|
345
|
-
clone[
|
|
348
|
+
clone['$' + k] = value[k];
|
|
346
349
|
}
|
|
347
350
|
return clone;
|
|
348
351
|
}
|
|
@@ -393,7 +396,7 @@
|
|
|
393
396
|
//
|
|
394
397
|
// Child part
|
|
395
398
|
//
|
|
396
|
-
if (value === undefined || (key[0] ===
|
|
399
|
+
if (value === undefined || (key[0] === '$' && key !== '$t')) {
|
|
397
400
|
top = stack[stack.length - 1];
|
|
398
401
|
let deletes;
|
|
399
402
|
let mods;
|
|
@@ -404,7 +407,7 @@
|
|
|
404
407
|
else {
|
|
405
408
|
stack.push([this, (deletes = []), (mods = {})]);
|
|
406
409
|
}
|
|
407
|
-
if (key[0] ===
|
|
410
|
+
if (key[0] === '$' && key !== '$t') {
|
|
408
411
|
// Unescape props (also preserves undefined if this is a combo)
|
|
409
412
|
deletes.push(key);
|
|
410
413
|
mods[key.substr(1)] = value;
|
|
@@ -421,8 +424,8 @@
|
|
|
421
424
|
function getTypeDef(realVal) {
|
|
422
425
|
const type = typeof realVal;
|
|
423
426
|
switch (typeof realVal) {
|
|
424
|
-
case
|
|
425
|
-
case
|
|
427
|
+
case 'object':
|
|
428
|
+
case 'function': {
|
|
426
429
|
// "object", "function", null
|
|
427
430
|
if (realVal === null)
|
|
428
431
|
return null;
|
|
@@ -438,7 +441,7 @@
|
|
|
438
441
|
if (!typeDef) {
|
|
439
442
|
typeDef = Array.isArray(realVal)
|
|
440
443
|
? null
|
|
441
|
-
: typeof realVal ===
|
|
444
|
+
: typeof realVal === 'function'
|
|
442
445
|
? typeDefs.function || null
|
|
443
446
|
: ObjectDef;
|
|
444
447
|
}
|
|
@@ -614,13 +617,13 @@
|
|
|
614
617
|
|
|
615
618
|
function readBlobSync(b) {
|
|
616
619
|
const req = new XMLHttpRequest();
|
|
617
|
-
req.overrideMimeType(
|
|
620
|
+
req.overrideMimeType('text/plain; charset=x-user-defined');
|
|
618
621
|
const url = URL.createObjectURL(b);
|
|
619
622
|
try {
|
|
620
|
-
req.open(
|
|
623
|
+
req.open('GET', url, false); // Sync
|
|
621
624
|
req.send();
|
|
622
625
|
if (req.status !== 200 && req.status !== 0) {
|
|
623
|
-
throw new Error(
|
|
626
|
+
throw new Error('Bad Blob access: ' + req.status);
|
|
624
627
|
}
|
|
625
628
|
return req.responseText;
|
|
626
629
|
}
|
|
@@ -634,11 +637,11 @@
|
|
|
634
637
|
replace: (num) => {
|
|
635
638
|
switch (true) {
|
|
636
639
|
case isNaN(num):
|
|
637
|
-
return { $t:
|
|
640
|
+
return { $t: 'number', v: 'NaN' };
|
|
638
641
|
case num === Infinity:
|
|
639
|
-
return { $t:
|
|
642
|
+
return { $t: 'number', v: 'Infinity' };
|
|
640
643
|
case num === -Infinity:
|
|
641
|
-
return { $t:
|
|
644
|
+
return { $t: 'number', v: '-Infinity' };
|
|
642
645
|
default:
|
|
643
646
|
return num;
|
|
644
647
|
}
|
|
@@ -650,17 +653,17 @@
|
|
|
650
653
|
const dateTypeDef = {
|
|
651
654
|
Date: {
|
|
652
655
|
replace: (date) => ({
|
|
653
|
-
$t:
|
|
654
|
-
v: isNaN(date.getTime()) ?
|
|
656
|
+
$t: 'Date',
|
|
657
|
+
v: isNaN(date.getTime()) ? 'NaN' : date.toISOString(),
|
|
655
658
|
}),
|
|
656
|
-
revive: ({ v }) => new Date(v ===
|
|
659
|
+
revive: ({ v }) => new Date(v === 'NaN' ? NaN : Date.parse(v)),
|
|
657
660
|
},
|
|
658
661
|
};
|
|
659
662
|
|
|
660
663
|
const setTypeDef = {
|
|
661
664
|
Set: {
|
|
662
665
|
replace: (set) => ({
|
|
663
|
-
$t:
|
|
666
|
+
$t: 'Set',
|
|
664
667
|
v: Array.from(set),
|
|
665
668
|
}),
|
|
666
669
|
revive: ({ v }) => new Set(v),
|
|
@@ -670,34 +673,34 @@
|
|
|
670
673
|
const mapTypeDef = {
|
|
671
674
|
Map: {
|
|
672
675
|
replace: (map) => ({
|
|
673
|
-
$t:
|
|
676
|
+
$t: 'Map',
|
|
674
677
|
v: Array.from(map.entries()),
|
|
675
678
|
}),
|
|
676
679
|
revive: ({ v }) => new Map(v),
|
|
677
680
|
},
|
|
678
681
|
};
|
|
679
682
|
|
|
680
|
-
const _global = typeof globalThis !==
|
|
683
|
+
const _global = typeof globalThis !== 'undefined' // All modern environments (node, bun, deno, browser, workers, webview etc)
|
|
681
684
|
? globalThis
|
|
682
|
-
: typeof self !==
|
|
685
|
+
: typeof self !== 'undefined' // Older browsers, workers, webview, window etc
|
|
683
686
|
? self
|
|
684
|
-
: typeof global !==
|
|
687
|
+
: typeof global !== 'undefined' // Older versions of node
|
|
685
688
|
? global
|
|
686
689
|
: undefined; // Unsupported environment. No idea to return 'this' since we are in a module or a function scope anyway.
|
|
687
690
|
|
|
688
691
|
const typedArrayTypeDefs = [
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
692
|
+
'Int8Array',
|
|
693
|
+
'Uint8Array',
|
|
694
|
+
'Uint8ClampedArray',
|
|
695
|
+
'Int16Array',
|
|
696
|
+
'Uint16Array',
|
|
697
|
+
'Int32Array',
|
|
698
|
+
'Uint32Array',
|
|
699
|
+
'Float32Array',
|
|
700
|
+
'Float64Array',
|
|
701
|
+
'DataView',
|
|
702
|
+
'BigInt64Array',
|
|
703
|
+
'BigUint64Array',
|
|
701
704
|
].reduce((specs, typeName) => ({
|
|
702
705
|
...specs,
|
|
703
706
|
[typeName]: {
|
|
@@ -725,10 +728,10 @@
|
|
|
725
728
|
},
|
|
726
729
|
}), {});
|
|
727
730
|
|
|
728
|
-
const hasArrayBufferFromBase64 =
|
|
729
|
-
const hasArrayBufferToBase64 =
|
|
730
|
-
const b64decode = typeof Buffer !==
|
|
731
|
-
? (base64) => Buffer.from(base64,
|
|
731
|
+
const hasArrayBufferFromBase64 = 'fromBase64' in Uint8Array; // https://github.com/tc39/proposal-arraybuffer-base64;
|
|
732
|
+
const hasArrayBufferToBase64 = 'toBase64' in Uint8Array.prototype; // https://github.com/tc39/proposal-arraybuffer-base64;
|
|
733
|
+
const b64decode = typeof Buffer !== 'undefined'
|
|
734
|
+
? (base64) => Buffer.from(base64, 'base64') // Node
|
|
732
735
|
: hasArrayBufferFromBase64
|
|
733
736
|
? // @ts-ignore: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array/fromBase64
|
|
734
737
|
(base64) => Uint8Array.fromBase64(base64) // Modern javascript standard
|
|
@@ -742,14 +745,14 @@
|
|
|
742
745
|
}
|
|
743
746
|
return bytes;
|
|
744
747
|
};
|
|
745
|
-
const b64encode = typeof Buffer !==
|
|
748
|
+
const b64encode = typeof Buffer !== 'undefined'
|
|
746
749
|
? (b) => {
|
|
747
750
|
// Node
|
|
748
751
|
if (ArrayBuffer.isView(b)) {
|
|
749
|
-
return Buffer.from(b.buffer, b.byteOffset, b.byteLength).toString(
|
|
752
|
+
return Buffer.from(b.buffer, b.byteOffset, b.byteLength).toString('base64');
|
|
750
753
|
}
|
|
751
754
|
else {
|
|
752
|
-
return Buffer.from(b).toString(
|
|
755
|
+
return Buffer.from(b).toString('base64');
|
|
753
756
|
}
|
|
754
757
|
}
|
|
755
758
|
: hasArrayBufferToBase64
|
|
@@ -768,7 +771,7 @@
|
|
|
768
771
|
const chunk = u8a.subarray(i, i + CHUNK_SIZE);
|
|
769
772
|
strs.push(String.fromCharCode.apply(null, Array.from(chunk)));
|
|
770
773
|
}
|
|
771
|
-
return btoa(strs.join(
|
|
774
|
+
return btoa(strs.join(''));
|
|
772
775
|
};
|
|
773
776
|
|
|
774
777
|
function b64LexEncode(b) {
|
|
@@ -778,7 +781,7 @@
|
|
|
778
781
|
return b64decode(lexToB64(b64Lex));
|
|
779
782
|
}
|
|
780
783
|
function b64ToLex(base64) {
|
|
781
|
-
var encoded =
|
|
784
|
+
var encoded = '';
|
|
782
785
|
for (var i = 0, length = base64.length; i < length; i++) {
|
|
783
786
|
encoded += ENCODE_TABLE[base64[i]];
|
|
784
787
|
}
|
|
@@ -786,81 +789,81 @@
|
|
|
786
789
|
}
|
|
787
790
|
function lexToB64(base64lex) {
|
|
788
791
|
// only accept string input
|
|
789
|
-
if (typeof base64lex !==
|
|
790
|
-
throw new Error(
|
|
792
|
+
if (typeof base64lex !== 'string') {
|
|
793
|
+
throw new Error('invalid decoder input: ' + base64lex);
|
|
791
794
|
}
|
|
792
|
-
var base64 =
|
|
795
|
+
var base64 = '';
|
|
793
796
|
for (var i = 0, length = base64lex.length; i < length; i++) {
|
|
794
797
|
base64 += DECODE_TABLE[base64lex[i]];
|
|
795
798
|
}
|
|
796
799
|
return base64;
|
|
797
800
|
}
|
|
798
801
|
const DECODE_TABLE = {
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
A:
|
|
811
|
-
B:
|
|
812
|
-
C:
|
|
813
|
-
D:
|
|
814
|
-
E:
|
|
815
|
-
F:
|
|
816
|
-
G:
|
|
817
|
-
H:
|
|
818
|
-
I:
|
|
819
|
-
J:
|
|
820
|
-
K:
|
|
821
|
-
L:
|
|
822
|
-
M:
|
|
823
|
-
N:
|
|
824
|
-
O:
|
|
825
|
-
P:
|
|
826
|
-
Q:
|
|
827
|
-
R:
|
|
828
|
-
S:
|
|
829
|
-
T:
|
|
830
|
-
U:
|
|
831
|
-
V:
|
|
832
|
-
W:
|
|
833
|
-
X:
|
|
834
|
-
Y:
|
|
835
|
-
Z:
|
|
836
|
-
_:
|
|
837
|
-
a:
|
|
838
|
-
b:
|
|
839
|
-
c:
|
|
840
|
-
d:
|
|
841
|
-
e:
|
|
842
|
-
f:
|
|
843
|
-
g:
|
|
844
|
-
h:
|
|
845
|
-
i:
|
|
846
|
-
j:
|
|
847
|
-
k:
|
|
848
|
-
l:
|
|
849
|
-
m:
|
|
850
|
-
n:
|
|
851
|
-
o:
|
|
852
|
-
p:
|
|
853
|
-
q:
|
|
854
|
-
r:
|
|
855
|
-
s:
|
|
856
|
-
t:
|
|
857
|
-
u:
|
|
858
|
-
v:
|
|
859
|
-
w:
|
|
860
|
-
x:
|
|
861
|
-
y:
|
|
862
|
-
z:
|
|
863
|
-
|
|
802
|
+
'-': '=',
|
|
803
|
+
'0': 'A',
|
|
804
|
+
'1': 'B',
|
|
805
|
+
'2': 'C',
|
|
806
|
+
'3': 'D',
|
|
807
|
+
'4': 'E',
|
|
808
|
+
'5': 'F',
|
|
809
|
+
'6': 'G',
|
|
810
|
+
'7': 'H',
|
|
811
|
+
'8': 'I',
|
|
812
|
+
'9': 'J',
|
|
813
|
+
A: 'K',
|
|
814
|
+
B: 'L',
|
|
815
|
+
C: 'M',
|
|
816
|
+
D: 'N',
|
|
817
|
+
E: 'O',
|
|
818
|
+
F: 'P',
|
|
819
|
+
G: 'Q',
|
|
820
|
+
H: 'R',
|
|
821
|
+
I: 'S',
|
|
822
|
+
J: 'T',
|
|
823
|
+
K: 'U',
|
|
824
|
+
L: 'V',
|
|
825
|
+
M: 'W',
|
|
826
|
+
N: 'X',
|
|
827
|
+
O: 'Y',
|
|
828
|
+
P: 'Z',
|
|
829
|
+
Q: 'a',
|
|
830
|
+
R: 'b',
|
|
831
|
+
S: 'c',
|
|
832
|
+
T: 'd',
|
|
833
|
+
U: 'e',
|
|
834
|
+
V: 'f',
|
|
835
|
+
W: 'g',
|
|
836
|
+
X: 'h',
|
|
837
|
+
Y: 'i',
|
|
838
|
+
Z: 'j',
|
|
839
|
+
_: 'k',
|
|
840
|
+
a: 'l',
|
|
841
|
+
b: 'm',
|
|
842
|
+
c: 'n',
|
|
843
|
+
d: 'o',
|
|
844
|
+
e: 'p',
|
|
845
|
+
f: 'q',
|
|
846
|
+
g: 'r',
|
|
847
|
+
h: 's',
|
|
848
|
+
i: 't',
|
|
849
|
+
j: 'u',
|
|
850
|
+
k: 'v',
|
|
851
|
+
l: 'w',
|
|
852
|
+
m: 'x',
|
|
853
|
+
n: 'y',
|
|
854
|
+
o: 'z',
|
|
855
|
+
p: '0',
|
|
856
|
+
q: '1',
|
|
857
|
+
r: '2',
|
|
858
|
+
s: '3',
|
|
859
|
+
t: '4',
|
|
860
|
+
u: '5',
|
|
861
|
+
v: '6',
|
|
862
|
+
w: '7',
|
|
863
|
+
x: '8',
|
|
864
|
+
y: '9',
|
|
865
|
+
z: '+',
|
|
866
|
+
'|': '/',
|
|
864
867
|
};
|
|
865
868
|
const ENCODE_TABLE = {};
|
|
866
869
|
for (const c of Object.keys(DECODE_TABLE)) {
|
|
@@ -870,7 +873,7 @@
|
|
|
870
873
|
const arrayBufferTypeDef = {
|
|
871
874
|
ArrayBuffer: {
|
|
872
875
|
replace: (ab) => ({
|
|
873
|
-
$t:
|
|
876
|
+
$t: 'ArrayBuffer',
|
|
874
877
|
v: b64LexEncode(ab),
|
|
875
878
|
}),
|
|
876
879
|
revive: ({ v }) => {
|
|
@@ -893,9 +896,9 @@
|
|
|
893
896
|
|
|
894
897
|
const blobTypeDef = {
|
|
895
898
|
Blob: {
|
|
896
|
-
test: (blob, toStringTag) => toStringTag ===
|
|
899
|
+
test: (blob, toStringTag) => toStringTag === 'Blob' || blob instanceof FakeBlob,
|
|
897
900
|
replace: (blob) => ({
|
|
898
|
-
$t:
|
|
901
|
+
$t: 'Blob',
|
|
899
902
|
v: blob instanceof FakeBlob
|
|
900
903
|
? b64encode(blob.buf)
|
|
901
904
|
: b64encode(string2ArrayBuffer(readBlobSync(blob))),
|
|
@@ -906,7 +909,7 @@
|
|
|
906
909
|
const buf = ab.buffer.byteLength === ab.byteLength
|
|
907
910
|
? ab.buffer
|
|
908
911
|
: ab.buffer.slice(ab.byteOffset, ab.byteOffset + ab.byteLength);
|
|
909
|
-
return typeof Blob !==
|
|
912
|
+
return typeof Blob !== 'undefined'
|
|
910
913
|
? new Blob([new Uint8Array(buf)], { type })
|
|
911
914
|
: new FakeBlob(buf, type);
|
|
912
915
|
},
|
|
@@ -925,15 +928,15 @@
|
|
|
925
928
|
|
|
926
929
|
const fileTypeDef = {
|
|
927
930
|
File: {
|
|
928
|
-
test: (file, toStringTag) => toStringTag ===
|
|
931
|
+
test: (file, toStringTag) => toStringTag === 'File',
|
|
929
932
|
replace: (file) => ({
|
|
930
|
-
$t:
|
|
933
|
+
$t: 'File',
|
|
931
934
|
v: b64encode(string2ArrayBuffer(readBlobSync(file))),
|
|
932
935
|
type: file.type,
|
|
933
936
|
name: file.name,
|
|
934
937
|
lastModified: new Date(file.lastModified).toISOString(),
|
|
935
938
|
}),
|
|
936
|
-
revive: ({ type, v, name, lastModified }) => {
|
|
939
|
+
revive: ({ type, v, name, lastModified, }) => {
|
|
937
940
|
const ab = b64decode(v);
|
|
938
941
|
const buf = ab.buffer.byteLength === ab.byteLength
|
|
939
942
|
? ab.buffer
|
|
@@ -957,13 +960,13 @@
|
|
|
957
960
|
const undefinedTypeDef = {
|
|
958
961
|
undefined: {
|
|
959
962
|
replace: () => ({
|
|
960
|
-
$t:
|
|
963
|
+
$t: 'undefined',
|
|
961
964
|
}),
|
|
962
965
|
revive: () => undefined,
|
|
963
966
|
},
|
|
964
967
|
};
|
|
965
968
|
|
|
966
|
-
const getRandomValues$1 = typeof crypto !==
|
|
969
|
+
const getRandomValues$1 = typeof crypto !== 'undefined'
|
|
967
970
|
? crypto.getRandomValues.bind(crypto)
|
|
968
971
|
: (buf) => {
|
|
969
972
|
for (let i = 0; i < buf.length; ++i) {
|
|
@@ -1064,7 +1067,7 @@
|
|
|
1064
1067
|
var innerObj = obj[currentKeyPath];
|
|
1065
1068
|
//@ts-ignore: even if currentKeyPath would be numeric string and obj would be array - it works.
|
|
1066
1069
|
if (!innerObj || !hasOwn(obj, currentKeyPath))
|
|
1067
|
-
innerObj =
|
|
1070
|
+
innerObj = obj[currentKeyPath] = {};
|
|
1068
1071
|
setByKeyPath(innerObj, remainingKeyPath, value);
|
|
1069
1072
|
}
|
|
1070
1073
|
}
|
|
@@ -1083,17 +1086,23 @@
|
|
|
1083
1086
|
}
|
|
1084
1087
|
}
|
|
1085
1088
|
}
|
|
1086
|
-
const randomString$1 = typeof self !== 'undefined' && typeof crypto !== 'undefined'
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1089
|
+
const randomString$1 = typeof self !== 'undefined' && typeof crypto !== 'undefined'
|
|
1090
|
+
? (bytes, randomFill = crypto.getRandomValues.bind(crypto)) => {
|
|
1091
|
+
// Web
|
|
1092
|
+
const buf = new Uint8Array(bytes);
|
|
1093
|
+
randomFill(buf);
|
|
1094
|
+
return self.btoa(String.fromCharCode.apply(null, buf));
|
|
1095
|
+
}
|
|
1096
|
+
: typeof Buffer !== 'undefined'
|
|
1097
|
+
? (bytes, randomFill = simpleRandomFill) => {
|
|
1098
|
+
// Node
|
|
1099
|
+
const buf = Buffer.alloc(bytes);
|
|
1100
|
+
randomFill(buf);
|
|
1101
|
+
return buf.toString('base64');
|
|
1102
|
+
}
|
|
1103
|
+
: () => {
|
|
1104
|
+
throw new Error('No implementation of randomString was found');
|
|
1105
|
+
};
|
|
1097
1106
|
function simpleRandomFill(buf) {
|
|
1098
1107
|
for (let i = 0; i < buf.length; ++i) {
|
|
1099
1108
|
buf[i] = Math.floor(Math.random() * 256);
|
|
@@ -1112,11 +1121,13 @@
|
|
|
1112
1121
|
* @returns
|
|
1113
1122
|
*/
|
|
1114
1123
|
function isValidSyncableID(id) {
|
|
1115
|
-
if (typeof id ===
|
|
1124
|
+
if (typeof id === 'string')
|
|
1116
1125
|
return true;
|
|
1117
1126
|
//if (validIDTypes[toStringTag(id)]) return true;
|
|
1118
1127
|
//if (Array.isArray(id)) return id.every((part) => isValidSyncableID(part));
|
|
1119
|
-
if (Array.isArray(id) &&
|
|
1128
|
+
if (Array.isArray(id) &&
|
|
1129
|
+
id.some((key) => isValidSyncableID(key)) &&
|
|
1130
|
+
id.every(isValidSyncableIDPart))
|
|
1120
1131
|
return true;
|
|
1121
1132
|
return false;
|
|
1122
1133
|
}
|
|
@@ -1125,53 +1136,53 @@
|
|
|
1125
1136
|
* For example, ArrayBuffer cannot be used (gives "object ArrayBuffer") but Uint8Array can be
|
|
1126
1137
|
* used (gives comma-delimited list of included bytes).
|
|
1127
1138
|
* 2: Since we store the key as a VARCHAR server side in current version, try not promote types that stringifies to become very long server side.
|
|
1128
|
-
|
|
1139
|
+
*/
|
|
1129
1140
|
function isValidSyncableIDPart(part) {
|
|
1130
|
-
return typeof part ===
|
|
1141
|
+
return (typeof part === 'string' ||
|
|
1142
|
+
typeof part === 'number' ||
|
|
1143
|
+
(Array.isArray(part) && part.every(isValidSyncableIDPart)));
|
|
1131
1144
|
}
|
|
1132
1145
|
function isValidAtID(id, idPrefix) {
|
|
1133
|
-
return !idPrefix || (typeof id ===
|
|
1146
|
+
return !idPrefix || (typeof id === 'string' && id.startsWith(idPrefix));
|
|
1134
1147
|
}
|
|
1135
1148
|
|
|
1136
1149
|
function applyOperation(target, table, op) {
|
|
1137
1150
|
const tbl = target[table] || (target[table] = {});
|
|
1138
|
-
const keys = op.keys.map(key => typeof key === 'string' ? key : JSON.stringify(key));
|
|
1151
|
+
const keys = op.keys.map((key) => typeof key === 'string' ? key : JSON.stringify(key));
|
|
1139
1152
|
switch (op.type) {
|
|
1140
|
-
case
|
|
1153
|
+
case 'insert':
|
|
1141
1154
|
// TODO: Don't treat insert and upsert the same?
|
|
1142
|
-
case
|
|
1155
|
+
case 'upsert':
|
|
1143
1156
|
keys.forEach((key, idx) => {
|
|
1144
1157
|
tbl[key] = {
|
|
1145
|
-
type:
|
|
1158
|
+
type: 'ups',
|
|
1146
1159
|
val: op.values[idx],
|
|
1147
1160
|
};
|
|
1148
1161
|
});
|
|
1149
1162
|
break;
|
|
1150
|
-
case
|
|
1151
|
-
case
|
|
1163
|
+
case 'update':
|
|
1164
|
+
case 'modify': {
|
|
1152
1165
|
keys.forEach((key, idx) => {
|
|
1153
|
-
const changeSpec = op.type ===
|
|
1154
|
-
? op.changeSpecs[idx]
|
|
1155
|
-
: op.changeSpec;
|
|
1166
|
+
const changeSpec = op.type === 'update' ? op.changeSpecs[idx] : op.changeSpec;
|
|
1156
1167
|
const entry = tbl[key];
|
|
1157
1168
|
if (!entry) {
|
|
1158
1169
|
tbl[key] = {
|
|
1159
|
-
type:
|
|
1170
|
+
type: 'upd',
|
|
1160
1171
|
mod: changeSpec,
|
|
1161
1172
|
};
|
|
1162
1173
|
}
|
|
1163
1174
|
else {
|
|
1164
1175
|
switch (entry.type) {
|
|
1165
|
-
case
|
|
1176
|
+
case 'ups':
|
|
1166
1177
|
// Adjust the existing upsert with additional updates
|
|
1167
1178
|
for (const [propPath, value] of Object.entries(changeSpec)) {
|
|
1168
1179
|
setByKeyPath(entry.val, propPath, value);
|
|
1169
1180
|
}
|
|
1170
1181
|
break;
|
|
1171
|
-
case
|
|
1182
|
+
case 'del':
|
|
1172
1183
|
// No action.
|
|
1173
1184
|
break;
|
|
1174
|
-
case
|
|
1185
|
+
case 'upd':
|
|
1175
1186
|
// Adjust existing update with additional updates
|
|
1176
1187
|
Object.assign(entry.mod, changeSpec); // May work for deep props as well - new keys is added later, right? Does the prop order persist along TSON and all? But it will not be 100% when combined with some server code (seach for "address.city": "Stockholm" comment)
|
|
1177
1188
|
break;
|
|
@@ -1180,10 +1191,10 @@
|
|
|
1180
1191
|
});
|
|
1181
1192
|
break;
|
|
1182
1193
|
}
|
|
1183
|
-
case
|
|
1194
|
+
case 'delete':
|
|
1184
1195
|
keys.forEach((key) => {
|
|
1185
1196
|
tbl[key] = {
|
|
1186
|
-
type:
|
|
1197
|
+
type: 'del',
|
|
1187
1198
|
};
|
|
1188
1199
|
});
|
|
1189
1200
|
break;
|
|
@@ -1280,30 +1291,30 @@
|
|
|
1280
1291
|
};
|
|
1281
1292
|
for (const [optype, muts] of Object.entries(ops)) {
|
|
1282
1293
|
switch (optype) {
|
|
1283
|
-
case
|
|
1294
|
+
case 'ups': {
|
|
1284
1295
|
const op = {
|
|
1285
|
-
type:
|
|
1286
|
-
keys: muts.map(mut => mut.key),
|
|
1287
|
-
values: muts.map(mut => mut.val),
|
|
1288
|
-
txid
|
|
1296
|
+
type: 'upsert',
|
|
1297
|
+
keys: muts.map((mut) => mut.key),
|
|
1298
|
+
values: muts.map((mut) => mut.val),
|
|
1299
|
+
txid,
|
|
1289
1300
|
};
|
|
1290
1301
|
resultEntry.muts.push(op);
|
|
1291
1302
|
break;
|
|
1292
1303
|
}
|
|
1293
|
-
case
|
|
1304
|
+
case 'upd': {
|
|
1294
1305
|
const op = {
|
|
1295
|
-
type:
|
|
1296
|
-
keys: muts.map(mut => mut.key),
|
|
1297
|
-
changeSpecs: muts.map(mut => mut.mod),
|
|
1298
|
-
txid
|
|
1306
|
+
type: 'update',
|
|
1307
|
+
keys: muts.map((mut) => mut.key),
|
|
1308
|
+
changeSpecs: muts.map((mut) => mut.mod),
|
|
1309
|
+
txid,
|
|
1299
1310
|
};
|
|
1300
1311
|
resultEntry.muts.push(op);
|
|
1301
1312
|
break;
|
|
1302
1313
|
}
|
|
1303
|
-
case
|
|
1314
|
+
case 'del': {
|
|
1304
1315
|
const op = {
|
|
1305
|
-
type:
|
|
1306
|
-
keys: muts.map(mut => mut.key),
|
|
1316
|
+
type: 'delete',
|
|
1317
|
+
keys: muts.map((mut) => mut.key),
|
|
1307
1318
|
txid,
|
|
1308
1319
|
};
|
|
1309
1320
|
resultEntry.muts.push(op);
|
|
@@ -1318,7 +1329,7 @@
|
|
|
1318
1329
|
|
|
1319
1330
|
function getDbNameFromDbUrl(dbUrl) {
|
|
1320
1331
|
const url = new URL(dbUrl);
|
|
1321
|
-
return url.pathname ===
|
|
1332
|
+
return url.pathname === '/'
|
|
1322
1333
|
? url.hostname.split('.')[0]
|
|
1323
1334
|
: url.pathname.split('/')[1];
|
|
1324
1335
|
}
|
|
@@ -2739,7 +2750,8 @@
|
|
|
2739
2750
|
prop,
|
|
2740
2751
|
k,
|
|
2741
2752
|
u: readVarUint8Array(decoder),
|
|
2742
|
-
r: (decoder.pos < decoder.arr.length && readVarString(decoder)) ||
|
|
2753
|
+
r: (decoder.pos < decoder.arr.length && readVarString(decoder)) ||
|
|
2754
|
+
undefined,
|
|
2743
2755
|
};
|
|
2744
2756
|
default:
|
|
2745
2757
|
throw new TypeError(`Unknown message type: ${type}`);
|
|
@@ -2756,7 +2768,8 @@
|
|
|
2756
2768
|
}
|
|
2757
2769
|
// Start running the machine. If the last stage is a sink, it will consume the data and never emit anything
|
|
2758
2770
|
// to us here...
|
|
2759
|
-
for await (const chunk of result) {
|
|
2771
|
+
for await (const chunk of result) {
|
|
2772
|
+
}
|
|
2760
2773
|
}
|
|
2761
2774
|
|
|
2762
2775
|
async function* consumeChunkedBinaryStream(source) {
|
|
@@ -2810,7 +2823,7 @@
|
|
|
2810
2823
|
}
|
|
2811
2824
|
if (pos + len > chunk.byteLength) {
|
|
2812
2825
|
bufs.push(chunk.slice(pos));
|
|
2813
|
-
len -=
|
|
2826
|
+
len -= chunk.byteLength - pos;
|
|
2814
2827
|
state = 2;
|
|
2815
2828
|
pos = chunk.byteLength; // will break while loop.
|
|
2816
2829
|
}
|
|
@@ -2841,7 +2854,7 @@
|
|
|
2841
2854
|
function getFetchResponseBodyGenerator(res) {
|
|
2842
2855
|
return async function* () {
|
|
2843
2856
|
if (!res.body)
|
|
2844
|
-
throw new Error(
|
|
2857
|
+
throw new Error('Response body is not readable');
|
|
2845
2858
|
const reader = res.body.getReader();
|
|
2846
2859
|
try {
|
|
2847
2860
|
while (true) {
|
|
@@ -2949,7 +2962,7 @@
|
|
|
2949
2962
|
}
|
|
2950
2963
|
const strKey = '' + mut.keys[0];
|
|
2951
2964
|
const changeSpecs = mut.changeSpecs[0];
|
|
2952
|
-
if (Object.values(changeSpecs).some(v => typeof v ===
|
|
2965
|
+
if (Object.values(changeSpecs).some((v) => typeof v === 'object' && v && '@@propmod' in v)) {
|
|
2953
2966
|
continue; // Cannot optimize if any PropModification is present
|
|
2954
2967
|
}
|
|
2955
2968
|
let keyCoverage = updateCoverage.get(strKey);
|
|
@@ -2957,11 +2970,13 @@
|
|
|
2957
2970
|
keyCoverage.push({ txid: mut.txid, updateSpec: changeSpecs });
|
|
2958
2971
|
}
|
|
2959
2972
|
else {
|
|
2960
|
-
updateCoverage.set(strKey, [
|
|
2973
|
+
updateCoverage.set(strKey, [
|
|
2974
|
+
{ txid: mut.txid, updateSpec: changeSpecs },
|
|
2975
|
+
]);
|
|
2961
2976
|
}
|
|
2962
2977
|
}
|
|
2963
2978
|
}
|
|
2964
|
-
muts = muts.filter(mut => {
|
|
2979
|
+
muts = muts.filter((mut) => {
|
|
2965
2980
|
// Only apply optimization to update mutations that are single-key
|
|
2966
2981
|
if (mut.type !== 'update')
|
|
2967
2982
|
return true;
|
|
@@ -2969,7 +2984,7 @@
|
|
|
2969
2984
|
return true;
|
|
2970
2985
|
// Check if this has PropModifications - if so, skip optimization
|
|
2971
2986
|
const changeSpecs = mut.changeSpecs[0];
|
|
2972
|
-
if (Object.values(changeSpecs).some(v => typeof v ===
|
|
2987
|
+
if (Object.values(changeSpecs).some((v) => typeof v === 'object' && v && '@@propmod' in v)) {
|
|
2973
2988
|
return true; // Cannot optimize if any PropModification is present
|
|
2974
2989
|
}
|
|
2975
2990
|
// Keep track of properties that aren't overlapped by later transactions
|
|
@@ -2997,7 +3012,7 @@
|
|
|
2997
3012
|
return muts;
|
|
2998
3013
|
}
|
|
2999
3014
|
function canonicalizeToUpdateOps(muts) {
|
|
3000
|
-
muts = muts.map(mut => {
|
|
3015
|
+
muts = muts.map((mut) => {
|
|
3001
3016
|
if (mut.type === 'modify' && mut.criteria.index === null) {
|
|
3002
3017
|
// The criteria is on primary key. Convert to an update operation instead.
|
|
3003
3018
|
// It is simpler for the server to handle and also more efficient.
|
|
@@ -3163,14 +3178,15 @@
|
|
|
3163
3178
|
// the domain extension like .com, .net, etc.
|
|
3164
3179
|
// (\sas\s[\w-+.]+@([\w-]+\.)+[\w-]{2,10})?$ : This part is optional (due to the ? at the end).
|
|
3165
3180
|
// If present, it matches " as " followed by another valid email address. This allows for the
|
|
3166
|
-
// input to be either a single email address or two email addresses separated by " as ".
|
|
3181
|
+
// input to be either a single email address or two email addresses separated by " as ".
|
|
3167
3182
|
//
|
|
3168
3183
|
// The use case for "<email1> as <email2>"" is for when a database owner with full access to the
|
|
3169
3184
|
// database needs to impersonate another user in the database in order to troubleshoot. This
|
|
3170
3185
|
// format will only be possible to use when email1 is the owner of an API client with GLOBAL_READ
|
|
3171
3186
|
// and GLOBAL_WRITE permissions on the database. The email will be checked on the server before
|
|
3172
3187
|
// allowing it and giving out a token for email2, using the OTP sent to email1.
|
|
3173
|
-
while (!email ||
|
|
3188
|
+
while (!email ||
|
|
3189
|
+
!/^[\w-+.]+@([\w-]+\.)+[\w-]{2,10}(\sas\s[\w-+.]+@([\w-]+\.)+[\w-]{2,10})?$/.test(email)) {
|
|
3174
3190
|
const alerts = [];
|
|
3175
3191
|
if (firstPrompt && initialAlert)
|
|
3176
3192
|
alerts.push(initialAlert);
|
|
@@ -3236,7 +3252,7 @@
|
|
|
3236
3252
|
messageParams: {
|
|
3237
3253
|
currentUserId,
|
|
3238
3254
|
numUnsyncedChanges: numUnsyncedChanges.toString(),
|
|
3239
|
-
}
|
|
3255
|
+
},
|
|
3240
3256
|
},
|
|
3241
3257
|
];
|
|
3242
3258
|
return yield interactWithUser(userInteraction, {
|
|
@@ -3245,7 +3261,7 @@
|
|
|
3245
3261
|
alerts,
|
|
3246
3262
|
fields: {},
|
|
3247
3263
|
submitLabel: 'Confirm logout',
|
|
3248
|
-
cancelLabel: 'Cancel'
|
|
3264
|
+
cancelLabel: 'Cancel',
|
|
3249
3265
|
})
|
|
3250
3266
|
.then(() => true)
|
|
3251
3267
|
.catch(() => false);
|
|
@@ -3362,7 +3378,8 @@
|
|
|
3362
3378
|
if (!accessToken)
|
|
3363
3379
|
return null;
|
|
3364
3380
|
const expTime = (_a = accessTokenExpiration === null || accessTokenExpiration === void 0 ? void 0 : accessTokenExpiration.getTime()) !== null && _a !== void 0 ? _a : Infinity;
|
|
3365
|
-
if (expTime >
|
|
3381
|
+
if (expTime > Date.now() + 5 * MINUTES &&
|
|
3382
|
+
(((_b = currentUser.license) === null || _b === void 0 ? void 0 : _b.status) || 'ok') === 'ok') {
|
|
3366
3383
|
return currentUser;
|
|
3367
3384
|
}
|
|
3368
3385
|
if (!refreshToken) {
|
|
@@ -3522,11 +3539,13 @@
|
|
|
3522
3539
|
}
|
|
3523
3540
|
catch (error) {
|
|
3524
3541
|
// OAuth redirect is not an error - page is navigating away
|
|
3525
|
-
if (error instanceof OAuthRedirectError ||
|
|
3542
|
+
if (error instanceof OAuthRedirectError ||
|
|
3543
|
+
(error === null || error === void 0 ? void 0 : error.name) === 'OAuthRedirectError') {
|
|
3526
3544
|
throw error; // Re-throw without logging
|
|
3527
3545
|
}
|
|
3528
3546
|
// Policy rejections have already been shown to the user as a challenge
|
|
3529
|
-
if (error instanceof PolicyRejectionError ||
|
|
3547
|
+
if (error instanceof PolicyRejectionError ||
|
|
3548
|
+
(error === null || error === void 0 ? void 0 : error.name) === 'PolicyRejectionError') {
|
|
3530
3549
|
throw error;
|
|
3531
3550
|
}
|
|
3532
3551
|
if (error instanceof TokenErrorResponseError) {
|
|
@@ -3545,7 +3564,10 @@
|
|
|
3545
3564
|
if (isOffline) {
|
|
3546
3565
|
message = `You seem to be offline. Please connect to the internet and try again.`;
|
|
3547
3566
|
}
|
|
3548
|
-
else if (typeof location !== 'undefined' &&
|
|
3567
|
+
else if (typeof location !== 'undefined' &&
|
|
3568
|
+
(Dexie.debug ||
|
|
3569
|
+
location.hostname === 'localhost' ||
|
|
3570
|
+
location.hostname === '127.0.0.1')) {
|
|
3549
3571
|
// The audience is most likely the developer. Suggest to whitelist the localhost origin:
|
|
3550
3572
|
const whitelistCommand = `npx dexie-cloud whitelist ${location.origin}`;
|
|
3551
3573
|
message = `Could not connect to server. Please verify that your origin '${location.origin}' is whitelisted using \`npx dexie-cloud whitelist\``;
|
|
@@ -3648,7 +3670,7 @@
|
|
|
3648
3670
|
this.httpStatus = res.status;
|
|
3649
3671
|
}
|
|
3650
3672
|
get name() {
|
|
3651
|
-
return
|
|
3673
|
+
return 'HttpError';
|
|
3652
3674
|
}
|
|
3653
3675
|
}
|
|
3654
3676
|
|
|
@@ -3725,7 +3747,7 @@
|
|
|
3725
3747
|
const delatMilliseconds = ((_b = (_a = syncRatelimitDelays.get(db)) === null || _a === void 0 ? void 0 : _a.getTime()) !== null && _b !== void 0 ? _b : 0) - Date.now();
|
|
3726
3748
|
if (delatMilliseconds > 0) {
|
|
3727
3749
|
console.debug(`Stalling sync request ${delatMilliseconds} ms to spare ratelimits`);
|
|
3728
|
-
yield new Promise(resolve => setTimeout(resolve, delatMilliseconds));
|
|
3750
|
+
yield new Promise((resolve) => setTimeout(resolve, delatMilliseconds));
|
|
3729
3751
|
}
|
|
3730
3752
|
});
|
|
3731
3753
|
}
|
|
@@ -3790,7 +3812,7 @@
|
|
|
3790
3812
|
baseRevs,
|
|
3791
3813
|
changes: encodeIdsForServer(db.dx.core.schema, currentUser, changes),
|
|
3792
3814
|
y,
|
|
3793
|
-
dxcv: db.cloud.version
|
|
3815
|
+
dxcv: db.cloud.version,
|
|
3794
3816
|
};
|
|
3795
3817
|
console.debug('Sync request', syncRequest);
|
|
3796
3818
|
db.syncStateChangedEvent.next({
|
|
@@ -3830,19 +3852,22 @@
|
|
|
3830
3852
|
return __awaiter(this, void 0, void 0, function* () {
|
|
3831
3853
|
const ignoredRealms = new Set(alreadySyncedRealms || []);
|
|
3832
3854
|
for (const table of syncifiedTables) {
|
|
3833
|
-
if (table.name ===
|
|
3855
|
+
if (table.name === 'members') {
|
|
3834
3856
|
// members
|
|
3835
3857
|
yield table.toCollection().modify((member) => {
|
|
3836
|
-
if (!ignoredRealms.has(member.realmId) &&
|
|
3858
|
+
if (!ignoredRealms.has(member.realmId) &&
|
|
3859
|
+
(!member.userId || member.userId === UNAUTHORIZED_USER.userId)) {
|
|
3837
3860
|
member.userId = currentUser.userId;
|
|
3838
3861
|
}
|
|
3839
3862
|
});
|
|
3840
3863
|
}
|
|
3841
|
-
else if (table.name ===
|
|
3842
|
-
else if (table.name ===
|
|
3864
|
+
else if (table.name === 'roles') ;
|
|
3865
|
+
else if (table.name === 'realms') {
|
|
3843
3866
|
// realms
|
|
3844
3867
|
yield table.toCollection().modify((realm) => {
|
|
3845
|
-
if (!ignoredRealms.has(realm.realmId) &&
|
|
3868
|
+
if (!ignoredRealms.has(realm.realmId) &&
|
|
3869
|
+
(realm.owner === undefined ||
|
|
3870
|
+
realm.owner === UNAUTHORIZED_USER.userId)) {
|
|
3846
3871
|
realm.owner = currentUser.userId;
|
|
3847
3872
|
}
|
|
3848
3873
|
});
|
|
@@ -3875,8 +3900,8 @@
|
|
|
3875
3900
|
let isOnline = false;
|
|
3876
3901
|
if (typeof self !== 'undefined' && typeof navigator !== 'undefined') {
|
|
3877
3902
|
isOnline = navigator.onLine;
|
|
3878
|
-
self.addEventListener('online', () => isOnline = true);
|
|
3879
|
-
self.addEventListener('offline', () => isOnline = false);
|
|
3903
|
+
self.addEventListener('online', () => (isOnline = true));
|
|
3904
|
+
self.addEventListener('offline', () => (isOnline = false));
|
|
3880
3905
|
}
|
|
3881
3906
|
|
|
3882
3907
|
function updateBaseRevs(db, schema, latestRevisions, serverRev) {
|
|
@@ -3893,7 +3918,10 @@
|
|
|
3893
3918
|
}));
|
|
3894
3919
|
// Clean up baseRevs for tables that do not exist anymore or are no longer marked for sync
|
|
3895
3920
|
// Resolve #2168 by also cleaning up baseRevs for tables that are not marked for sync
|
|
3896
|
-
yield db.$baseRevs
|
|
3921
|
+
yield db.$baseRevs
|
|
3922
|
+
.where('tableName')
|
|
3923
|
+
.noneOf(Object.keys(schema).filter((table) => schema[table].markedForSync))
|
|
3924
|
+
.delete();
|
|
3897
3925
|
});
|
|
3898
3926
|
}
|
|
3899
3927
|
|
|
@@ -3986,11 +4014,11 @@
|
|
|
3986
4014
|
return false;
|
|
3987
4015
|
}
|
|
3988
4016
|
if (Array.isArray(obj)) {
|
|
3989
|
-
return obj.some(item => hasBlobRefs(item, visited));
|
|
4017
|
+
return obj.some((item) => hasBlobRefs(item, visited));
|
|
3990
4018
|
}
|
|
3991
4019
|
// Only traverse POJOs
|
|
3992
4020
|
if (obj.constructor === Object) {
|
|
3993
|
-
return Object.values(obj).some(value => hasBlobRefs(value, visited));
|
|
4021
|
+
return Object.values(obj).some((value) => hasBlobRefs(value, visited));
|
|
3994
4022
|
}
|
|
3995
4023
|
return false;
|
|
3996
4024
|
}
|
|
@@ -4054,7 +4082,8 @@
|
|
|
4054
4082
|
*/
|
|
4055
4083
|
function resolveAllBlobRefs(obj_1, dbUrl_1) {
|
|
4056
4084
|
return __awaiter(this, arguments, void 0, function* (obj, dbUrl, resolvedBlobs = [], currentPath = '', visited = new WeakMap(), tracker) {
|
|
4057
|
-
if (obj == null) {
|
|
4085
|
+
if (obj == null) {
|
|
4086
|
+
// null or undefined
|
|
4058
4087
|
return obj;
|
|
4059
4088
|
}
|
|
4060
4089
|
// Check if this is a BlobRef - resolve it and track it
|
|
@@ -4103,9 +4132,7 @@
|
|
|
4103
4132
|
* Check if an object has unresolved BlobRefs
|
|
4104
4133
|
*/
|
|
4105
4134
|
function hasUnresolvedBlobRefs(obj) {
|
|
4106
|
-
return (typeof obj === 'object' &&
|
|
4107
|
-
obj !== null &&
|
|
4108
|
-
obj._hasBlobRefs === 1);
|
|
4135
|
+
return (typeof obj === 'object' && obj !== null && obj._hasBlobRefs === 1);
|
|
4109
4136
|
}
|
|
4110
4137
|
|
|
4111
4138
|
/**
|
|
@@ -4190,6 +4217,16 @@
|
|
|
4190
4217
|
}
|
|
4191
4218
|
break;
|
|
4192
4219
|
case 'update':
|
|
4220
|
+
if (!primaryKey.outbound && primaryKey.keyPath) {
|
|
4221
|
+
// The primary key should never be part of an updateSpec — it cannot change
|
|
4222
|
+
// and is already communicated via the operation's keys array.
|
|
4223
|
+
// For private singleton IDs (e.g. "#key:userId" on server, "#key" on client),
|
|
4224
|
+
// the encoded server-side key may leak into the changeSpec via getObjectDiff().
|
|
4225
|
+
// Strip it here unconditionally as a defensive measure.
|
|
4226
|
+
for (const changeSpec of mut.changeSpecs) {
|
|
4227
|
+
Dexie.delByKeyPath(changeSpec, primaryKey.keyPath);
|
|
4228
|
+
}
|
|
4229
|
+
}
|
|
4193
4230
|
yield bulkUpdate(table, keys, mut.changeSpecs);
|
|
4194
4231
|
break;
|
|
4195
4232
|
case 'delete':
|
|
@@ -4204,10 +4241,7 @@
|
|
|
4204
4241
|
const DEXIE_CLOUD_SYNCER_ID = 'dexie-cloud-syncer';
|
|
4205
4242
|
|
|
4206
4243
|
function listUpdatesSince(yTable, sinceIncluding) {
|
|
4207
|
-
return yTable
|
|
4208
|
-
.where('i')
|
|
4209
|
-
.between(sinceIncluding, Infinity, true)
|
|
4210
|
-
.toArray();
|
|
4244
|
+
return yTable.where('i').between(sinceIncluding, Infinity, true).toArray();
|
|
4211
4245
|
}
|
|
4212
4246
|
|
|
4213
4247
|
/**
|
|
@@ -13559,7 +13593,7 @@
|
|
|
13559
13593
|
}
|
|
13560
13594
|
return {
|
|
13561
13595
|
yMessages: result,
|
|
13562
|
-
lastUpdateIds
|
|
13596
|
+
lastUpdateIds,
|
|
13563
13597
|
};
|
|
13564
13598
|
});
|
|
13565
13599
|
}
|
|
@@ -13568,7 +13602,8 @@
|
|
|
13568
13602
|
var _a, _b, _c;
|
|
13569
13603
|
if (!db.dx._allTables[table])
|
|
13570
13604
|
return undefined;
|
|
13571
|
-
const utbl = (_c = (_b = (_a = db
|
|
13605
|
+
const utbl = (_c = (_b = (_a = db
|
|
13606
|
+
.table(table)) === null || _a === void 0 ? void 0 : _a.schema.yProps) === null || _b === void 0 ? void 0 : _b.find((p) => p.prop === ydocProp)) === null || _c === void 0 ? void 0 : _c.updatesTable;
|
|
13572
13607
|
if (!utbl) {
|
|
13573
13608
|
console.debug(`No updatesTable found for ${table}.${ydocProp}`);
|
|
13574
13609
|
return undefined;
|
|
@@ -13588,7 +13623,7 @@
|
|
|
13588
13623
|
*
|
|
13589
13624
|
* ==========================================================================
|
|
13590
13625
|
*
|
|
13591
|
-
* Version 4.4.0,
|
|
13626
|
+
* Version 4.4.0, Fri Mar 27 2026
|
|
13592
13627
|
*
|
|
13593
13628
|
* https://dexie.org
|
|
13594
13629
|
*
|
|
@@ -13605,7 +13640,7 @@
|
|
|
13605
13640
|
function getDocCache(db) {
|
|
13606
13641
|
var _a;
|
|
13607
13642
|
var _b;
|
|
13608
|
-
return (_a = (_b = db._novip)['_docCache']) !== null && _a !== void 0 ? _a : (_b['_docCache'] = {
|
|
13643
|
+
return ((_a = (_b = db._novip)['_docCache']) !== null && _a !== void 0 ? _a : (_b['_docCache'] = {
|
|
13609
13644
|
cache: {},
|
|
13610
13645
|
get size() {
|
|
13611
13646
|
return Object.keys(this.cache).length;
|
|
@@ -13636,7 +13671,7 @@
|
|
|
13636
13671
|
delete this.cache[cacheKey]; // Remove the entry from the cache only if it is the same doc.
|
|
13637
13672
|
}
|
|
13638
13673
|
},
|
|
13639
|
-
});
|
|
13674
|
+
}));
|
|
13640
13675
|
}
|
|
13641
13676
|
// Emulate a private boolean property "destroyed" on Y.Doc instances that we manage
|
|
13642
13677
|
// in createYDocProperty.ts:
|
|
@@ -13952,7 +13987,7 @@
|
|
|
13952
13987
|
}
|
|
13953
13988
|
throwIfDestroyed(doc);
|
|
13954
13989
|
this.stopObserving = observeYDocUpdates(this, doc, db, parentTable, updatesTable, parentId);
|
|
13955
|
-
DexieYProvider.on(
|
|
13990
|
+
DexieYProvider.on('new').fire(this); // Allow for addons to invoke their sync- and awareness providers here.
|
|
13956
13991
|
}
|
|
13957
13992
|
destroy() {
|
|
13958
13993
|
var _a, _b, _c;
|
|
@@ -13977,16 +14012,16 @@
|
|
|
13977
14012
|
});
|
|
13978
14013
|
DexieYProvider.getDocCache = getDocCache;
|
|
13979
14014
|
//
|
|
13980
|
-
// Eliminate dual package hazard
|
|
14015
|
+
// Eliminate dual package hazard
|
|
13981
14016
|
//
|
|
13982
14017
|
// Since we're holding static state, make sure to singletonize DexieYProvider
|
|
13983
14018
|
//
|
|
13984
|
-
if (Dexie.Dexie[
|
|
14019
|
+
if (Dexie.Dexie['DexieYProvider']) {
|
|
13985
14020
|
// @ts-ignore
|
|
13986
|
-
DexieYProvider = Dexie.Dexie[
|
|
14021
|
+
DexieYProvider = Dexie.Dexie['DexieYProvider'] || DexieYProvider;
|
|
13987
14022
|
}
|
|
13988
14023
|
else {
|
|
13989
|
-
Dexie.Dexie[
|
|
14024
|
+
Dexie.Dexie['DexieYProvider'] = DexieYProvider;
|
|
13990
14025
|
}
|
|
13991
14026
|
|
|
13992
14027
|
function applyYServerMessages(yMessages, db) {
|
|
@@ -14112,10 +14147,18 @@
|
|
|
14112
14147
|
*/
|
|
14113
14148
|
// TypedArray/DataView tags for size check
|
|
14114
14149
|
const ARRAYBUFFER_VIEW_TAGS = new Set([
|
|
14115
|
-
'Int8Array',
|
|
14116
|
-
'
|
|
14117
|
-
'
|
|
14118
|
-
'
|
|
14150
|
+
'Int8Array',
|
|
14151
|
+
'Uint8Array',
|
|
14152
|
+
'Uint8ClampedArray',
|
|
14153
|
+
'Int16Array',
|
|
14154
|
+
'Uint16Array',
|
|
14155
|
+
'Int32Array',
|
|
14156
|
+
'Uint32Array',
|
|
14157
|
+
'Float32Array',
|
|
14158
|
+
'Float64Array',
|
|
14159
|
+
'BigInt64Array',
|
|
14160
|
+
'BigUint64Array',
|
|
14161
|
+
'DataView',
|
|
14119
14162
|
]);
|
|
14120
14163
|
// Static Set for O(1) lookup of binary type tags
|
|
14121
14164
|
const BINARY_TYPE_TAGS = new Set([
|
|
@@ -14215,7 +14258,7 @@
|
|
|
14215
14258
|
const response = yield fetch(uploadUrl, {
|
|
14216
14259
|
method: 'PUT',
|
|
14217
14260
|
headers: {
|
|
14218
|
-
|
|
14261
|
+
Authorization: `Bearer ${accessToken}`,
|
|
14219
14262
|
'Content-Type': contentType,
|
|
14220
14263
|
},
|
|
14221
14264
|
body,
|
|
@@ -14231,8 +14274,7 @@
|
|
|
14231
14274
|
// The server returns the ref with version prefix (e.g., "1:blobId")
|
|
14232
14275
|
const result = yield response.json();
|
|
14233
14276
|
// Return BlobRef with server's ref (includes version) and original type preserved in _bt
|
|
14234
|
-
return Object.assign({ _bt: origType, ref: result.ref, size: size }, (origType === 'Blob' ? { ct: contentType } : {})
|
|
14235
|
-
);
|
|
14277
|
+
return Object.assign({ _bt: origType, ref: result.ref, size: size }, (origType === 'Blob' ? { ct: contentType } : {}));
|
|
14236
14278
|
});
|
|
14237
14279
|
}
|
|
14238
14280
|
function offloadBlobsAndMarkDirty(obj_1, databaseUrl_1, getCachedAccessToken_1) {
|
|
@@ -14240,7 +14282,10 @@
|
|
|
14240
14282
|
const dirtyFlag = { dirty: false };
|
|
14241
14283
|
const result = yield offloadBlobs(obj, databaseUrl, getCachedAccessToken, maxStringLength, dirtyFlag);
|
|
14242
14284
|
// Mark the object as dirty for sync if any blobs were offloaded
|
|
14243
|
-
if (dirtyFlag.dirty &&
|
|
14285
|
+
if (dirtyFlag.dirty &&
|
|
14286
|
+
typeof result === 'object' &&
|
|
14287
|
+
result !== null &&
|
|
14288
|
+
result.constructor === Object) {
|
|
14244
14289
|
result._hasBlobRefs = 1;
|
|
14245
14290
|
}
|
|
14246
14291
|
return result;
|
|
@@ -14256,7 +14301,9 @@
|
|
|
14256
14301
|
return obj;
|
|
14257
14302
|
}
|
|
14258
14303
|
// Check if this is a long string that should be offloaded
|
|
14259
|
-
if (typeof obj === 'string' &&
|
|
14304
|
+
if (typeof obj === 'string' &&
|
|
14305
|
+
obj.length > maxStringLength &&
|
|
14306
|
+
maxStringLength !== Infinity) {
|
|
14260
14307
|
if (blobEndpointSupported.get(databaseUrl) === false) {
|
|
14261
14308
|
return obj;
|
|
14262
14309
|
}
|
|
@@ -14342,11 +14389,11 @@
|
|
|
14342
14389
|
switch (op.type) {
|
|
14343
14390
|
case 'insert':
|
|
14344
14391
|
case 'upsert': {
|
|
14345
|
-
const processedValues = yield Promise.all(op.values.map(value => offloadBlobsAndMarkDirty(value, databaseUrl, getCachedAccessToken, maxStringLength)));
|
|
14392
|
+
const processedValues = yield Promise.all(op.values.map((value) => offloadBlobsAndMarkDirty(value, databaseUrl, getCachedAccessToken, maxStringLength)));
|
|
14346
14393
|
return Object.assign(Object.assign({}, op), { values: processedValues });
|
|
14347
14394
|
}
|
|
14348
14395
|
case 'update': {
|
|
14349
|
-
const processedChangeSpecs = yield Promise.all(op.changeSpecs.map(spec => offloadBlobsAndMarkDirty(spec, databaseUrl, getCachedAccessToken, maxStringLength)));
|
|
14396
|
+
const processedChangeSpecs = yield Promise.all(op.changeSpecs.map((spec) => offloadBlobsAndMarkDirty(spec, databaseUrl, getCachedAccessToken, maxStringLength)));
|
|
14350
14397
|
return Object.assign(Object.assign({}, op), { changeSpecs: processedChangeSpecs });
|
|
14351
14398
|
}
|
|
14352
14399
|
case 'modify': {
|
|
@@ -14379,9 +14426,9 @@
|
|
|
14379
14426
|
switch (op.type) {
|
|
14380
14427
|
case 'insert':
|
|
14381
14428
|
case 'upsert':
|
|
14382
|
-
return op.values.some(value => hasLargeBlobs(value, maxStringLength));
|
|
14429
|
+
return op.values.some((value) => hasLargeBlobs(value, maxStringLength));
|
|
14383
14430
|
case 'update':
|
|
14384
|
-
return op.changeSpecs.some(spec => hasLargeBlobs(spec, maxStringLength));
|
|
14431
|
+
return op.changeSpecs.some((spec) => hasLargeBlobs(spec, maxStringLength));
|
|
14385
14432
|
case 'modify':
|
|
14386
14433
|
return hasLargeBlobs(op.changeSpec, maxStringLength);
|
|
14387
14434
|
default:
|
|
@@ -14393,7 +14440,9 @@
|
|
|
14393
14440
|
return false;
|
|
14394
14441
|
}
|
|
14395
14442
|
// Check long strings
|
|
14396
|
-
if (typeof obj === 'string' &&
|
|
14443
|
+
if (typeof obj === 'string' &&
|
|
14444
|
+
obj.length > maxStringLength &&
|
|
14445
|
+
maxStringLength !== Infinity) {
|
|
14397
14446
|
return true;
|
|
14398
14447
|
}
|
|
14399
14448
|
if (shouldOffloadBlob(obj)) {
|
|
@@ -14408,13 +14457,13 @@
|
|
|
14408
14457
|
}
|
|
14409
14458
|
visited.add(obj);
|
|
14410
14459
|
if (Array.isArray(obj)) {
|
|
14411
|
-
return obj.some(item => hasLargeBlobs(item, maxStringLength, visited));
|
|
14460
|
+
return obj.some((item) => hasLargeBlobs(item, maxStringLength, visited));
|
|
14412
14461
|
}
|
|
14413
14462
|
// Traverse plain objects (POJO-like) - use duck typing since IndexedDB
|
|
14414
14463
|
// may return objects where constructor !== Object
|
|
14415
14464
|
const proto = Object.getPrototypeOf(obj);
|
|
14416
14465
|
if (proto === Object.prototype || proto === null) {
|
|
14417
|
-
return Object.values(obj).some(value => hasLargeBlobs(value, maxStringLength, visited));
|
|
14466
|
+
return Object.values(obj).some((value) => hasLargeBlobs(value, maxStringLength, visited));
|
|
14418
14467
|
}
|
|
14419
14468
|
return false;
|
|
14420
14469
|
}
|
|
@@ -14468,7 +14517,7 @@
|
|
|
14468
14517
|
yield db.table(yTable).add({
|
|
14469
14518
|
i: DEXIE_CLOUD_SYNCER_ID,
|
|
14470
14519
|
unsentFrom,
|
|
14471
|
-
receivedUntil
|
|
14520
|
+
receivedUntil,
|
|
14472
14521
|
});
|
|
14473
14522
|
}
|
|
14474
14523
|
else {
|
|
@@ -14608,19 +14657,22 @@
|
|
|
14608
14657
|
return Promise.resolve(cached.accessToken);
|
|
14609
14658
|
}
|
|
14610
14659
|
const currentUser = db.cloud.currentUser.value;
|
|
14611
|
-
if (currentUser &&
|
|
14660
|
+
if (currentUser &&
|
|
14661
|
+
currentUser.accessToken &&
|
|
14662
|
+
((_b = (_a = currentUser.accessTokenExpiration) === null || _a === void 0 ? void 0 : _a.getTime()) !== null && _b !== void 0 ? _b : Infinity) >
|
|
14663
|
+
Date.now() + 5 * MINUTES) {
|
|
14612
14664
|
wm$3.set(db, {
|
|
14613
14665
|
accessToken: currentUser.accessToken,
|
|
14614
|
-
expiration: (_d = (_c = currentUser.accessTokenExpiration) === null || _c === void 0 ? void 0 : _c.getTime()) !== null && _d !== void 0 ? _d : Infinity
|
|
14666
|
+
expiration: (_d = (_c = currentUser.accessTokenExpiration) === null || _c === void 0 ? void 0 : _c.getTime()) !== null && _d !== void 0 ? _d : Infinity,
|
|
14615
14667
|
});
|
|
14616
14668
|
return Promise.resolve(currentUser.accessToken);
|
|
14617
14669
|
}
|
|
14618
|
-
return Dexie.ignoreTransaction(() => loadAccessToken(db).then(user => {
|
|
14670
|
+
return Dexie.ignoreTransaction(() => loadAccessToken(db).then((user) => {
|
|
14619
14671
|
var _a, _b;
|
|
14620
14672
|
if (user === null || user === void 0 ? void 0 : user.accessToken) {
|
|
14621
14673
|
wm$3.set(db, {
|
|
14622
14674
|
accessToken: user.accessToken,
|
|
14623
|
-
expiration: (_b = (_a = user.accessTokenExpiration) === null || _a === void 0 ? void 0 : _a.getTime()) !== null && _b !== void 0 ? _b : Infinity
|
|
14675
|
+
expiration: (_b = (_a = user.accessTokenExpiration) === null || _a === void 0 ? void 0 : _a.getTime()) !== null && _b !== void 0 ? _b : Infinity,
|
|
14624
14676
|
});
|
|
14625
14677
|
}
|
|
14626
14678
|
return (user === null || user === void 0 ? void 0 : user.accessToken) || null;
|
|
@@ -14631,7 +14683,8 @@
|
|
|
14631
14683
|
function sync(db, options, schema, syncOptions) {
|
|
14632
14684
|
return _sync(db, options, schema, syncOptions)
|
|
14633
14685
|
.then((result) => {
|
|
14634
|
-
if (!(syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.justCheckIfNeeded)) {
|
|
14686
|
+
if (!(syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.justCheckIfNeeded)) {
|
|
14687
|
+
// && syncOptions?.purpose !== 'push') {
|
|
14635
14688
|
db.syncStateChangedEvent.next({
|
|
14636
14689
|
phase: 'in-sync',
|
|
14637
14690
|
});
|
|
@@ -14718,7 +14771,7 @@
|
|
|
14718
14771
|
const syncState = yield db.getPersistedSyncState();
|
|
14719
14772
|
let baseRevs = yield db.$baseRevs.toArray();
|
|
14720
14773
|
// Resolve #2168
|
|
14721
|
-
baseRevs = baseRevs.filter(br => tablesToSync.some(tbl => tbl.name === br.tableName));
|
|
14774
|
+
baseRevs = baseRevs.filter((br) => tablesToSync.some((tbl) => tbl.name === br.tableName));
|
|
14722
14775
|
let clientChanges = yield listClientChanges(mutationTables, db);
|
|
14723
14776
|
const yResults = yield listYClientMessagesAndStateVector(db, tablesToSync);
|
|
14724
14777
|
throwIfCancelled(cancelToken);
|
|
@@ -14734,7 +14787,7 @@
|
|
|
14734
14787
|
}
|
|
14735
14788
|
return [clientChanges, syncState, baseRevs, yResults];
|
|
14736
14789
|
}));
|
|
14737
|
-
const pushSyncIsNeeded = clientChangeSet.some((set) => set.muts.some((mut) => mut.keys.length > 0)) || yMessages.some(m => m.type === 'u-c');
|
|
14790
|
+
const pushSyncIsNeeded = clientChangeSet.some((set) => set.muts.some((mut) => mut.keys.length > 0)) || yMessages.some((m) => m.type === 'u-c');
|
|
14738
14791
|
if (justCheckIfNeeded) {
|
|
14739
14792
|
console.debug('Sync is needed:', pushSyncIsNeeded);
|
|
14740
14793
|
return pushSyncIsNeeded;
|
|
@@ -14878,7 +14931,7 @@
|
|
|
14878
14931
|
db.$syncState.put(newSyncState, 'syncState');
|
|
14879
14932
|
return {
|
|
14880
14933
|
done: addedClientChanges.length === 0,
|
|
14881
|
-
newSyncState
|
|
14934
|
+
newSyncState,
|
|
14882
14935
|
};
|
|
14883
14936
|
}));
|
|
14884
14937
|
if (!done) {
|
|
@@ -14886,7 +14939,7 @@
|
|
|
14886
14939
|
yield checkSyncRateLimitDelay(db);
|
|
14887
14940
|
return yield _sync(db, options, schema, { isInitialSync, cancelToken });
|
|
14888
14941
|
}
|
|
14889
|
-
const usingYProps = Object.values(schema).some(tbl => { var _a; return (_a = tbl.yProps) === null || _a === void 0 ? void 0 : _a.length; });
|
|
14942
|
+
const usingYProps = Object.values(schema).some((tbl) => { var _a; return (_a = tbl.yProps) === null || _a === void 0 ? void 0 : _a.length; });
|
|
14890
14943
|
const serverSupportsYprops = !!res.yMessages;
|
|
14891
14944
|
if (usingYProps && serverSupportsYprops) {
|
|
14892
14945
|
try {
|
|
@@ -15193,11 +15246,13 @@
|
|
|
15193
15246
|
download(blobRef, dbUrl) {
|
|
15194
15247
|
let promise = this.inFlight.get(blobRef.ref);
|
|
15195
15248
|
if (!promise) {
|
|
15196
|
-
promise = loadCachedAccessToken(this.db)
|
|
15249
|
+
promise = loadCachedAccessToken(this.db)
|
|
15250
|
+
.then((accessToken) => {
|
|
15197
15251
|
if (!accessToken)
|
|
15198
|
-
throw new Error(
|
|
15252
|
+
throw new Error('No access token available for blob download');
|
|
15199
15253
|
return downloadBlob(blobRef, dbUrl, accessToken);
|
|
15200
|
-
})
|
|
15254
|
+
})
|
|
15255
|
+
.finally(() => this.inFlight.delete(blobRef.ref));
|
|
15201
15256
|
// When the promise settles (either fulfilled or rejected), remove it from the in-flight map
|
|
15202
15257
|
this.inFlight.set(blobRef.ref, promise);
|
|
15203
15258
|
}
|
|
@@ -15217,8 +15272,8 @@
|
|
|
15217
15272
|
const downloadUrl = `${dbUrl}/blob/${blobRef.ref}`;
|
|
15218
15273
|
const response = yield fetch(downloadUrl, {
|
|
15219
15274
|
headers: {
|
|
15220
|
-
|
|
15221
|
-
}
|
|
15275
|
+
Authorization: `Bearer ${accessToken}`,
|
|
15276
|
+
},
|
|
15222
15277
|
});
|
|
15223
15278
|
if (!response.ok) {
|
|
15224
15279
|
throw new Error(`Failed to download blob ${blobRef.ref}: ${response.status} ${response.statusText}`);
|
|
@@ -15310,7 +15365,9 @@
|
|
|
15310
15365
|
return db.$syncState.get('schema').then((schema) => {
|
|
15311
15366
|
if (schema) {
|
|
15312
15367
|
for (const table of db.tables) {
|
|
15313
|
-
if (table.schema.primKey &&
|
|
15368
|
+
if (table.schema.primKey &&
|
|
15369
|
+
table.schema.primKey.keyPath &&
|
|
15370
|
+
schema[table.name]) {
|
|
15314
15371
|
schema[table.name].primaryKey = nameFromKeyPath(table.schema.primKey.keyPath);
|
|
15315
15372
|
}
|
|
15316
15373
|
}
|
|
@@ -15338,9 +15395,11 @@
|
|
|
15338
15395
|
return db;
|
|
15339
15396
|
}
|
|
15340
15397
|
function nameFromKeyPath(keyPath) {
|
|
15341
|
-
return typeof keyPath === 'string'
|
|
15342
|
-
keyPath
|
|
15343
|
-
|
|
15398
|
+
return typeof keyPath === 'string'
|
|
15399
|
+
? keyPath
|
|
15400
|
+
: keyPath
|
|
15401
|
+
? '[' + [].join.call(keyPath, '+') + ']'
|
|
15402
|
+
: '';
|
|
15344
15403
|
}
|
|
15345
15404
|
|
|
15346
15405
|
/**
|
|
@@ -15398,7 +15457,7 @@
|
|
|
15398
15457
|
isDownloading: isDownloading && stats.blobsRemaining > 0,
|
|
15399
15458
|
blobsRemaining: stats.blobsRemaining,
|
|
15400
15459
|
bytesRemaining: stats.bytesRemaining,
|
|
15401
|
-
})), operators.share({ resetOnRefCountZero: () => rxjs.timer(2000) }) // Keep alive for 2s after last unsubscription to avoid rapid re-subscriptions during UI updates
|
|
15460
|
+
})), operators.share({ resetOnRefCountZero: () => rxjs.timer(2000) }) // Keep alive for 2s after last unsubscription to avoid rapid re-subscriptions during UI updates
|
|
15402
15461
|
);
|
|
15403
15462
|
}
|
|
15404
15463
|
/**
|
|
@@ -15482,13 +15541,13 @@
|
|
|
15482
15541
|
}
|
|
15483
15542
|
setDownloadingState(downloading$, true);
|
|
15484
15543
|
try {
|
|
15485
|
-
debugLog(`Eager download: Found ${syncedTables.length} syncable tables: ${syncedTables.map(t => t.name).join(', ')}`);
|
|
15544
|
+
debugLog(`Eager download: Found ${syncedTables.length} syncable tables: ${syncedTables.map((t) => t.name).join(', ')}`);
|
|
15486
15545
|
for (const table of syncedTables) {
|
|
15487
15546
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted)
|
|
15488
15547
|
;
|
|
15489
15548
|
try {
|
|
15490
15549
|
// Check if table has _hasBlobRefs index
|
|
15491
|
-
const hasIndex = table.schema.indexes.some(idx => idx.name === '_hasBlobRefs');
|
|
15550
|
+
const hasIndex = table.schema.indexes.some((idx) => idx.name === '_hasBlobRefs');
|
|
15492
15551
|
if (!hasIndex)
|
|
15493
15552
|
continue;
|
|
15494
15553
|
// Query objects with _hasBlobRefs marker
|
|
@@ -15504,7 +15563,7 @@
|
|
|
15504
15563
|
const MAX_CONCURRENT = 6;
|
|
15505
15564
|
const primaryKey = table.schema.primKey;
|
|
15506
15565
|
// Filter to actionable objects first
|
|
15507
|
-
const pending = unresolvedObjects.filter(obj => {
|
|
15566
|
+
const pending = unresolvedObjects.filter((obj) => {
|
|
15508
15567
|
if (!hasUnresolvedBlobRefs(obj))
|
|
15509
15568
|
return false;
|
|
15510
15569
|
const key = primaryKey.keyPath
|
|
@@ -15567,20 +15626,20 @@
|
|
|
15567
15626
|
}
|
|
15568
15627
|
static load(db, userId) {
|
|
15569
15628
|
return db
|
|
15570
|
-
.table(
|
|
15629
|
+
.table('$logins')
|
|
15571
15630
|
.get(userId)
|
|
15572
15631
|
.then((userLogin) => new AuthPersistedContext(db, userLogin || {
|
|
15573
15632
|
userId,
|
|
15574
15633
|
claims: {
|
|
15575
|
-
sub: userId
|
|
15634
|
+
sub: userId,
|
|
15576
15635
|
},
|
|
15577
|
-
lastLogin: new Date(0)
|
|
15636
|
+
lastLogin: new Date(0),
|
|
15578
15637
|
}));
|
|
15579
15638
|
}
|
|
15580
15639
|
save() {
|
|
15581
15640
|
return __awaiter(this, void 0, void 0, function* () {
|
|
15582
15641
|
const db = wm$1.get(this);
|
|
15583
|
-
db.table(
|
|
15642
|
+
db.table('$logins').put(this);
|
|
15584
15643
|
});
|
|
15585
15644
|
}
|
|
15586
15645
|
}
|
|
@@ -15675,7 +15734,7 @@
|
|
|
15675
15734
|
*/
|
|
15676
15735
|
function exchangeOAuthCode(options) {
|
|
15677
15736
|
return __awaiter(this, void 0, void 0, function* () {
|
|
15678
|
-
const { databaseUrl, code, publicKey, scopes = ['ACCESS_DB'], intent } = options;
|
|
15737
|
+
const { databaseUrl, code, publicKey, scopes = ['ACCESS_DB'], intent, } = options;
|
|
15679
15738
|
const tokenRequest = Object.assign({ grant_type: 'authorization_code', code, public_key: publicKey, scopes }, (intent !== undefined ? { intent } : {}));
|
|
15680
15739
|
try {
|
|
15681
15740
|
const res = yield fetch(`${databaseUrl}/token`, {
|
|
@@ -15733,7 +15792,8 @@
|
|
|
15733
15792
|
return response;
|
|
15734
15793
|
}
|
|
15735
15794
|
catch (error) {
|
|
15736
|
-
if (error instanceof OAuthError ||
|
|
15795
|
+
if (error instanceof OAuthError ||
|
|
15796
|
+
error instanceof TokenErrorResponseError) {
|
|
15737
15797
|
throw error;
|
|
15738
15798
|
}
|
|
15739
15799
|
if (error instanceof TypeError) {
|
|
@@ -15771,7 +15831,7 @@
|
|
|
15771
15831
|
try {
|
|
15772
15832
|
const res = yield fetch(`${databaseUrl}/auth-providers`, {
|
|
15773
15833
|
method: 'GET',
|
|
15774
|
-
headers: {
|
|
15834
|
+
headers: { Accept: 'application/json' },
|
|
15775
15835
|
mode: 'cors',
|
|
15776
15836
|
});
|
|
15777
15837
|
if (res.status === 404) {
|
|
@@ -16101,7 +16161,7 @@
|
|
|
16101
16161
|
* @param args
|
|
16102
16162
|
*/
|
|
16103
16163
|
function prodLog(level, ...args) {
|
|
16104
|
-
globalThis[
|
|
16164
|
+
globalThis['con' + 'sole'][level](...args);
|
|
16105
16165
|
}
|
|
16106
16166
|
|
|
16107
16167
|
/** This function changes or sets the current user as requested.
|
|
@@ -16231,7 +16291,7 @@
|
|
|
16231
16291
|
const DISABLE_SERVICEWORKER_STRATEGY = (isSafari && safariVersion <= 605) || // Disable for Safari for now.
|
|
16232
16292
|
isFirefox; // Disable for Firefox for now. Seems to have a bug in reading CryptoKeys from IDB from service workers
|
|
16233
16293
|
|
|
16234
|
-
const IS_SERVICE_WORKER = typeof self !==
|
|
16294
|
+
const IS_SERVICE_WORKER = typeof self !== 'undefined' && 'clients' in self && !self.document;
|
|
16235
16295
|
|
|
16236
16296
|
function throwVersionIncrementNeeded() {
|
|
16237
16297
|
throw new Dexie.SchemaError(`Version increment needed to allow dexie-cloud change tracking`);
|
|
@@ -16477,7 +16537,7 @@
|
|
|
16477
16537
|
// We must also degrade from consistent modify operations for the
|
|
16478
16538
|
// same reason - object might be there on server. Must but put up instead.
|
|
16479
16539
|
// FUTURE: This clumpsy behavior of private IDs could be refined later.
|
|
16480
|
-
// Suggestion is to in future, treat private IDs as we treat all objects
|
|
16540
|
+
// Suggestion is to in future, treat private IDs as we treat all objects
|
|
16481
16541
|
// and sync operations normally. Only that deletions should become soft deletes
|
|
16482
16542
|
// for them - so that server knows when a private ID has been deleted on server
|
|
16483
16543
|
// not accept insert/upserts on them.
|
|
@@ -16500,19 +16560,20 @@
|
|
|
16500
16560
|
}
|
|
16501
16561
|
|
|
16502
16562
|
function allSettled(possiblePromises) {
|
|
16503
|
-
return new Promise(resolve => {
|
|
16563
|
+
return new Promise((resolve) => {
|
|
16504
16564
|
if (possiblePromises.length === 0)
|
|
16505
16565
|
resolve([]);
|
|
16506
16566
|
let remaining = possiblePromises.length;
|
|
16507
16567
|
const results = new Array(remaining);
|
|
16508
|
-
possiblePromises.forEach((p, i) => Promise.resolve(p)
|
|
16568
|
+
possiblePromises.forEach((p, i) => Promise.resolve(p)
|
|
16569
|
+
.then((value) => (results[i] = { status: 'fulfilled', value }), (reason) => (results[i] = { status: 'rejected', reason }))
|
|
16509
16570
|
.then(() => --remaining || resolve(results)));
|
|
16510
16571
|
});
|
|
16511
16572
|
}
|
|
16512
16573
|
|
|
16513
16574
|
let counter$1 = 0;
|
|
16514
16575
|
function guardedTable(table) {
|
|
16515
|
-
const prop =
|
|
16576
|
+
const prop = '$lock' + ++counter$1;
|
|
16516
16577
|
return Object.assign(Object.assign({}, table), { count: readLock(table.count, prop), get: readLock(table.get, prop), getMany: readLock(table.getMany, prop), openCursor: readLock(table.openCursor, prop), query: readLock(table.query, prop), mutate: writeLock(table.mutate, prop) });
|
|
16517
16578
|
}
|
|
16518
16579
|
function readLock(fn, prop) {
|
|
@@ -16521,7 +16582,9 @@
|
|
|
16521
16582
|
const numWriters = writers.length;
|
|
16522
16583
|
const promise = (numWriters > 0
|
|
16523
16584
|
? writers[numWriters - 1].then(() => fn(req), () => fn(req))
|
|
16524
|
-
: fn(req)).finally(() => {
|
|
16585
|
+
: fn(req)).finally(() => {
|
|
16586
|
+
readers.splice(readers.indexOf(promise));
|
|
16587
|
+
});
|
|
16525
16588
|
readers.push(promise);
|
|
16526
16589
|
return promise;
|
|
16527
16590
|
};
|
|
@@ -16533,7 +16596,9 @@
|
|
|
16533
16596
|
? writers[writers.length - 1].then(() => fn(req), () => fn(req))
|
|
16534
16597
|
: readers.length > 0
|
|
16535
16598
|
? allSettled(readers).then(() => fn(req))
|
|
16536
|
-
: fn(req)).finally(() => {
|
|
16599
|
+
: fn(req)).finally(() => {
|
|
16600
|
+
writers.shift();
|
|
16601
|
+
});
|
|
16537
16602
|
writers.push(promise);
|
|
16538
16603
|
return promise;
|
|
16539
16604
|
};
|
|
@@ -16811,16 +16876,17 @@
|
|
|
16811
16876
|
userId,
|
|
16812
16877
|
values,
|
|
16813
16878
|
}
|
|
16814
|
-
: upsert && updates
|
|
16815
|
-
|
|
16816
|
-
|
|
16817
|
-
|
|
16818
|
-
|
|
16819
|
-
|
|
16820
|
-
|
|
16821
|
-
|
|
16822
|
-
|
|
16823
|
-
|
|
16879
|
+
: upsert && updates
|
|
16880
|
+
? {
|
|
16881
|
+
type: 'upsert',
|
|
16882
|
+
ts,
|
|
16883
|
+
opNo,
|
|
16884
|
+
keys,
|
|
16885
|
+
values,
|
|
16886
|
+
changeSpecs: updates.changeSpecs.filter((_, idx) => !failures[idx]),
|
|
16887
|
+
txid,
|
|
16888
|
+
userId,
|
|
16889
|
+
}
|
|
16824
16890
|
: criteria && changeSpec
|
|
16825
16891
|
? {
|
|
16826
16892
|
// Common changeSpec for all keys
|
|
@@ -16933,7 +16999,8 @@
|
|
|
16933
16999
|
return;
|
|
16934
17000
|
}
|
|
16935
17001
|
// Atomic update of just the blob property
|
|
16936
|
-
this.db
|
|
17002
|
+
this.db
|
|
17003
|
+
.transaction('rw', item.tableName, (tx) => {
|
|
16937
17004
|
const trans = tx.idbtrans;
|
|
16938
17005
|
trans.disableChangeTracking = true; // Don't regard this as a change for sync purposes
|
|
16939
17006
|
trans.disableAccessControl = true; // Bypass any access control checks since this is an internal operation
|
|
@@ -16942,7 +17009,7 @@
|
|
|
16942
17009
|
for (const blob of item.resolvedBlobs) {
|
|
16943
17010
|
updateSpec[blob.keyPath] = blob.data;
|
|
16944
17011
|
}
|
|
16945
|
-
tx.table(item.tableName).update(item.primaryKey, obj => {
|
|
17012
|
+
tx.table(item.tableName).update(item.primaryKey, (obj) => {
|
|
16946
17013
|
// Check that object still has the same unresolved blob refs before applying update (i.e. it hasn't been modified since we read it)
|
|
16947
17014
|
for (const blob of item.resolvedBlobs) {
|
|
16948
17015
|
// Verify atomicity - none of the blob properties has been modified since we read it. If any of them was modified, skip updating this item to avoid overwriting user changes.
|
|
@@ -16963,9 +17030,11 @@
|
|
|
16963
17030
|
}
|
|
16964
17031
|
delete obj._hasBlobRefs; // Clear the _hasBlobRefs marker if all refs was resolved.
|
|
16965
17032
|
});
|
|
16966
|
-
})
|
|
17033
|
+
})
|
|
17034
|
+
.catch((error) => {
|
|
16967
17035
|
console.error(`Error saving resolved blobs on ${item.tableName}:${item.primaryKey}:`, error);
|
|
16968
|
-
})
|
|
17036
|
+
})
|
|
17037
|
+
.finally(() => {
|
|
16969
17038
|
// Process next item in the queue
|
|
16970
17039
|
return this.processQueue();
|
|
16971
17040
|
});
|
|
@@ -17016,7 +17085,7 @@
|
|
|
17016
17085
|
if ((_a = req.trans) === null || _a === void 0 ? void 0 : _a.disableBlobResolve) {
|
|
17017
17086
|
return downlevelTable.get(req);
|
|
17018
17087
|
}
|
|
17019
|
-
return downlevelTable.get(req).then(result => {
|
|
17088
|
+
return downlevelTable.get(req).then((result) => {
|
|
17020
17089
|
if (result && hasUnresolvedBlobRefs(result)) {
|
|
17021
17090
|
return resolveAndSave(downlevelTable, req.trans, req.key, result, blobSavingQueue, db);
|
|
17022
17091
|
}
|
|
@@ -17028,9 +17097,9 @@
|
|
|
17028
17097
|
if ((_a = req.trans) === null || _a === void 0 ? void 0 : _a.disableBlobResolve) {
|
|
17029
17098
|
return downlevelTable.getMany(req);
|
|
17030
17099
|
}
|
|
17031
|
-
return downlevelTable.getMany(req).then(results => {
|
|
17100
|
+
return downlevelTable.getMany(req).then((results) => {
|
|
17032
17101
|
// Check if any results need resolution
|
|
17033
|
-
const needsResolution = results.some(r => r && hasUnresolvedBlobRefs(r));
|
|
17102
|
+
const needsResolution = results.some((r) => r && hasUnresolvedBlobRefs(r));
|
|
17034
17103
|
if (!needsResolution)
|
|
17035
17104
|
return results;
|
|
17036
17105
|
return Dexie.Promise.all(results.map((result, index) => {
|
|
@@ -17046,19 +17115,19 @@
|
|
|
17046
17115
|
if ((_a = req.trans) === null || _a === void 0 ? void 0 : _a.disableBlobResolve) {
|
|
17047
17116
|
return downlevelTable.query(req);
|
|
17048
17117
|
}
|
|
17049
|
-
return downlevelTable.query(req).then(result => {
|
|
17118
|
+
return downlevelTable.query(req).then((result) => {
|
|
17050
17119
|
if (!result.result || !Array.isArray(result.result))
|
|
17051
17120
|
return result;
|
|
17052
17121
|
// Check if any results need resolution
|
|
17053
|
-
const needsResolution = result.result.some(r => r && hasUnresolvedBlobRefs(r));
|
|
17122
|
+
const needsResolution = result.result.some((r) => r && hasUnresolvedBlobRefs(r));
|
|
17054
17123
|
if (!needsResolution)
|
|
17055
17124
|
return result;
|
|
17056
|
-
return Dexie.Promise.all(result.result.map(item => {
|
|
17125
|
+
return Dexie.Promise.all(result.result.map((item) => {
|
|
17057
17126
|
if (item && hasUnresolvedBlobRefs(item)) {
|
|
17058
17127
|
return resolveAndSave(downlevelTable, req.trans, undefined, item, blobSavingQueue, db);
|
|
17059
17128
|
}
|
|
17060
17129
|
return item;
|
|
17061
|
-
})).then(resolved => (Object.assign(Object.assign({}, result), { result: resolved })));
|
|
17130
|
+
})).then((resolved) => (Object.assign(Object.assign({}, result), { result: resolved })));
|
|
17062
17131
|
});
|
|
17063
17132
|
},
|
|
17064
17133
|
openCursor(req) {
|
|
@@ -17066,7 +17135,7 @@
|
|
|
17066
17135
|
if ((_a = req.trans) === null || _a === void 0 ? void 0 : _a.disableBlobResolve) {
|
|
17067
17136
|
return downlevelTable.openCursor(req);
|
|
17068
17137
|
}
|
|
17069
|
-
return downlevelTable.openCursor(req).then(cursor => {
|
|
17138
|
+
return downlevelTable.openCursor(req).then((cursor) => {
|
|
17070
17139
|
if (!cursor)
|
|
17071
17140
|
return cursor; // No results, so no resolution needed
|
|
17072
17141
|
if (!req.values)
|
|
@@ -17096,7 +17165,7 @@
|
|
|
17096
17165
|
value: {
|
|
17097
17166
|
value: cursor.value,
|
|
17098
17167
|
enumerable: true,
|
|
17099
|
-
writable: true
|
|
17168
|
+
writable: true,
|
|
17100
17169
|
},
|
|
17101
17170
|
start: {
|
|
17102
17171
|
value(onNext) {
|
|
@@ -17108,17 +17177,17 @@
|
|
|
17108
17177
|
onNext();
|
|
17109
17178
|
return;
|
|
17110
17179
|
}
|
|
17111
|
-
resolveAndSave(table, cursor.trans, cursor.primaryKey, rawValue, blobSavingQueue, db, true).then(resolved => {
|
|
17180
|
+
resolveAndSave(table, cursor.trans, cursor.primaryKey, rawValue, blobSavingQueue, db, true).then((resolved) => {
|
|
17112
17181
|
wrappedCursor.value = resolved;
|
|
17113
17182
|
onNext();
|
|
17114
|
-
}, err => {
|
|
17183
|
+
}, (err) => {
|
|
17115
17184
|
console.error('Failed to resolve BlobRefs for cursor value:', err);
|
|
17116
17185
|
wrappedCursor.value = rawValue;
|
|
17117
17186
|
onNext();
|
|
17118
17187
|
});
|
|
17119
17188
|
});
|
|
17120
|
-
}
|
|
17121
|
-
}
|
|
17189
|
+
},
|
|
17190
|
+
},
|
|
17122
17191
|
});
|
|
17123
17192
|
return wrappedCursor;
|
|
17124
17193
|
}
|
|
@@ -17163,12 +17232,15 @@
|
|
|
17163
17232
|
const resolvePromise = needsWaitFor
|
|
17164
17233
|
? Dexie.waitFor(resolutionPromise)
|
|
17165
17234
|
: Dexie.Promise.resolve(resolutionPromise);
|
|
17166
|
-
return resolvePromise
|
|
17235
|
+
return resolvePromise
|
|
17236
|
+
.then((resolved) => {
|
|
17167
17237
|
// Get primary key from the object
|
|
17168
17238
|
const primaryKey = table.schema.primaryKey;
|
|
17169
|
-
const key = pKey !== undefined
|
|
17170
|
-
?
|
|
17171
|
-
:
|
|
17239
|
+
const key = pKey !== undefined
|
|
17240
|
+
? pKey
|
|
17241
|
+
: primaryKey.keyPath
|
|
17242
|
+
? Dexie.getByKeyPath(obj, primaryKey.keyPath)
|
|
17243
|
+
: undefined;
|
|
17172
17244
|
if (key !== undefined) {
|
|
17173
17245
|
// Queue each resolved blob individually for atomic update
|
|
17174
17246
|
// This uses setTimeout(fn, 0) to completely isolate from
|
|
@@ -17179,13 +17251,16 @@
|
|
|
17179
17251
|
else {
|
|
17180
17252
|
// For rw transactions, we can save directly without queueing
|
|
17181
17253
|
// since we're still in the same transaction context
|
|
17182
|
-
table
|
|
17254
|
+
table
|
|
17255
|
+
.mutate({ type: 'put', keys: [key], values: [resolved], trans })
|
|
17256
|
+
.catch((err) => {
|
|
17183
17257
|
console.error(`Failed to save resolved blob on ${table.name}:${key}:`, err);
|
|
17184
17258
|
});
|
|
17185
17259
|
}
|
|
17186
17260
|
}
|
|
17187
17261
|
return resolved;
|
|
17188
|
-
})
|
|
17262
|
+
})
|
|
17263
|
+
.catch((err) => {
|
|
17189
17264
|
console.error(`[dexie-cloud:blobResolve] Failed to resolve BlobRefs on ${table.name}:`, err);
|
|
17190
17265
|
return obj; // Return original object on error - never block the read pipeline
|
|
17191
17266
|
});
|
|
@@ -17214,9 +17289,13 @@
|
|
|
17214
17289
|
return; // Continue
|
|
17215
17290
|
}
|
|
17216
17291
|
// They have declared this table. Merge indexes in case they didn't declare all indexes we need.
|
|
17217
|
-
const requestedIndexes = schemaSrc
|
|
17218
|
-
|
|
17219
|
-
|
|
17292
|
+
const requestedIndexes = schemaSrc
|
|
17293
|
+
.split(',')
|
|
17294
|
+
.map((spec) => spec.trim());
|
|
17295
|
+
const builtInIndexes = DEXIE_CLOUD_SCHEMA[tableName]
|
|
17296
|
+
.split(',')
|
|
17297
|
+
.map((spec) => spec.trim());
|
|
17298
|
+
const requestedIndexSet = new Set(requestedIndexes.map((index) => index.replace(/([&*]|\+\+)/g, '')));
|
|
17220
17299
|
// Verify that primary key is unchanged
|
|
17221
17300
|
if (requestedIndexes[0] !== builtInIndexes[0]) {
|
|
17222
17301
|
// Primary key must match exactly
|
|
@@ -17225,7 +17304,7 @@
|
|
|
17225
17304
|
// Merge indexes
|
|
17226
17305
|
for (let i = 1; i < builtInIndexes.length; ++i) {
|
|
17227
17306
|
const builtInIndex = builtInIndexes[i];
|
|
17228
|
-
if (!requestedIndexSet.has(builtInIndex.replace(/([&*]|\+\+)/g,
|
|
17307
|
+
if (!requestedIndexSet.has(builtInIndex.replace(/([&*]|\+\+)/g, ''))) {
|
|
17229
17308
|
// Add built-in index if not already requested
|
|
17230
17309
|
storesClone[tableName] += `,${builtInIndex}`;
|
|
17231
17310
|
}
|
|
@@ -17234,7 +17313,7 @@
|
|
|
17234
17313
|
// Populate dexie.cloud.schema
|
|
17235
17314
|
const cloudSchema = dexie.cloud.schema || (dexie.cloud.schema = {});
|
|
17236
17315
|
const allPrefixes = new Set();
|
|
17237
|
-
Object.keys(storesClone).forEach(tableName => {
|
|
17316
|
+
Object.keys(storesClone).forEach((tableName) => {
|
|
17238
17317
|
var _a;
|
|
17239
17318
|
const schemaSrc = (_a = storesClone[tableName]) === null || _a === void 0 ? void 0 : _a.trim();
|
|
17240
17319
|
const cloudTableSchema = cloudSchema[tableName] || (cloudSchema[tableName] = {});
|
|
@@ -17363,7 +17442,7 @@
|
|
|
17363
17442
|
class TokenExpiredError extends Error {
|
|
17364
17443
|
constructor() {
|
|
17365
17444
|
super(...arguments);
|
|
17366
|
-
this.name =
|
|
17445
|
+
this.name = 'TokenExpiredError';
|
|
17367
17446
|
}
|
|
17368
17447
|
}
|
|
17369
17448
|
|
|
@@ -17849,7 +17928,7 @@
|
|
|
17849
17928
|
// Connect the WebSocket to given url:
|
|
17850
17929
|
console.debug('dexie-cloud WebSocket create');
|
|
17851
17930
|
const ws = (this.ws = new WebSocket(`${wsUrl}/changes?${searchParams}`));
|
|
17852
|
-
ws.binaryType =
|
|
17931
|
+
ws.binaryType = 'arraybuffer';
|
|
17853
17932
|
ws.onclose = (event) => {
|
|
17854
17933
|
if (!this.pinger)
|
|
17855
17934
|
return;
|
|
@@ -17888,10 +17967,17 @@
|
|
|
17888
17967
|
getOpenDocSignal(doc).next(); // Make yHandler reopen the document on server.
|
|
17889
17968
|
}
|
|
17890
17969
|
}
|
|
17891
|
-
else if (msg.type === 'u-ack' ||
|
|
17970
|
+
else if (msg.type === 'u-ack' ||
|
|
17971
|
+
msg.type === 'u-reject' ||
|
|
17972
|
+
msg.type === 'u-s' ||
|
|
17973
|
+
msg.type === 'in-sync' ||
|
|
17974
|
+
msg.type === 'outdated-server-rev' ||
|
|
17975
|
+
msg.type === 'y-complete-sync-done') {
|
|
17892
17976
|
applyYServerMessages([msg], this.db).then((_a) => __awaiter(this, [_a], void 0, function* ({ resyncNeeded, yServerRevision, receivedUntils }) {
|
|
17893
17977
|
if (yServerRevision) {
|
|
17894
|
-
yield this.db.$syncState.update('syncState', {
|
|
17978
|
+
yield this.db.$syncState.update('syncState', {
|
|
17979
|
+
yServerRevision: yServerRevision,
|
|
17980
|
+
});
|
|
17895
17981
|
}
|
|
17896
17982
|
if (msg.type === 'u-s' && receivedUntils) {
|
|
17897
17983
|
const utbl = getUpdatesTable(this.db, msg.table, msg.prop);
|
|
@@ -18094,7 +18180,9 @@
|
|
|
18094
18180
|
return __awaiter(this, void 0, void 0, function* () {
|
|
18095
18181
|
var _a;
|
|
18096
18182
|
return ((_a = db.cloud.options) === null || _a === void 0 ? void 0 : _a.databaseUrl) && db.cloud.schema
|
|
18097
|
-
? yield sync(db, db.cloud.options, db.cloud.schema, {
|
|
18183
|
+
? yield sync(db, db.cloud.options, db.cloud.schema, {
|
|
18184
|
+
justCheckIfNeeded: true,
|
|
18185
|
+
})
|
|
18098
18186
|
: false;
|
|
18099
18187
|
});
|
|
18100
18188
|
}
|
|
@@ -18306,243 +18394,243 @@
|
|
|
18306
18394
|
const Styles = {
|
|
18307
18395
|
Alert: {
|
|
18308
18396
|
error: {
|
|
18309
|
-
color:
|
|
18310
|
-
fontWeight:
|
|
18397
|
+
color: 'red',
|
|
18398
|
+
fontWeight: 'bold',
|
|
18311
18399
|
},
|
|
18312
18400
|
warning: {
|
|
18313
|
-
color:
|
|
18314
|
-
fontWeight:
|
|
18401
|
+
color: '#f80',
|
|
18402
|
+
fontWeight: 'bold',
|
|
18315
18403
|
},
|
|
18316
18404
|
info: {
|
|
18317
|
-
color:
|
|
18318
|
-
}
|
|
18405
|
+
color: 'black',
|
|
18406
|
+
},
|
|
18319
18407
|
},
|
|
18320
18408
|
Darken: {
|
|
18321
|
-
position:
|
|
18409
|
+
position: 'fixed',
|
|
18322
18410
|
top: 0,
|
|
18323
18411
|
left: 0,
|
|
18324
18412
|
opacity: 0.5,
|
|
18325
|
-
backgroundColor:
|
|
18326
|
-
width:
|
|
18327
|
-
height:
|
|
18413
|
+
backgroundColor: '#000',
|
|
18414
|
+
width: '100vw',
|
|
18415
|
+
height: '100vh',
|
|
18328
18416
|
zIndex: 150,
|
|
18329
|
-
webkitBackdropFilter:
|
|
18330
|
-
backdropFilter:
|
|
18417
|
+
webkitBackdropFilter: 'blur(2px)',
|
|
18418
|
+
backdropFilter: 'blur(2px)',
|
|
18331
18419
|
},
|
|
18332
18420
|
DialogOuter: {
|
|
18333
|
-
position:
|
|
18421
|
+
position: 'fixed',
|
|
18334
18422
|
top: 0,
|
|
18335
18423
|
left: 0,
|
|
18336
|
-
width:
|
|
18337
|
-
height:
|
|
18424
|
+
width: '100vw',
|
|
18425
|
+
height: '100vh',
|
|
18338
18426
|
zIndex: 150,
|
|
18339
|
-
alignItems:
|
|
18340
|
-
display:
|
|
18341
|
-
justifyContent:
|
|
18342
|
-
padding:
|
|
18343
|
-
boxSizing:
|
|
18427
|
+
alignItems: 'center',
|
|
18428
|
+
display: 'flex',
|
|
18429
|
+
justifyContent: 'center',
|
|
18430
|
+
padding: '16px',
|
|
18431
|
+
boxSizing: 'border-box',
|
|
18344
18432
|
},
|
|
18345
18433
|
DialogInner: {
|
|
18346
|
-
position:
|
|
18347
|
-
color:
|
|
18348
|
-
backgroundColor:
|
|
18349
|
-
padding:
|
|
18350
|
-
marginBottom:
|
|
18351
|
-
maxWidth:
|
|
18352
|
-
width:
|
|
18353
|
-
maxHeight:
|
|
18354
|
-
overflowY:
|
|
18355
|
-
border:
|
|
18356
|
-
borderRadius:
|
|
18357
|
-
boxShadow:
|
|
18358
|
-
fontFamily:
|
|
18359
|
-
boxSizing:
|
|
18434
|
+
position: 'relative',
|
|
18435
|
+
color: '#222',
|
|
18436
|
+
backgroundColor: '#fff',
|
|
18437
|
+
padding: '24px',
|
|
18438
|
+
marginBottom: '2em',
|
|
18439
|
+
maxWidth: '400px',
|
|
18440
|
+
width: '100%',
|
|
18441
|
+
maxHeight: '90%',
|
|
18442
|
+
overflowY: 'auto',
|
|
18443
|
+
border: '3px solid #3d3d5d',
|
|
18444
|
+
borderRadius: '8px',
|
|
18445
|
+
boxShadow: '0 0 80px 10px #666',
|
|
18446
|
+
fontFamily: 'sans-serif',
|
|
18447
|
+
boxSizing: 'border-box',
|
|
18360
18448
|
},
|
|
18361
18449
|
Input: {
|
|
18362
|
-
height:
|
|
18363
|
-
width:
|
|
18364
|
-
maxWidth:
|
|
18365
|
-
borderColor:
|
|
18366
|
-
outline:
|
|
18367
|
-
fontSize:
|
|
18368
|
-
padding:
|
|
18369
|
-
boxSizing:
|
|
18370
|
-
backgroundColor:
|
|
18371
|
-
borderRadius:
|
|
18372
|
-
border:
|
|
18373
|
-
marginTop:
|
|
18374
|
-
fontFamily:
|
|
18450
|
+
height: '35px',
|
|
18451
|
+
width: '100%',
|
|
18452
|
+
maxWidth: '100%',
|
|
18453
|
+
borderColor: '#ccf4',
|
|
18454
|
+
outline: 'none',
|
|
18455
|
+
fontSize: '16px',
|
|
18456
|
+
padding: '8px',
|
|
18457
|
+
boxSizing: 'border-box',
|
|
18458
|
+
backgroundColor: '#f9f9f9',
|
|
18459
|
+
borderRadius: '4px',
|
|
18460
|
+
border: '1px solid #ccc',
|
|
18461
|
+
marginTop: '6px',
|
|
18462
|
+
fontFamily: 'inherit',
|
|
18375
18463
|
},
|
|
18376
18464
|
Button: {
|
|
18377
|
-
padding:
|
|
18378
|
-
margin:
|
|
18379
|
-
border:
|
|
18380
|
-
borderRadius:
|
|
18381
|
-
backgroundColor:
|
|
18382
|
-
cursor:
|
|
18383
|
-
fontSize:
|
|
18384
|
-
fontWeight:
|
|
18385
|
-
color:
|
|
18386
|
-
transition:
|
|
18465
|
+
padding: '10px 20px',
|
|
18466
|
+
margin: '0 4px',
|
|
18467
|
+
border: '1px solid #d1d5db',
|
|
18468
|
+
borderRadius: '6px',
|
|
18469
|
+
backgroundColor: '#ffffff',
|
|
18470
|
+
cursor: 'pointer',
|
|
18471
|
+
fontSize: '14px',
|
|
18472
|
+
fontWeight: '500',
|
|
18473
|
+
color: '#374151',
|
|
18474
|
+
transition: 'all 0.2s ease',
|
|
18387
18475
|
},
|
|
18388
18476
|
PrimaryButton: {
|
|
18389
|
-
padding:
|
|
18390
|
-
margin:
|
|
18391
|
-
border:
|
|
18392
|
-
borderRadius:
|
|
18393
|
-
backgroundColor:
|
|
18394
|
-
color:
|
|
18395
|
-
cursor:
|
|
18396
|
-
fontSize:
|
|
18397
|
-
fontWeight:
|
|
18398
|
-
transition:
|
|
18477
|
+
padding: '10px 20px',
|
|
18478
|
+
margin: '0 4px',
|
|
18479
|
+
border: '1px solid #3b82f6',
|
|
18480
|
+
borderRadius: '6px',
|
|
18481
|
+
backgroundColor: '#3b82f6',
|
|
18482
|
+
color: 'white',
|
|
18483
|
+
cursor: 'pointer',
|
|
18484
|
+
fontSize: '14px',
|
|
18485
|
+
fontWeight: '500',
|
|
18486
|
+
transition: 'all 0.2s ease',
|
|
18399
18487
|
},
|
|
18400
18488
|
ButtonsDiv: {
|
|
18401
|
-
display:
|
|
18402
|
-
justifyContent:
|
|
18403
|
-
gap:
|
|
18404
|
-
marginTop:
|
|
18405
|
-
paddingTop:
|
|
18489
|
+
display: 'flex',
|
|
18490
|
+
justifyContent: 'flex-end',
|
|
18491
|
+
gap: '12px',
|
|
18492
|
+
marginTop: '24px',
|
|
18493
|
+
paddingTop: '20px',
|
|
18406
18494
|
},
|
|
18407
18495
|
Label: {
|
|
18408
|
-
display:
|
|
18409
|
-
marginBottom:
|
|
18410
|
-
fontSize:
|
|
18411
|
-
fontWeight:
|
|
18412
|
-
color:
|
|
18496
|
+
display: 'block',
|
|
18497
|
+
marginBottom: '12px',
|
|
18498
|
+
fontSize: '14px',
|
|
18499
|
+
fontWeight: '500',
|
|
18500
|
+
color: '#333',
|
|
18413
18501
|
},
|
|
18414
18502
|
WindowHeader: {
|
|
18415
|
-
margin:
|
|
18416
|
-
fontSize:
|
|
18417
|
-
fontWeight:
|
|
18418
|
-
color:
|
|
18419
|
-
borderBottom:
|
|
18420
|
-
paddingBottom:
|
|
18503
|
+
margin: '0 0 20px 0',
|
|
18504
|
+
fontSize: '18px',
|
|
18505
|
+
fontWeight: '600',
|
|
18506
|
+
color: '#333',
|
|
18507
|
+
borderBottom: '1px solid #eee',
|
|
18508
|
+
paddingBottom: '10px',
|
|
18421
18509
|
},
|
|
18422
18510
|
// OAuth Provider Button Styles
|
|
18423
18511
|
ProviderButton: {
|
|
18424
|
-
display:
|
|
18425
|
-
alignItems:
|
|
18426
|
-
justifyContent:
|
|
18427
|
-
width:
|
|
18428
|
-
padding:
|
|
18429
|
-
marginBottom:
|
|
18430
|
-
border:
|
|
18431
|
-
borderRadius:
|
|
18432
|
-
backgroundColor:
|
|
18433
|
-
cursor:
|
|
18434
|
-
fontSize:
|
|
18435
|
-
fontWeight:
|
|
18436
|
-
color:
|
|
18437
|
-
transition:
|
|
18438
|
-
gap:
|
|
18512
|
+
display: 'flex',
|
|
18513
|
+
alignItems: 'center',
|
|
18514
|
+
justifyContent: 'center',
|
|
18515
|
+
width: '100%',
|
|
18516
|
+
padding: '12px 16px',
|
|
18517
|
+
marginBottom: '10px',
|
|
18518
|
+
border: '1px solid #d1d5db',
|
|
18519
|
+
borderRadius: '6px',
|
|
18520
|
+
backgroundColor: '#ffffff',
|
|
18521
|
+
cursor: 'pointer',
|
|
18522
|
+
fontSize: '14px',
|
|
18523
|
+
fontWeight: '500',
|
|
18524
|
+
color: '#374151',
|
|
18525
|
+
transition: 'all 0.2s ease',
|
|
18526
|
+
gap: '12px',
|
|
18439
18527
|
},
|
|
18440
18528
|
ProviderButtonIcon: {
|
|
18441
|
-
width:
|
|
18442
|
-
height:
|
|
18529
|
+
width: '20px',
|
|
18530
|
+
height: '20px',
|
|
18443
18531
|
flexShrink: 0,
|
|
18444
|
-
display:
|
|
18445
|
-
alignItems:
|
|
18446
|
-
justifyContent:
|
|
18532
|
+
display: 'flex',
|
|
18533
|
+
alignItems: 'center',
|
|
18534
|
+
justifyContent: 'center',
|
|
18447
18535
|
},
|
|
18448
18536
|
ProviderButtonText: {
|
|
18449
18537
|
flex: 1,
|
|
18450
|
-
textAlign:
|
|
18538
|
+
textAlign: 'left',
|
|
18451
18539
|
},
|
|
18452
18540
|
// Provider-specific colors
|
|
18453
18541
|
ProviderGoogle: {
|
|
18454
|
-
backgroundColor:
|
|
18455
|
-
border:
|
|
18456
|
-
color:
|
|
18542
|
+
backgroundColor: '#ffffff',
|
|
18543
|
+
border: '1px solid #dadce0',
|
|
18544
|
+
color: '#3c4043',
|
|
18457
18545
|
},
|
|
18458
18546
|
ProviderGitHub: {
|
|
18459
|
-
backgroundColor:
|
|
18460
|
-
border:
|
|
18461
|
-
color:
|
|
18547
|
+
backgroundColor: '#ffffff',
|
|
18548
|
+
border: '1px solid #dadce0',
|
|
18549
|
+
color: '#181717',
|
|
18462
18550
|
},
|
|
18463
18551
|
ProviderMicrosoft: {
|
|
18464
|
-
backgroundColor:
|
|
18465
|
-
border:
|
|
18466
|
-
color:
|
|
18552
|
+
backgroundColor: '#ffffff',
|
|
18553
|
+
border: '1px solid #dadce0',
|
|
18554
|
+
color: '#5e5e5e',
|
|
18467
18555
|
},
|
|
18468
18556
|
ProviderApple: {
|
|
18469
|
-
backgroundColor:
|
|
18470
|
-
border:
|
|
18471
|
-
color:
|
|
18557
|
+
backgroundColor: '#000000',
|
|
18558
|
+
border: '1px solid #000000',
|
|
18559
|
+
color: '#ffffff',
|
|
18472
18560
|
},
|
|
18473
18561
|
ProviderCustom: {
|
|
18474
|
-
backgroundColor:
|
|
18475
|
-
border:
|
|
18476
|
-
color:
|
|
18562
|
+
backgroundColor: '#ffffff',
|
|
18563
|
+
border: '1px solid #dadce0',
|
|
18564
|
+
color: '#181717',
|
|
18477
18565
|
},
|
|
18478
18566
|
// Divider styles
|
|
18479
18567
|
Divider: {
|
|
18480
|
-
display:
|
|
18481
|
-
alignItems:
|
|
18482
|
-
margin:
|
|
18483
|
-
color:
|
|
18484
|
-
fontSize:
|
|
18568
|
+
display: 'flex',
|
|
18569
|
+
alignItems: 'center',
|
|
18570
|
+
margin: '20px 0',
|
|
18571
|
+
color: '#6b7280',
|
|
18572
|
+
fontSize: '13px',
|
|
18485
18573
|
},
|
|
18486
18574
|
DividerLine: {
|
|
18487
18575
|
flex: 1,
|
|
18488
|
-
height:
|
|
18489
|
-
backgroundColor:
|
|
18576
|
+
height: '1px',
|
|
18577
|
+
backgroundColor: '#e5e7eb',
|
|
18490
18578
|
},
|
|
18491
18579
|
DividerText: {
|
|
18492
|
-
padding:
|
|
18493
|
-
color:
|
|
18580
|
+
padding: '0 12px',
|
|
18581
|
+
color: '#9ca3af',
|
|
18494
18582
|
},
|
|
18495
18583
|
// OTP Button (Continue with email)
|
|
18496
18584
|
OtpButton: {
|
|
18497
|
-
display:
|
|
18498
|
-
alignItems:
|
|
18499
|
-
justifyContent:
|
|
18500
|
-
width:
|
|
18501
|
-
padding:
|
|
18502
|
-
border:
|
|
18503
|
-
borderRadius:
|
|
18504
|
-
backgroundColor:
|
|
18505
|
-
cursor:
|
|
18506
|
-
fontSize:
|
|
18507
|
-
fontWeight:
|
|
18508
|
-
color:
|
|
18509
|
-
transition:
|
|
18510
|
-
gap:
|
|
18585
|
+
display: 'flex',
|
|
18586
|
+
alignItems: 'center',
|
|
18587
|
+
justifyContent: 'center',
|
|
18588
|
+
width: '100%',
|
|
18589
|
+
padding: '12px 16px',
|
|
18590
|
+
border: '1px solid #d1d5db',
|
|
18591
|
+
borderRadius: '6px',
|
|
18592
|
+
backgroundColor: '#f9fafb',
|
|
18593
|
+
cursor: 'pointer',
|
|
18594
|
+
fontSize: '14px',
|
|
18595
|
+
fontWeight: '500',
|
|
18596
|
+
color: '#374151',
|
|
18597
|
+
transition: 'all 0.2s ease',
|
|
18598
|
+
gap: '12px',
|
|
18511
18599
|
},
|
|
18512
18600
|
// Copy button for alerts with copyText
|
|
18513
18601
|
CopyButton: {
|
|
18514
|
-
display:
|
|
18515
|
-
alignItems:
|
|
18516
|
-
gap:
|
|
18517
|
-
padding:
|
|
18518
|
-
marginTop:
|
|
18519
|
-
border:
|
|
18520
|
-
borderRadius:
|
|
18521
|
-
backgroundColor:
|
|
18522
|
-
cursor:
|
|
18523
|
-
fontSize:
|
|
18524
|
-
fontWeight:
|
|
18525
|
-
color:
|
|
18526
|
-
transition:
|
|
18527
|
-
fontFamily:
|
|
18602
|
+
display: 'inline-flex',
|
|
18603
|
+
alignItems: 'center',
|
|
18604
|
+
gap: '4px',
|
|
18605
|
+
padding: '4px 10px',
|
|
18606
|
+
marginTop: '8px',
|
|
18607
|
+
border: '1px solid #d1d5db',
|
|
18608
|
+
borderRadius: '4px',
|
|
18609
|
+
backgroundColor: '#f9fafb',
|
|
18610
|
+
cursor: 'pointer',
|
|
18611
|
+
fontSize: '12px',
|
|
18612
|
+
fontWeight: '500',
|
|
18613
|
+
color: '#374151',
|
|
18614
|
+
transition: 'all 0.15s ease',
|
|
18615
|
+
fontFamily: 'monospace',
|
|
18528
18616
|
},
|
|
18529
18617
|
CopyButtonCopied: {
|
|
18530
|
-
display:
|
|
18531
|
-
alignItems:
|
|
18532
|
-
gap:
|
|
18533
|
-
padding:
|
|
18534
|
-
marginTop:
|
|
18535
|
-
border:
|
|
18536
|
-
borderRadius:
|
|
18537
|
-
backgroundColor:
|
|
18538
|
-
cursor:
|
|
18539
|
-
fontSize:
|
|
18540
|
-
fontWeight:
|
|
18541
|
-
color:
|
|
18542
|
-
fontFamily:
|
|
18618
|
+
display: 'inline-flex',
|
|
18619
|
+
alignItems: 'center',
|
|
18620
|
+
gap: '4px',
|
|
18621
|
+
padding: '4px 10px',
|
|
18622
|
+
marginTop: '8px',
|
|
18623
|
+
border: '1px solid #22c55e',
|
|
18624
|
+
borderRadius: '4px',
|
|
18625
|
+
backgroundColor: '#f0fdf4',
|
|
18626
|
+
cursor: 'default',
|
|
18627
|
+
fontSize: '12px',
|
|
18628
|
+
fontWeight: '500',
|
|
18629
|
+
color: '#16a34a',
|
|
18630
|
+
fontFamily: 'monospace',
|
|
18543
18631
|
}};
|
|
18544
18632
|
|
|
18545
|
-
function Dialog({ children, className }) {
|
|
18633
|
+
function Dialog({ children, className, }) {
|
|
18546
18634
|
return (_$1("div", { className: `dexie-dialog ${className || ''}` },
|
|
18547
18635
|
_$1("div", { style: Styles.Darken }),
|
|
18548
18636
|
_$1("div", { style: Styles.DialogOuter },
|
|
@@ -18566,7 +18654,7 @@
|
|
|
18566
18654
|
* @returns A final message where parameters have been replaced with values.
|
|
18567
18655
|
*/
|
|
18568
18656
|
function resolveText({ message, messageCode, messageParams }) {
|
|
18569
|
-
return message.replace(/\{\w+\}/
|
|
18657
|
+
return message.replace(/\{\w+\}/gi, (n) => messageParams[n.substring(1, n.length - 1)]);
|
|
18570
18658
|
}
|
|
18571
18659
|
|
|
18572
18660
|
/** Get style based on styleHint (for provider branding, etc.) */
|
|
@@ -18653,13 +18741,13 @@
|
|
|
18653
18741
|
alerts.map((alert, idx) => (_$1("div", { key: idx },
|
|
18654
18742
|
_$1("p", { style: Styles.Alert[alert.type] }, resolveText(alert)),
|
|
18655
18743
|
alert.copyText && _$1(CopyButton, { text: alert.copyText })))),
|
|
18656
|
-
hasOptions && (_$1("div", { class: "dxc-options" }, hasMultipleGroups
|
|
18657
|
-
|
|
18658
|
-
|
|
18659
|
-
|
|
18660
|
-
|
|
18661
|
-
|
|
18662
|
-
|
|
18744
|
+
hasOptions && (_$1("div", { class: "dxc-options" }, hasMultipleGroups
|
|
18745
|
+
? // Render with dividers between groups
|
|
18746
|
+
Array.from(optionGroups.entries()).map(([groupName, groupOptions], groupIdx) => (_$1(k$1, { key: groupName },
|
|
18747
|
+
groupIdx > 0 && _$1(Divider, null),
|
|
18748
|
+
groupOptions.map((option) => (_$1(OptionButton, { key: `${option.name}-${option.value}`, option: option, onClick: () => handleOptionClick(option) }))))))
|
|
18749
|
+
: // Simple case: all options in one group
|
|
18750
|
+
options.map((option) => (_$1(OptionButton, { key: `${option.name}-${option.value}`, option: option, onClick: () => handleOptionClick(option) }))))),
|
|
18663
18751
|
hasOptions && hasFields && _$1(Divider, null),
|
|
18664
18752
|
hasFields && (_$1("form", { onSubmit: (ev) => {
|
|
18665
18753
|
ev.preventDefault();
|
|
@@ -18671,7 +18759,8 @@
|
|
|
18671
18759
|
const value = valueTransformer(type, (_a = ev.target) === null || _a === void 0 ? void 0 : _a['value']);
|
|
18672
18760
|
let updatedParams = Object.assign(Object.assign({}, params), { [fieldName]: value });
|
|
18673
18761
|
setParams(updatedParams);
|
|
18674
|
-
if (type === 'otp' &&
|
|
18762
|
+
if (type === 'otp' &&
|
|
18763
|
+
(value === null || value === void 0 ? void 0 : value.trim().length) === OTP_LENGTH) {
|
|
18675
18764
|
// Auto-submit when OTP is filled in.
|
|
18676
18765
|
onSubmit(updatedParams);
|
|
18677
18766
|
}
|
|
@@ -18713,7 +18802,10 @@
|
|
|
18713
18802
|
const handleClick = () => {
|
|
18714
18803
|
var _a;
|
|
18715
18804
|
if (typeof navigator !== 'undefined' && ((_a = navigator.clipboard) === null || _a === void 0 ? void 0 : _a.writeText)) {
|
|
18716
|
-
navigator.clipboard
|
|
18805
|
+
navigator.clipboard
|
|
18806
|
+
.writeText(text)
|
|
18807
|
+
.then(scheduleCopiedReset)
|
|
18808
|
+
.catch(() => {
|
|
18717
18809
|
fallbackCopy(text, scheduleCopiedReset);
|
|
18718
18810
|
});
|
|
18719
18811
|
}
|
|
@@ -18784,7 +18876,7 @@
|
|
|
18784
18876
|
},
|
|
18785
18877
|
get closed() {
|
|
18786
18878
|
return closed;
|
|
18787
|
-
}
|
|
18879
|
+
},
|
|
18788
18880
|
};
|
|
18789
18881
|
}
|
|
18790
18882
|
|
|
@@ -18829,14 +18921,14 @@
|
|
|
18829
18921
|
lazyWebSocketStatus,
|
|
18830
18922
|
db.syncStateChangedEvent.pipe(operators.startWith({ phase: 'initial' })),
|
|
18831
18923
|
getCurrentUserEmitter(db.dx._novip),
|
|
18832
|
-
userIsReallyActive
|
|
18924
|
+
userIsReallyActive,
|
|
18833
18925
|
]).pipe(operators.map(([status, syncState, user, userIsActive]) => {
|
|
18834
18926
|
var _a;
|
|
18835
18927
|
if (((_a = user.license) === null || _a === void 0 ? void 0 : _a.status) && user.license.status !== 'ok') {
|
|
18836
18928
|
return {
|
|
18837
18929
|
phase: 'offline',
|
|
18838
18930
|
status: 'offline',
|
|
18839
|
-
license: user.license.status
|
|
18931
|
+
license: user.license.status,
|
|
18840
18932
|
};
|
|
18841
18933
|
}
|
|
18842
18934
|
let { phase, error, progress } = syncState;
|
|
@@ -18856,7 +18948,8 @@
|
|
|
18856
18948
|
}
|
|
18857
18949
|
const previousPhase = db.cloud.syncState.value.phase;
|
|
18858
18950
|
//const previousStatus = db.cloud.syncState.value.status;
|
|
18859
|
-
if (previousPhase === 'error' &&
|
|
18951
|
+
if (previousPhase === 'error' &&
|
|
18952
|
+
(syncState.phase === 'pushing' || syncState.phase === 'pulling')) {
|
|
18860
18953
|
// We were in an errored state but is now doing sync. Show "connecting" icon.
|
|
18861
18954
|
adjustedStatus = 'connecting';
|
|
18862
18955
|
}
|
|
@@ -18871,7 +18964,7 @@
|
|
|
18871
18964
|
error,
|
|
18872
18965
|
progress,
|
|
18873
18966
|
status: isOnline ? adjustedStatus : 'offline',
|
|
18874
|
-
license: 'ok'
|
|
18967
|
+
license: 'ok',
|
|
18875
18968
|
};
|
|
18876
18969
|
return retState;
|
|
18877
18970
|
}));
|
|
@@ -18892,7 +18985,7 @@
|
|
|
18892
18985
|
},
|
|
18893
18986
|
complete() {
|
|
18894
18987
|
observer.complete();
|
|
18895
|
-
}
|
|
18988
|
+
},
|
|
18896
18989
|
});
|
|
18897
18990
|
if (!didEmit && !subscription.closed) {
|
|
18898
18991
|
observer.next(currentValue);
|
|
@@ -19133,7 +19226,9 @@
|
|
|
19133
19226
|
const realm = permissionsLookup[realmId || dexie.cloud.currentUserId];
|
|
19134
19227
|
if (!realm)
|
|
19135
19228
|
return new PermissionChecker({}, tableName, !owner || owner === dexie.cloud.currentUserId);
|
|
19136
|
-
return new PermissionChecker(realm.permissions, tableName, realmId === undefined ||
|
|
19229
|
+
return new PermissionChecker(realm.permissions, tableName, realmId === undefined ||
|
|
19230
|
+
realmId === dexie.cloud.currentUserId ||
|
|
19231
|
+
owner === dexie.cloud.currentUserId);
|
|
19137
19232
|
};
|
|
19138
19233
|
const o = source.pipe(operators.map(mapper));
|
|
19139
19234
|
o.getValue = () => mapper(source.getValue());
|
|
@@ -19175,7 +19270,19 @@
|
|
|
19175
19270
|
return; // The table that holds the doc is not marked for sync - leave it to dexie. No syncing, no awareness.
|
|
19176
19271
|
}
|
|
19177
19272
|
let awareness;
|
|
19273
|
+
const existingDescriptor = Object.getOwnPropertyDescriptor(provider, 'awareness');
|
|
19274
|
+
if (existingDescriptor) {
|
|
19275
|
+
// Provider already initialized — likely a leaked handler from a previous db instance
|
|
19276
|
+
// (e.g. HMR where db.close() didn't fire). Destroy the stale awareness so the new
|
|
19277
|
+
// handler can take over cleanly.
|
|
19278
|
+
const staleAwareness = provider.awareness;
|
|
19279
|
+
if (staleAwareness) {
|
|
19280
|
+
staleAwareness.destroy();
|
|
19281
|
+
awarenessWeakMap.delete(doc);
|
|
19282
|
+
}
|
|
19283
|
+
}
|
|
19178
19284
|
Object.defineProperty(provider, 'awareness', {
|
|
19285
|
+
configurable: true,
|
|
19179
19286
|
get() {
|
|
19180
19287
|
if (awareness)
|
|
19181
19288
|
return awareness;
|
|
@@ -19358,10 +19465,12 @@
|
|
|
19358
19465
|
const { code, provider, state, error } = payload;
|
|
19359
19466
|
// Check for error first
|
|
19360
19467
|
if (error) {
|
|
19361
|
-
if (error.toLowerCase().includes('access_denied') ||
|
|
19468
|
+
if (error.toLowerCase().includes('access_denied') ||
|
|
19469
|
+
error.toLowerCase().includes('access denied')) {
|
|
19362
19470
|
throw new OAuthError('access_denied', provider, error);
|
|
19363
19471
|
}
|
|
19364
|
-
if (error.toLowerCase().includes('email') &&
|
|
19472
|
+
if (error.toLowerCase().includes('email') &&
|
|
19473
|
+
error.toLowerCase().includes('verif')) {
|
|
19365
19474
|
throw new OAuthError('email_not_verified', provider, error);
|
|
19366
19475
|
}
|
|
19367
19476
|
throw new OAuthError('provider_error', provider, error);
|
|
@@ -19387,7 +19496,9 @@
|
|
|
19387
19496
|
return;
|
|
19388
19497
|
}
|
|
19389
19498
|
url.searchParams.delete('dxc-auth');
|
|
19390
|
-
const cleanUrl = url.pathname +
|
|
19499
|
+
const cleanUrl = url.pathname +
|
|
19500
|
+
(url.searchParams.toString() ? `?${url.searchParams.toString()}` : '') +
|
|
19501
|
+
url.hash;
|
|
19391
19502
|
window.history.replaceState(null, '', cleanUrl);
|
|
19392
19503
|
}
|
|
19393
19504
|
|
|
@@ -19436,7 +19547,7 @@
|
|
|
19436
19547
|
const downloading$ = createDownloadingState();
|
|
19437
19548
|
dexie.cloud = {
|
|
19438
19549
|
// @ts-ignore
|
|
19439
|
-
version: "4.4.
|
|
19550
|
+
version: "4.4.7",
|
|
19440
19551
|
options: Object.assign({}, DEFAULT_OPTIONS),
|
|
19441
19552
|
schema: null,
|
|
19442
19553
|
get currentUserId() {
|
|
@@ -19492,7 +19603,10 @@
|
|
|
19492
19603
|
const callback = parseOAuthCallback();
|
|
19493
19604
|
if (callback) {
|
|
19494
19605
|
// Store the pending auth code for processing when db is ready
|
|
19495
|
-
pendingOAuthCode = {
|
|
19606
|
+
pendingOAuthCode = {
|
|
19607
|
+
code: callback.code,
|
|
19608
|
+
provider: callback.provider,
|
|
19609
|
+
};
|
|
19496
19610
|
console.debug('[dexie-cloud] OAuth callback detected, auth code stored for processing');
|
|
19497
19611
|
}
|
|
19498
19612
|
}
|
|
@@ -19609,7 +19723,7 @@
|
|
|
19609
19723
|
if (eagerBlobDownloadInFlight)
|
|
19610
19724
|
return;
|
|
19611
19725
|
eagerBlobDownloadInFlight = Dexie.ignoreTransaction(() => downloadUnresolvedBlobs(db, downloading$))
|
|
19612
|
-
.catch(err => {
|
|
19726
|
+
.catch((err) => {
|
|
19613
19727
|
console.error('[dexie-cloud] Eager blob download failed:', err);
|
|
19614
19728
|
})
|
|
19615
19729
|
.finally(() => {
|
|
@@ -19702,7 +19816,10 @@
|
|
|
19702
19816
|
// Let's assign all props as the newPersistedSchems should be what we should be working with.
|
|
19703
19817
|
Object.assign(schema, newPersistedSchema);
|
|
19704
19818
|
}
|
|
19705
|
-
return [
|
|
19819
|
+
return [
|
|
19820
|
+
persistedSyncState === null || persistedSyncState === void 0 ? void 0 : persistedSyncState.initiallySynced,
|
|
19821
|
+
persistedSyncState === null || persistedSyncState === void 0 ? void 0 : persistedSyncState.realms,
|
|
19822
|
+
];
|
|
19706
19823
|
}));
|
|
19707
19824
|
if (initiallySynced) {
|
|
19708
19825
|
db.setInitiallySynced(true);
|
|
@@ -19711,8 +19828,10 @@
|
|
|
19711
19828
|
// Manage CurrentUser observable:
|
|
19712
19829
|
throwIfClosed();
|
|
19713
19830
|
if (!db.cloud.isServiceWorkerDB) {
|
|
19714
|
-
subscriptions.push(Dexie.liveQuery(() => db.getCurrentUser().then(user => {
|
|
19715
|
-
if (!user.isLoggedIn &&
|
|
19831
|
+
subscriptions.push(Dexie.liveQuery(() => db.getCurrentUser().then((user) => {
|
|
19832
|
+
if (!user.isLoggedIn &&
|
|
19833
|
+
typeof location !== 'undefined' &&
|
|
19834
|
+
/dxc-auth\=/.test(location.search)) {
|
|
19716
19835
|
// Still loading user because OAuth redirect just happened.
|
|
19717
19836
|
// Keep isLoading true.
|
|
19718
19837
|
return Object.assign(Object.assign({}, user), { isLoading: true });
|
|
@@ -19750,7 +19869,7 @@
|
|
|
19750
19869
|
type: 'error',
|
|
19751
19870
|
messageCode: 'GENERIC_ERROR',
|
|
19752
19871
|
message: error.message,
|
|
19753
|
-
messageParams: { provider: error.provider || 'unknown' }
|
|
19872
|
+
messageParams: { provider: error.provider || 'unknown' },
|
|
19754
19873
|
});
|
|
19755
19874
|
// Clean up URL (remove dxc-auth param)
|
|
19756
19875
|
cleanupOAuthUrl();
|
|
@@ -19800,7 +19919,8 @@
|
|
|
19800
19919
|
}
|
|
19801
19920
|
}
|
|
19802
19921
|
}
|
|
19803
|
-
if (user.isLoggedIn &&
|
|
19922
|
+
if (user.isLoggedIn &&
|
|
19923
|
+
(!lastSyncedRealms || !lastSyncedRealms.includes(user.userId))) {
|
|
19804
19924
|
// User has been logged in but this is not reflected in the sync state.
|
|
19805
19925
|
// This can happen if page is reloaded after login but before the sync call following
|
|
19806
19926
|
// the login was complete.
|
|
@@ -19863,7 +19983,7 @@
|
|
|
19863
19983
|
}
|
|
19864
19984
|
}
|
|
19865
19985
|
// @ts-ignore
|
|
19866
|
-
dexieCloud.version = "4.4.
|
|
19986
|
+
dexieCloud.version = "4.4.7";
|
|
19867
19987
|
Dexie.Cloud = dexieCloud;
|
|
19868
19988
|
|
|
19869
19989
|
// In case the SW lives for a while, let it reuse already opened connections:
|
|
@@ -19955,14 +20075,14 @@
|
|
|
19955
20075
|
console.debug('SW "sync" Event', event.tag);
|
|
19956
20076
|
const dbName = getDbNameFromTag(event.tag);
|
|
19957
20077
|
if (dbName) {
|
|
19958
|
-
event.waitUntil(syncDB(dbName,
|
|
20078
|
+
event.waitUntil(syncDB(dbName, 'push')); // The purpose of sync events are "push"
|
|
19959
20079
|
}
|
|
19960
20080
|
});
|
|
19961
20081
|
self.addEventListener('periodicsync', (event) => {
|
|
19962
20082
|
console.debug('SW "periodicsync" Event', event.tag);
|
|
19963
20083
|
const dbName = getDbNameFromTag(event.tag);
|
|
19964
20084
|
if (dbName) {
|
|
19965
|
-
event.waitUntil(syncDB(dbName,
|
|
20085
|
+
event.waitUntil(syncDB(dbName, 'pull')); // The purpose of periodic sync events are "pull"
|
|
19966
20086
|
}
|
|
19967
20087
|
});
|
|
19968
20088
|
self.addEventListener('message', (event) => {
|
|
@@ -19972,7 +20092,7 @@
|
|
|
19972
20092
|
// Mimic background sync behavior - retry in X minutes on failure.
|
|
19973
20093
|
// But lesser timeout and more number of times.
|
|
19974
20094
|
const syncAndRetry = (num = 1) => {
|
|
19975
|
-
return syncDB(dbName, event.data.purpose ||
|
|
20095
|
+
return syncDB(dbName, event.data.purpose || 'pull').catch((e) => __awaiter(void 0, void 0, void 0, function* () {
|
|
19976
20096
|
if (num === 3)
|
|
19977
20097
|
throw e;
|
|
19978
20098
|
yield sleep(60000); // 1 minute
|
|
@@ -19980,10 +20100,10 @@
|
|
|
19980
20100
|
}));
|
|
19981
20101
|
};
|
|
19982
20102
|
if ('waitUntil' in event) {
|
|
19983
|
-
event.waitUntil(syncAndRetry().catch(error => console.error(error)));
|
|
20103
|
+
event.waitUntil(syncAndRetry().catch((error) => console.error(error)));
|
|
19984
20104
|
}
|
|
19985
20105
|
else {
|
|
19986
|
-
syncAndRetry().catch(error => console.error(error));
|
|
20106
|
+
syncAndRetry().catch((error) => console.error(error));
|
|
19987
20107
|
}
|
|
19988
20108
|
}
|
|
19989
20109
|
});
|