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
|
*
|
|
@@ -114,7 +114,7 @@ function escapeDollarProps(value) {
|
|
|
114
114
|
const keys = Object.keys(value);
|
|
115
115
|
let dollarKeys = null;
|
|
116
116
|
for (let i = 0, l = keys.length; i < l; ++i) {
|
|
117
|
-
if (keys[i][0] ===
|
|
117
|
+
if (keys[i][0] === '$') {
|
|
118
118
|
dollarKeys = dollarKeys || [];
|
|
119
119
|
dollarKeys.push(keys[i]);
|
|
120
120
|
}
|
|
@@ -126,7 +126,7 @@ function escapeDollarProps(value) {
|
|
|
126
126
|
delete clone[k];
|
|
127
127
|
}
|
|
128
128
|
for (const k of dollarKeys) {
|
|
129
|
-
clone[
|
|
129
|
+
clone['$' + k] = value[k];
|
|
130
130
|
}
|
|
131
131
|
return clone;
|
|
132
132
|
}
|
|
@@ -177,7 +177,7 @@ function TypesonSimplified(...typeDefsInputs) {
|
|
|
177
177
|
//
|
|
178
178
|
// Child part
|
|
179
179
|
//
|
|
180
|
-
if (value === undefined || (key[0] ===
|
|
180
|
+
if (value === undefined || (key[0] === '$' && key !== '$t')) {
|
|
181
181
|
top = stack[stack.length - 1];
|
|
182
182
|
let deletes;
|
|
183
183
|
let mods;
|
|
@@ -188,7 +188,7 @@ function TypesonSimplified(...typeDefsInputs) {
|
|
|
188
188
|
else {
|
|
189
189
|
stack.push([this, (deletes = []), (mods = {})]);
|
|
190
190
|
}
|
|
191
|
-
if (key[0] ===
|
|
191
|
+
if (key[0] === '$' && key !== '$t') {
|
|
192
192
|
// Unescape props (also preserves undefined if this is a combo)
|
|
193
193
|
deletes.push(key);
|
|
194
194
|
mods[key.substr(1)] = value;
|
|
@@ -205,8 +205,8 @@ function TypesonSimplified(...typeDefsInputs) {
|
|
|
205
205
|
function getTypeDef(realVal) {
|
|
206
206
|
const type = typeof realVal;
|
|
207
207
|
switch (typeof realVal) {
|
|
208
|
-
case
|
|
209
|
-
case
|
|
208
|
+
case 'object':
|
|
209
|
+
case 'function': {
|
|
210
210
|
// "object", "function", null
|
|
211
211
|
if (realVal === null)
|
|
212
212
|
return null;
|
|
@@ -222,7 +222,7 @@ function TypesonSimplified(...typeDefsInputs) {
|
|
|
222
222
|
if (!typeDef) {
|
|
223
223
|
typeDef = Array.isArray(realVal)
|
|
224
224
|
? null
|
|
225
|
-
: typeof realVal ===
|
|
225
|
+
: typeof realVal === 'function'
|
|
226
226
|
? typeDefs.function || null
|
|
227
227
|
: ObjectDef;
|
|
228
228
|
}
|
|
@@ -398,13 +398,13 @@ TSONRef.resolver = null;
|
|
|
398
398
|
|
|
399
399
|
function readBlobSync(b) {
|
|
400
400
|
const req = new XMLHttpRequest();
|
|
401
|
-
req.overrideMimeType(
|
|
401
|
+
req.overrideMimeType('text/plain; charset=x-user-defined');
|
|
402
402
|
const url = URL.createObjectURL(b);
|
|
403
403
|
try {
|
|
404
|
-
req.open(
|
|
404
|
+
req.open('GET', url, false); // Sync
|
|
405
405
|
req.send();
|
|
406
406
|
if (req.status !== 200 && req.status !== 0) {
|
|
407
|
-
throw new Error(
|
|
407
|
+
throw new Error('Bad Blob access: ' + req.status);
|
|
408
408
|
}
|
|
409
409
|
return req.responseText;
|
|
410
410
|
}
|
|
@@ -418,11 +418,11 @@ const numberTypeDef = {
|
|
|
418
418
|
replace: (num) => {
|
|
419
419
|
switch (true) {
|
|
420
420
|
case isNaN(num):
|
|
421
|
-
return { $t:
|
|
421
|
+
return { $t: 'number', v: 'NaN' };
|
|
422
422
|
case num === Infinity:
|
|
423
|
-
return { $t:
|
|
423
|
+
return { $t: 'number', v: 'Infinity' };
|
|
424
424
|
case num === -Infinity:
|
|
425
|
-
return { $t:
|
|
425
|
+
return { $t: 'number', v: '-Infinity' };
|
|
426
426
|
default:
|
|
427
427
|
return num;
|
|
428
428
|
}
|
|
@@ -434,17 +434,17 @@ const numberTypeDef = {
|
|
|
434
434
|
const dateTypeDef = {
|
|
435
435
|
Date: {
|
|
436
436
|
replace: (date) => ({
|
|
437
|
-
$t:
|
|
438
|
-
v: isNaN(date.getTime()) ?
|
|
437
|
+
$t: 'Date',
|
|
438
|
+
v: isNaN(date.getTime()) ? 'NaN' : date.toISOString(),
|
|
439
439
|
}),
|
|
440
|
-
revive: ({ v }) => new Date(v ===
|
|
440
|
+
revive: ({ v }) => new Date(v === 'NaN' ? NaN : Date.parse(v)),
|
|
441
441
|
},
|
|
442
442
|
};
|
|
443
443
|
|
|
444
444
|
const setTypeDef = {
|
|
445
445
|
Set: {
|
|
446
446
|
replace: (set) => ({
|
|
447
|
-
$t:
|
|
447
|
+
$t: 'Set',
|
|
448
448
|
v: Array.from(set),
|
|
449
449
|
}),
|
|
450
450
|
revive: ({ v }) => new Set(v),
|
|
@@ -454,34 +454,34 @@ const setTypeDef = {
|
|
|
454
454
|
const mapTypeDef = {
|
|
455
455
|
Map: {
|
|
456
456
|
replace: (map) => ({
|
|
457
|
-
$t:
|
|
457
|
+
$t: 'Map',
|
|
458
458
|
v: Array.from(map.entries()),
|
|
459
459
|
}),
|
|
460
460
|
revive: ({ v }) => new Map(v),
|
|
461
461
|
},
|
|
462
462
|
};
|
|
463
463
|
|
|
464
|
-
const _global = typeof globalThis !==
|
|
464
|
+
const _global = typeof globalThis !== 'undefined' // All modern environments (node, bun, deno, browser, workers, webview etc)
|
|
465
465
|
? globalThis
|
|
466
|
-
: typeof self !==
|
|
466
|
+
: typeof self !== 'undefined' // Older browsers, workers, webview, window etc
|
|
467
467
|
? self
|
|
468
|
-
: typeof global !==
|
|
468
|
+
: typeof global !== 'undefined' // Older versions of node
|
|
469
469
|
? global
|
|
470
470
|
: undefined; // Unsupported environment. No idea to return 'this' since we are in a module or a function scope anyway.
|
|
471
471
|
|
|
472
472
|
const typedArrayTypeDefs = [
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
473
|
+
'Int8Array',
|
|
474
|
+
'Uint8Array',
|
|
475
|
+
'Uint8ClampedArray',
|
|
476
|
+
'Int16Array',
|
|
477
|
+
'Uint16Array',
|
|
478
|
+
'Int32Array',
|
|
479
|
+
'Uint32Array',
|
|
480
|
+
'Float32Array',
|
|
481
|
+
'Float64Array',
|
|
482
|
+
'DataView',
|
|
483
|
+
'BigInt64Array',
|
|
484
|
+
'BigUint64Array',
|
|
485
485
|
].reduce((specs, typeName) => ({
|
|
486
486
|
...specs,
|
|
487
487
|
[typeName]: {
|
|
@@ -509,10 +509,10 @@ const typedArrayTypeDefs = [
|
|
|
509
509
|
},
|
|
510
510
|
}), {});
|
|
511
511
|
|
|
512
|
-
const hasArrayBufferFromBase64 =
|
|
513
|
-
const hasArrayBufferToBase64 =
|
|
514
|
-
const b64decode = typeof Buffer !==
|
|
515
|
-
? (base64) => Buffer.from(base64,
|
|
512
|
+
const hasArrayBufferFromBase64 = 'fromBase64' in Uint8Array; // https://github.com/tc39/proposal-arraybuffer-base64;
|
|
513
|
+
const hasArrayBufferToBase64 = 'toBase64' in Uint8Array.prototype; // https://github.com/tc39/proposal-arraybuffer-base64;
|
|
514
|
+
const b64decode = typeof Buffer !== 'undefined'
|
|
515
|
+
? (base64) => Buffer.from(base64, 'base64') // Node
|
|
516
516
|
: hasArrayBufferFromBase64
|
|
517
517
|
? // @ts-ignore: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array/fromBase64
|
|
518
518
|
(base64) => Uint8Array.fromBase64(base64) // Modern javascript standard
|
|
@@ -526,14 +526,14 @@ const b64decode = typeof Buffer !== "undefined"
|
|
|
526
526
|
}
|
|
527
527
|
return bytes;
|
|
528
528
|
};
|
|
529
|
-
const b64encode = typeof Buffer !==
|
|
529
|
+
const b64encode = typeof Buffer !== 'undefined'
|
|
530
530
|
? (b) => {
|
|
531
531
|
// Node
|
|
532
532
|
if (ArrayBuffer.isView(b)) {
|
|
533
|
-
return Buffer.from(b.buffer, b.byteOffset, b.byteLength).toString(
|
|
533
|
+
return Buffer.from(b.buffer, b.byteOffset, b.byteLength).toString('base64');
|
|
534
534
|
}
|
|
535
535
|
else {
|
|
536
|
-
return Buffer.from(b).toString(
|
|
536
|
+
return Buffer.from(b).toString('base64');
|
|
537
537
|
}
|
|
538
538
|
}
|
|
539
539
|
: hasArrayBufferToBase64
|
|
@@ -552,7 +552,7 @@ const b64encode = typeof Buffer !== "undefined"
|
|
|
552
552
|
const chunk = u8a.subarray(i, i + CHUNK_SIZE);
|
|
553
553
|
strs.push(String.fromCharCode.apply(null, Array.from(chunk)));
|
|
554
554
|
}
|
|
555
|
-
return btoa(strs.join(
|
|
555
|
+
return btoa(strs.join(''));
|
|
556
556
|
};
|
|
557
557
|
|
|
558
558
|
function b64LexEncode(b) {
|
|
@@ -562,7 +562,7 @@ function b64LexDecode(b64Lex) {
|
|
|
562
562
|
return b64decode(lexToB64(b64Lex));
|
|
563
563
|
}
|
|
564
564
|
function b64ToLex(base64) {
|
|
565
|
-
var encoded =
|
|
565
|
+
var encoded = '';
|
|
566
566
|
for (var i = 0, length = base64.length; i < length; i++) {
|
|
567
567
|
encoded += ENCODE_TABLE[base64[i]];
|
|
568
568
|
}
|
|
@@ -570,81 +570,81 @@ function b64ToLex(base64) {
|
|
|
570
570
|
}
|
|
571
571
|
function lexToB64(base64lex) {
|
|
572
572
|
// only accept string input
|
|
573
|
-
if (typeof base64lex !==
|
|
574
|
-
throw new Error(
|
|
573
|
+
if (typeof base64lex !== 'string') {
|
|
574
|
+
throw new Error('invalid decoder input: ' + base64lex);
|
|
575
575
|
}
|
|
576
|
-
var base64 =
|
|
576
|
+
var base64 = '';
|
|
577
577
|
for (var i = 0, length = base64lex.length; i < length; i++) {
|
|
578
578
|
base64 += DECODE_TABLE[base64lex[i]];
|
|
579
579
|
}
|
|
580
580
|
return base64;
|
|
581
581
|
}
|
|
582
582
|
const DECODE_TABLE = {
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
A:
|
|
595
|
-
B:
|
|
596
|
-
C:
|
|
597
|
-
D:
|
|
598
|
-
E:
|
|
599
|
-
F:
|
|
600
|
-
G:
|
|
601
|
-
H:
|
|
602
|
-
I:
|
|
603
|
-
J:
|
|
604
|
-
K:
|
|
605
|
-
L:
|
|
606
|
-
M:
|
|
607
|
-
N:
|
|
608
|
-
O:
|
|
609
|
-
P:
|
|
610
|
-
Q:
|
|
611
|
-
R:
|
|
612
|
-
S:
|
|
613
|
-
T:
|
|
614
|
-
U:
|
|
615
|
-
V:
|
|
616
|
-
W:
|
|
617
|
-
X:
|
|
618
|
-
Y:
|
|
619
|
-
Z:
|
|
620
|
-
_:
|
|
621
|
-
a:
|
|
622
|
-
b:
|
|
623
|
-
c:
|
|
624
|
-
d:
|
|
625
|
-
e:
|
|
626
|
-
f:
|
|
627
|
-
g:
|
|
628
|
-
h:
|
|
629
|
-
i:
|
|
630
|
-
j:
|
|
631
|
-
k:
|
|
632
|
-
l:
|
|
633
|
-
m:
|
|
634
|
-
n:
|
|
635
|
-
o:
|
|
636
|
-
p:
|
|
637
|
-
q:
|
|
638
|
-
r:
|
|
639
|
-
s:
|
|
640
|
-
t:
|
|
641
|
-
u:
|
|
642
|
-
v:
|
|
643
|
-
w:
|
|
644
|
-
x:
|
|
645
|
-
y:
|
|
646
|
-
z:
|
|
647
|
-
|
|
583
|
+
'-': '=',
|
|
584
|
+
'0': 'A',
|
|
585
|
+
'1': 'B',
|
|
586
|
+
'2': 'C',
|
|
587
|
+
'3': 'D',
|
|
588
|
+
'4': 'E',
|
|
589
|
+
'5': 'F',
|
|
590
|
+
'6': 'G',
|
|
591
|
+
'7': 'H',
|
|
592
|
+
'8': 'I',
|
|
593
|
+
'9': 'J',
|
|
594
|
+
A: 'K',
|
|
595
|
+
B: 'L',
|
|
596
|
+
C: 'M',
|
|
597
|
+
D: 'N',
|
|
598
|
+
E: 'O',
|
|
599
|
+
F: 'P',
|
|
600
|
+
G: 'Q',
|
|
601
|
+
H: 'R',
|
|
602
|
+
I: 'S',
|
|
603
|
+
J: 'T',
|
|
604
|
+
K: 'U',
|
|
605
|
+
L: 'V',
|
|
606
|
+
M: 'W',
|
|
607
|
+
N: 'X',
|
|
608
|
+
O: 'Y',
|
|
609
|
+
P: 'Z',
|
|
610
|
+
Q: 'a',
|
|
611
|
+
R: 'b',
|
|
612
|
+
S: 'c',
|
|
613
|
+
T: 'd',
|
|
614
|
+
U: 'e',
|
|
615
|
+
V: 'f',
|
|
616
|
+
W: 'g',
|
|
617
|
+
X: 'h',
|
|
618
|
+
Y: 'i',
|
|
619
|
+
Z: 'j',
|
|
620
|
+
_: 'k',
|
|
621
|
+
a: 'l',
|
|
622
|
+
b: 'm',
|
|
623
|
+
c: 'n',
|
|
624
|
+
d: 'o',
|
|
625
|
+
e: 'p',
|
|
626
|
+
f: 'q',
|
|
627
|
+
g: 'r',
|
|
628
|
+
h: 's',
|
|
629
|
+
i: 't',
|
|
630
|
+
j: 'u',
|
|
631
|
+
k: 'v',
|
|
632
|
+
l: 'w',
|
|
633
|
+
m: 'x',
|
|
634
|
+
n: 'y',
|
|
635
|
+
o: 'z',
|
|
636
|
+
p: '0',
|
|
637
|
+
q: '1',
|
|
638
|
+
r: '2',
|
|
639
|
+
s: '3',
|
|
640
|
+
t: '4',
|
|
641
|
+
u: '5',
|
|
642
|
+
v: '6',
|
|
643
|
+
w: '7',
|
|
644
|
+
x: '8',
|
|
645
|
+
y: '9',
|
|
646
|
+
z: '+',
|
|
647
|
+
'|': '/',
|
|
648
648
|
};
|
|
649
649
|
const ENCODE_TABLE = {};
|
|
650
650
|
for (const c of Object.keys(DECODE_TABLE)) {
|
|
@@ -654,7 +654,7 @@ for (const c of Object.keys(DECODE_TABLE)) {
|
|
|
654
654
|
const arrayBufferTypeDef = {
|
|
655
655
|
ArrayBuffer: {
|
|
656
656
|
replace: (ab) => ({
|
|
657
|
-
$t:
|
|
657
|
+
$t: 'ArrayBuffer',
|
|
658
658
|
v: b64LexEncode(ab),
|
|
659
659
|
}),
|
|
660
660
|
revive: ({ v }) => {
|
|
@@ -677,9 +677,9 @@ function string2ArrayBuffer(str) {
|
|
|
677
677
|
|
|
678
678
|
const blobTypeDef = {
|
|
679
679
|
Blob: {
|
|
680
|
-
test: (blob, toStringTag) => toStringTag ===
|
|
680
|
+
test: (blob, toStringTag) => toStringTag === 'Blob' || blob instanceof FakeBlob,
|
|
681
681
|
replace: (blob) => ({
|
|
682
|
-
$t:
|
|
682
|
+
$t: 'Blob',
|
|
683
683
|
v: blob instanceof FakeBlob
|
|
684
684
|
? b64encode(blob.buf)
|
|
685
685
|
: b64encode(string2ArrayBuffer(readBlobSync(blob))),
|
|
@@ -690,7 +690,7 @@ const blobTypeDef = {
|
|
|
690
690
|
const buf = ab.buffer.byteLength === ab.byteLength
|
|
691
691
|
? ab.buffer
|
|
692
692
|
: ab.buffer.slice(ab.byteOffset, ab.byteOffset + ab.byteLength);
|
|
693
|
-
return typeof Blob !==
|
|
693
|
+
return typeof Blob !== 'undefined'
|
|
694
694
|
? new Blob([new Uint8Array(buf)], { type })
|
|
695
695
|
: new FakeBlob(buf, type);
|
|
696
696
|
},
|
|
@@ -709,15 +709,15 @@ const blobTypeDef = {
|
|
|
709
709
|
|
|
710
710
|
const fileTypeDef = {
|
|
711
711
|
File: {
|
|
712
|
-
test: (file, toStringTag) => toStringTag ===
|
|
712
|
+
test: (file, toStringTag) => toStringTag === 'File',
|
|
713
713
|
replace: (file) => ({
|
|
714
|
-
$t:
|
|
714
|
+
$t: 'File',
|
|
715
715
|
v: b64encode(string2ArrayBuffer(readBlobSync(file))),
|
|
716
716
|
type: file.type,
|
|
717
717
|
name: file.name,
|
|
718
718
|
lastModified: new Date(file.lastModified).toISOString(),
|
|
719
719
|
}),
|
|
720
|
-
revive: ({ type, v, name, lastModified }) => {
|
|
720
|
+
revive: ({ type, v, name, lastModified, }) => {
|
|
721
721
|
const ab = b64decode(v);
|
|
722
722
|
const buf = ab.buffer.byteLength === ab.byteLength
|
|
723
723
|
? ab.buffer
|
|
@@ -741,13 +741,13 @@ const fileTypeDef = {
|
|
|
741
741
|
const undefinedTypeDef = {
|
|
742
742
|
undefined: {
|
|
743
743
|
replace: () => ({
|
|
744
|
-
$t:
|
|
744
|
+
$t: 'undefined',
|
|
745
745
|
}),
|
|
746
746
|
revive: () => undefined,
|
|
747
747
|
},
|
|
748
748
|
};
|
|
749
749
|
|
|
750
|
-
const getRandomValues = typeof crypto !==
|
|
750
|
+
const getRandomValues = typeof crypto !== 'undefined'
|
|
751
751
|
? crypto.getRandomValues.bind(crypto)
|
|
752
752
|
: (buf) => {
|
|
753
753
|
for (let i = 0; i < buf.length; ++i) {
|
|
@@ -848,7 +848,7 @@ function setByKeyPath(obj, keyPath, value) {
|
|
|
848
848
|
var innerObj = obj[currentKeyPath];
|
|
849
849
|
//@ts-ignore: even if currentKeyPath would be numeric string and obj would be array - it works.
|
|
850
850
|
if (!innerObj || !hasOwn(obj, currentKeyPath))
|
|
851
|
-
innerObj =
|
|
851
|
+
innerObj = obj[currentKeyPath] = {};
|
|
852
852
|
setByKeyPath(innerObj, remainingKeyPath, value);
|
|
853
853
|
}
|
|
854
854
|
}
|
|
@@ -867,17 +867,23 @@ function setByKeyPath(obj, keyPath, value) {
|
|
|
867
867
|
}
|
|
868
868
|
}
|
|
869
869
|
}
|
|
870
|
-
const randomString$1 = typeof self !== 'undefined' && typeof crypto !== 'undefined'
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
870
|
+
const randomString$1 = typeof self !== 'undefined' && typeof crypto !== 'undefined'
|
|
871
|
+
? (bytes, randomFill = crypto.getRandomValues.bind(crypto)) => {
|
|
872
|
+
// Web
|
|
873
|
+
const buf = new Uint8Array(bytes);
|
|
874
|
+
randomFill(buf);
|
|
875
|
+
return self.btoa(String.fromCharCode.apply(null, buf));
|
|
876
|
+
}
|
|
877
|
+
: typeof Buffer !== 'undefined'
|
|
878
|
+
? (bytes, randomFill = simpleRandomFill) => {
|
|
879
|
+
// Node
|
|
880
|
+
const buf = Buffer.alloc(bytes);
|
|
881
|
+
randomFill(buf);
|
|
882
|
+
return buf.toString('base64');
|
|
883
|
+
}
|
|
884
|
+
: () => {
|
|
885
|
+
throw new Error('No implementation of randomString was found');
|
|
886
|
+
};
|
|
881
887
|
function simpleRandomFill(buf) {
|
|
882
888
|
for (let i = 0; i < buf.length; ++i) {
|
|
883
889
|
buf[i] = Math.floor(Math.random() * 256);
|
|
@@ -896,11 +902,13 @@ function simpleRandomFill(buf) {
|
|
|
896
902
|
* @returns
|
|
897
903
|
*/
|
|
898
904
|
function isValidSyncableID(id) {
|
|
899
|
-
if (typeof id ===
|
|
905
|
+
if (typeof id === 'string')
|
|
900
906
|
return true;
|
|
901
907
|
//if (validIDTypes[toStringTag(id)]) return true;
|
|
902
908
|
//if (Array.isArray(id)) return id.every((part) => isValidSyncableID(part));
|
|
903
|
-
if (Array.isArray(id) &&
|
|
909
|
+
if (Array.isArray(id) &&
|
|
910
|
+
id.some((key) => isValidSyncableID(key)) &&
|
|
911
|
+
id.every(isValidSyncableIDPart))
|
|
904
912
|
return true;
|
|
905
913
|
return false;
|
|
906
914
|
}
|
|
@@ -909,53 +917,53 @@ function isValidSyncableID(id) {
|
|
|
909
917
|
* For example, ArrayBuffer cannot be used (gives "object ArrayBuffer") but Uint8Array can be
|
|
910
918
|
* used (gives comma-delimited list of included bytes).
|
|
911
919
|
* 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.
|
|
912
|
-
*/
|
|
920
|
+
*/
|
|
913
921
|
function isValidSyncableIDPart(part) {
|
|
914
|
-
return typeof part ===
|
|
922
|
+
return (typeof part === 'string' ||
|
|
923
|
+
typeof part === 'number' ||
|
|
924
|
+
(Array.isArray(part) && part.every(isValidSyncableIDPart)));
|
|
915
925
|
}
|
|
916
926
|
function isValidAtID(id, idPrefix) {
|
|
917
|
-
return !idPrefix || (typeof id ===
|
|
927
|
+
return !idPrefix || (typeof id === 'string' && id.startsWith(idPrefix));
|
|
918
928
|
}
|
|
919
929
|
|
|
920
930
|
function applyOperation(target, table, op) {
|
|
921
931
|
const tbl = target[table] || (target[table] = {});
|
|
922
|
-
const keys = op.keys.map(key => typeof key === 'string' ? key : JSON.stringify(key));
|
|
932
|
+
const keys = op.keys.map((key) => typeof key === 'string' ? key : JSON.stringify(key));
|
|
923
933
|
switch (op.type) {
|
|
924
|
-
case
|
|
934
|
+
case 'insert':
|
|
925
935
|
// TODO: Don't treat insert and upsert the same?
|
|
926
|
-
case
|
|
936
|
+
case 'upsert':
|
|
927
937
|
keys.forEach((key, idx) => {
|
|
928
938
|
tbl[key] = {
|
|
929
|
-
type:
|
|
939
|
+
type: 'ups',
|
|
930
940
|
val: op.values[idx],
|
|
931
941
|
};
|
|
932
942
|
});
|
|
933
943
|
break;
|
|
934
|
-
case
|
|
935
|
-
case
|
|
944
|
+
case 'update':
|
|
945
|
+
case 'modify': {
|
|
936
946
|
keys.forEach((key, idx) => {
|
|
937
|
-
const changeSpec = op.type ===
|
|
938
|
-
? op.changeSpecs[idx]
|
|
939
|
-
: op.changeSpec;
|
|
947
|
+
const changeSpec = op.type === 'update' ? op.changeSpecs[idx] : op.changeSpec;
|
|
940
948
|
const entry = tbl[key];
|
|
941
949
|
if (!entry) {
|
|
942
950
|
tbl[key] = {
|
|
943
|
-
type:
|
|
951
|
+
type: 'upd',
|
|
944
952
|
mod: changeSpec,
|
|
945
953
|
};
|
|
946
954
|
}
|
|
947
955
|
else {
|
|
948
956
|
switch (entry.type) {
|
|
949
|
-
case
|
|
957
|
+
case 'ups':
|
|
950
958
|
// Adjust the existing upsert with additional updates
|
|
951
959
|
for (const [propPath, value] of Object.entries(changeSpec)) {
|
|
952
960
|
setByKeyPath(entry.val, propPath, value);
|
|
953
961
|
}
|
|
954
962
|
break;
|
|
955
|
-
case
|
|
963
|
+
case 'del':
|
|
956
964
|
// No action.
|
|
957
965
|
break;
|
|
958
|
-
case
|
|
966
|
+
case 'upd':
|
|
959
967
|
// Adjust existing update with additional updates
|
|
960
968
|
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)
|
|
961
969
|
break;
|
|
@@ -964,10 +972,10 @@ function applyOperation(target, table, op) {
|
|
|
964
972
|
});
|
|
965
973
|
break;
|
|
966
974
|
}
|
|
967
|
-
case
|
|
975
|
+
case 'delete':
|
|
968
976
|
keys.forEach((key) => {
|
|
969
977
|
tbl[key] = {
|
|
970
|
-
type:
|
|
978
|
+
type: 'del',
|
|
971
979
|
};
|
|
972
980
|
});
|
|
973
981
|
break;
|
|
@@ -1064,30 +1072,30 @@ function toDBOperationSet(inSet, txid) {
|
|
|
1064
1072
|
};
|
|
1065
1073
|
for (const [optype, muts] of Object.entries(ops)) {
|
|
1066
1074
|
switch (optype) {
|
|
1067
|
-
case
|
|
1075
|
+
case 'ups': {
|
|
1068
1076
|
const op = {
|
|
1069
|
-
type:
|
|
1070
|
-
keys: muts.map(mut => mut.key),
|
|
1071
|
-
values: muts.map(mut => mut.val),
|
|
1072
|
-
txid
|
|
1077
|
+
type: 'upsert',
|
|
1078
|
+
keys: muts.map((mut) => mut.key),
|
|
1079
|
+
values: muts.map((mut) => mut.val),
|
|
1080
|
+
txid,
|
|
1073
1081
|
};
|
|
1074
1082
|
resultEntry.muts.push(op);
|
|
1075
1083
|
break;
|
|
1076
1084
|
}
|
|
1077
|
-
case
|
|
1085
|
+
case 'upd': {
|
|
1078
1086
|
const op = {
|
|
1079
|
-
type:
|
|
1080
|
-
keys: muts.map(mut => mut.key),
|
|
1081
|
-
changeSpecs: muts.map(mut => mut.mod),
|
|
1082
|
-
txid
|
|
1087
|
+
type: 'update',
|
|
1088
|
+
keys: muts.map((mut) => mut.key),
|
|
1089
|
+
changeSpecs: muts.map((mut) => mut.mod),
|
|
1090
|
+
txid,
|
|
1083
1091
|
};
|
|
1084
1092
|
resultEntry.muts.push(op);
|
|
1085
1093
|
break;
|
|
1086
1094
|
}
|
|
1087
|
-
case
|
|
1095
|
+
case 'del': {
|
|
1088
1096
|
const op = {
|
|
1089
|
-
type:
|
|
1090
|
-
keys: muts.map(mut => mut.key),
|
|
1097
|
+
type: 'delete',
|
|
1098
|
+
keys: muts.map((mut) => mut.key),
|
|
1091
1099
|
txid,
|
|
1092
1100
|
};
|
|
1093
1101
|
resultEntry.muts.push(op);
|
|
@@ -1102,7 +1110,7 @@ function toDBOperationSet(inSet, txid) {
|
|
|
1102
1110
|
|
|
1103
1111
|
function getDbNameFromDbUrl(dbUrl) {
|
|
1104
1112
|
const url = new URL(dbUrl);
|
|
1105
|
-
return url.pathname ===
|
|
1113
|
+
return url.pathname === '/'
|
|
1106
1114
|
? url.hostname.split('.')[0]
|
|
1107
1115
|
: url.pathname.split('/')[1];
|
|
1108
1116
|
}
|
|
@@ -1220,7 +1228,8 @@ function decodeYMessage(a) {
|
|
|
1220
1228
|
prop,
|
|
1221
1229
|
k,
|
|
1222
1230
|
u: readVarUint8Array(decoder),
|
|
1223
|
-
r: (decoder.pos < decoder.arr.length && readVarString(decoder)) ||
|
|
1231
|
+
r: (decoder.pos < decoder.arr.length && readVarString(decoder)) ||
|
|
1232
|
+
undefined,
|
|
1224
1233
|
};
|
|
1225
1234
|
default:
|
|
1226
1235
|
throw new TypeError(`Unknown message type: ${type}`);
|
|
@@ -1237,7 +1246,8 @@ async function asyncIterablePipeline(source, ...stages) {
|
|
|
1237
1246
|
}
|
|
1238
1247
|
// Start running the machine. If the last stage is a sink, it will consume the data and never emit anything
|
|
1239
1248
|
// to us here...
|
|
1240
|
-
for await (const chunk of result) {
|
|
1249
|
+
for await (const chunk of result) {
|
|
1250
|
+
}
|
|
1241
1251
|
}
|
|
1242
1252
|
|
|
1243
1253
|
async function* consumeChunkedBinaryStream(source) {
|
|
@@ -1291,7 +1301,7 @@ async function* consumeChunkedBinaryStream(source) {
|
|
|
1291
1301
|
}
|
|
1292
1302
|
if (pos + len > chunk.byteLength) {
|
|
1293
1303
|
bufs.push(chunk.slice(pos));
|
|
1294
|
-
len -=
|
|
1304
|
+
len -= chunk.byteLength - pos;
|
|
1295
1305
|
state = 2;
|
|
1296
1306
|
pos = chunk.byteLength; // will break while loop.
|
|
1297
1307
|
}
|
|
@@ -1322,7 +1332,7 @@ async function* consumeChunkedBinaryStream(source) {
|
|
|
1322
1332
|
function getFetchResponseBodyGenerator(res) {
|
|
1323
1333
|
return async function* () {
|
|
1324
1334
|
if (!res.body)
|
|
1325
|
-
throw new Error(
|
|
1335
|
+
throw new Error('Response body is not readable');
|
|
1326
1336
|
const reader = res.body.getReader();
|
|
1327
1337
|
try {
|
|
1328
1338
|
while (true) {
|
|
@@ -1391,11 +1401,11 @@ function hasBlobRefs(obj, visited = new WeakSet()) {
|
|
|
1391
1401
|
return false;
|
|
1392
1402
|
}
|
|
1393
1403
|
if (Array.isArray(obj)) {
|
|
1394
|
-
return obj.some(item => hasBlobRefs(item, visited));
|
|
1404
|
+
return obj.some((item) => hasBlobRefs(item, visited));
|
|
1395
1405
|
}
|
|
1396
1406
|
// Only traverse POJOs
|
|
1397
1407
|
if (obj.constructor === Object) {
|
|
1398
|
-
return Object.values(obj).some(value => hasBlobRefs(value, visited));
|
|
1408
|
+
return Object.values(obj).some((value) => hasBlobRefs(value, visited));
|
|
1399
1409
|
}
|
|
1400
1410
|
return false;
|
|
1401
1411
|
}
|
|
@@ -1459,7 +1469,8 @@ function convertToOriginalType(data, ref) {
|
|
|
1459
1469
|
*/
|
|
1460
1470
|
function resolveAllBlobRefs(obj_1, dbUrl_1) {
|
|
1461
1471
|
return __awaiter(this, arguments, void 0, function* (obj, dbUrl, resolvedBlobs = [], currentPath = '', visited = new WeakMap(), tracker) {
|
|
1462
|
-
if (obj == null) {
|
|
1472
|
+
if (obj == null) {
|
|
1473
|
+
// null or undefined
|
|
1463
1474
|
return obj;
|
|
1464
1475
|
}
|
|
1465
1476
|
// Check if this is a BlobRef - resolve it and track it
|
|
@@ -1508,9 +1519,7 @@ function resolveAllBlobRefs(obj_1, dbUrl_1) {
|
|
|
1508
1519
|
* Check if an object has unresolved BlobRefs
|
|
1509
1520
|
*/
|
|
1510
1521
|
function hasUnresolvedBlobRefs(obj) {
|
|
1511
|
-
return (typeof obj === 'object' &&
|
|
1512
|
-
obj !== null &&
|
|
1513
|
-
obj._hasBlobRefs === 1);
|
|
1522
|
+
return (typeof obj === 'object' && obj !== null && obj._hasBlobRefs === 1);
|
|
1514
1523
|
}
|
|
1515
1524
|
|
|
1516
1525
|
function getSyncableTables(db) {
|
|
@@ -1575,7 +1584,7 @@ function observeBlobProgress(db, downloading$) {
|
|
|
1575
1584
|
isDownloading: isDownloading && stats.blobsRemaining > 0,
|
|
1576
1585
|
blobsRemaining: stats.blobsRemaining,
|
|
1577
1586
|
bytesRemaining: stats.bytesRemaining,
|
|
1578
|
-
})), share({ resetOnRefCountZero: () => timer(2000) }) // Keep alive for 2s after last unsubscription to avoid rapid re-subscriptions during UI updates
|
|
1587
|
+
})), share({ resetOnRefCountZero: () => timer(2000) }) // Keep alive for 2s after last unsubscription to avoid rapid re-subscriptions during UI updates
|
|
1579
1588
|
);
|
|
1580
1589
|
}
|
|
1581
1590
|
/**
|
|
@@ -1659,13 +1668,13 @@ function downloadUnresolvedBlobs(db, downloading$, signal) {
|
|
|
1659
1668
|
}
|
|
1660
1669
|
setDownloadingState(downloading$, true);
|
|
1661
1670
|
try {
|
|
1662
|
-
debugLog(`Eager download: Found ${syncedTables.length} syncable tables: ${syncedTables.map(t => t.name).join(', ')}`);
|
|
1671
|
+
debugLog(`Eager download: Found ${syncedTables.length} syncable tables: ${syncedTables.map((t) => t.name).join(', ')}`);
|
|
1663
1672
|
for (const table of syncedTables) {
|
|
1664
1673
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted)
|
|
1665
1674
|
;
|
|
1666
1675
|
try {
|
|
1667
1676
|
// Check if table has _hasBlobRefs index
|
|
1668
|
-
const hasIndex = table.schema.indexes.some(idx => idx.name === '_hasBlobRefs');
|
|
1677
|
+
const hasIndex = table.schema.indexes.some((idx) => idx.name === '_hasBlobRefs');
|
|
1669
1678
|
if (!hasIndex)
|
|
1670
1679
|
continue;
|
|
1671
1680
|
// Query objects with _hasBlobRefs marker
|
|
@@ -1681,7 +1690,7 @@ function downloadUnresolvedBlobs(db, downloading$, signal) {
|
|
|
1681
1690
|
const MAX_CONCURRENT = 6;
|
|
1682
1691
|
const primaryKey = table.schema.primKey;
|
|
1683
1692
|
// Filter to actionable objects first
|
|
1684
|
-
const pending = unresolvedObjects.filter(obj => {
|
|
1693
|
+
const pending = unresolvedObjects.filter((obj) => {
|
|
1685
1694
|
if (!hasUnresolvedBlobRefs(obj))
|
|
1686
1695
|
return false;
|
|
1687
1696
|
const key = primaryKey.keyPath
|
|
@@ -1742,7 +1751,7 @@ function registerSyncEvent(db, purpose) {
|
|
|
1742
1751
|
try {
|
|
1743
1752
|
// Send sync event to SW:
|
|
1744
1753
|
const sw = yield navigator.serviceWorker.ready;
|
|
1745
|
-
if (purpose ===
|
|
1754
|
+
if (purpose === 'push' && sw.sync) {
|
|
1746
1755
|
yield sw.sync.register(`dexie-cloud:${db.name}`);
|
|
1747
1756
|
}
|
|
1748
1757
|
if (sw.active) {
|
|
@@ -1751,7 +1760,7 @@ function registerSyncEvent(db, purpose) {
|
|
|
1751
1760
|
sw.active.postMessage({
|
|
1752
1761
|
type: 'dexie-cloud-sync',
|
|
1753
1762
|
dbName: db.name,
|
|
1754
|
-
purpose
|
|
1763
|
+
purpose,
|
|
1755
1764
|
});
|
|
1756
1765
|
}
|
|
1757
1766
|
else {
|
|
@@ -1876,14 +1885,15 @@ function promptForEmail(userInteraction, title, emailHint, initialAlert) {
|
|
|
1876
1885
|
// the domain extension like .com, .net, etc.
|
|
1877
1886
|
// (\sas\s[\w-+.]+@([\w-]+\.)+[\w-]{2,10})?$ : This part is optional (due to the ? at the end).
|
|
1878
1887
|
// If present, it matches " as " followed by another valid email address. This allows for the
|
|
1879
|
-
// input to be either a single email address or two email addresses separated by " as ".
|
|
1888
|
+
// input to be either a single email address or two email addresses separated by " as ".
|
|
1880
1889
|
//
|
|
1881
1890
|
// The use case for "<email1> as <email2>"" is for when a database owner with full access to the
|
|
1882
1891
|
// database needs to impersonate another user in the database in order to troubleshoot. This
|
|
1883
1892
|
// format will only be possible to use when email1 is the owner of an API client with GLOBAL_READ
|
|
1884
1893
|
// and GLOBAL_WRITE permissions on the database. The email will be checked on the server before
|
|
1885
1894
|
// allowing it and giving out a token for email2, using the OTP sent to email1.
|
|
1886
|
-
while (!email ||
|
|
1895
|
+
while (!email ||
|
|
1896
|
+
!/^[\w-+.]+@([\w-]+\.)+[\w-]{2,10}(\sas\s[\w-+.]+@([\w-]+\.)+[\w-]{2,10})?$/.test(email)) {
|
|
1887
1897
|
const alerts = [];
|
|
1888
1898
|
if (firstPrompt && initialAlert)
|
|
1889
1899
|
alerts.push(initialAlert);
|
|
@@ -1949,7 +1959,7 @@ function confirmLogout(userInteraction, currentUserId, numUnsyncedChanges) {
|
|
|
1949
1959
|
messageParams: {
|
|
1950
1960
|
currentUserId,
|
|
1951
1961
|
numUnsyncedChanges: numUnsyncedChanges.toString(),
|
|
1952
|
-
}
|
|
1962
|
+
},
|
|
1953
1963
|
},
|
|
1954
1964
|
];
|
|
1955
1965
|
return yield interactWithUser(userInteraction, {
|
|
@@ -1958,7 +1968,7 @@ function confirmLogout(userInteraction, currentUserId, numUnsyncedChanges) {
|
|
|
1958
1968
|
alerts,
|
|
1959
1969
|
fields: {},
|
|
1960
1970
|
submitLabel: 'Confirm logout',
|
|
1961
|
-
cancelLabel: 'Cancel'
|
|
1971
|
+
cancelLabel: 'Cancel',
|
|
1962
1972
|
})
|
|
1963
1973
|
.then(() => true)
|
|
1964
1974
|
.catch(() => false);
|
|
@@ -2075,7 +2085,8 @@ function loadAccessToken(db) {
|
|
|
2075
2085
|
if (!accessToken)
|
|
2076
2086
|
return null;
|
|
2077
2087
|
const expTime = (_a = accessTokenExpiration === null || accessTokenExpiration === void 0 ? void 0 : accessTokenExpiration.getTime()) !== null && _a !== void 0 ? _a : Infinity;
|
|
2078
|
-
if (expTime >
|
|
2088
|
+
if (expTime > Date.now() + 5 * MINUTES &&
|
|
2089
|
+
(((_b = currentUser.license) === null || _b === void 0 ? void 0 : _b.status) || 'ok') === 'ok') {
|
|
2079
2090
|
return currentUser;
|
|
2080
2091
|
}
|
|
2081
2092
|
if (!refreshToken) {
|
|
@@ -2235,11 +2246,13 @@ function userAuthenticate(context, fetchToken, userInteraction, hints) {
|
|
|
2235
2246
|
}
|
|
2236
2247
|
catch (error) {
|
|
2237
2248
|
// OAuth redirect is not an error - page is navigating away
|
|
2238
|
-
if (error instanceof OAuthRedirectError ||
|
|
2249
|
+
if (error instanceof OAuthRedirectError ||
|
|
2250
|
+
(error === null || error === void 0 ? void 0 : error.name) === 'OAuthRedirectError') {
|
|
2239
2251
|
throw error; // Re-throw without logging
|
|
2240
2252
|
}
|
|
2241
2253
|
// Policy rejections have already been shown to the user as a challenge
|
|
2242
|
-
if (error instanceof PolicyRejectionError ||
|
|
2254
|
+
if (error instanceof PolicyRejectionError ||
|
|
2255
|
+
(error === null || error === void 0 ? void 0 : error.name) === 'PolicyRejectionError') {
|
|
2243
2256
|
throw error;
|
|
2244
2257
|
}
|
|
2245
2258
|
if (error instanceof TokenErrorResponseError) {
|
|
@@ -2258,7 +2271,10 @@ function userAuthenticate(context, fetchToken, userInteraction, hints) {
|
|
|
2258
2271
|
if (isOffline) {
|
|
2259
2272
|
message = `You seem to be offline. Please connect to the internet and try again.`;
|
|
2260
2273
|
}
|
|
2261
|
-
else if (typeof location !== 'undefined' &&
|
|
2274
|
+
else if (typeof location !== 'undefined' &&
|
|
2275
|
+
(Dexie.debug ||
|
|
2276
|
+
location.hostname === 'localhost' ||
|
|
2277
|
+
location.hostname === '127.0.0.1')) {
|
|
2262
2278
|
// The audience is most likely the developer. Suggest to whitelist the localhost origin:
|
|
2263
2279
|
const whitelistCommand = `npx dexie-cloud whitelist ${location.origin}`;
|
|
2264
2280
|
message = `Could not connect to server. Please verify that your origin '${location.origin}' is whitelisted using \`npx dexie-cloud whitelist\``;
|
|
@@ -2308,31 +2324,31 @@ class AuthPersistedContext {
|
|
|
2308
2324
|
}
|
|
2309
2325
|
static load(db, userId) {
|
|
2310
2326
|
return db
|
|
2311
|
-
.table(
|
|
2327
|
+
.table('$logins')
|
|
2312
2328
|
.get(userId)
|
|
2313
2329
|
.then((userLogin) => new AuthPersistedContext(db, userLogin || {
|
|
2314
2330
|
userId,
|
|
2315
2331
|
claims: {
|
|
2316
|
-
sub: userId
|
|
2332
|
+
sub: userId,
|
|
2317
2333
|
},
|
|
2318
|
-
lastLogin: new Date(0)
|
|
2334
|
+
lastLogin: new Date(0),
|
|
2319
2335
|
}));
|
|
2320
2336
|
}
|
|
2321
2337
|
save() {
|
|
2322
2338
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2323
2339
|
const db = wm$3.get(this);
|
|
2324
|
-
db.table(
|
|
2340
|
+
db.table('$logins').put(this);
|
|
2325
2341
|
});
|
|
2326
2342
|
}
|
|
2327
2343
|
}
|
|
2328
2344
|
|
|
2329
2345
|
const UNAUTHORIZED_USER = {
|
|
2330
|
-
userId:
|
|
2331
|
-
name:
|
|
2346
|
+
userId: 'unauthorized',
|
|
2347
|
+
name: 'Unauthorized',
|
|
2332
2348
|
claims: {
|
|
2333
|
-
sub:
|
|
2349
|
+
sub: 'unauthorized',
|
|
2334
2350
|
},
|
|
2335
|
-
lastLogin: new Date(0)
|
|
2351
|
+
lastLogin: new Date(0),
|
|
2336
2352
|
};
|
|
2337
2353
|
try {
|
|
2338
2354
|
Object.freeze(UNAUTHORIZED_USER);
|
|
@@ -2401,7 +2417,7 @@ class HttpError extends Error {
|
|
|
2401
2417
|
this.httpStatus = res.status;
|
|
2402
2418
|
}
|
|
2403
2419
|
get name() {
|
|
2404
|
-
return
|
|
2420
|
+
return 'HttpError';
|
|
2405
2421
|
}
|
|
2406
2422
|
}
|
|
2407
2423
|
|
|
@@ -2440,7 +2456,7 @@ class OAuthError extends Error {
|
|
|
2440
2456
|
*/
|
|
2441
2457
|
function exchangeOAuthCode(options) {
|
|
2442
2458
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2443
|
-
const { databaseUrl, code, publicKey, scopes = ['ACCESS_DB'], intent } = options;
|
|
2459
|
+
const { databaseUrl, code, publicKey, scopes = ['ACCESS_DB'], intent, } = options;
|
|
2444
2460
|
const tokenRequest = Object.assign({ grant_type: 'authorization_code', code, public_key: publicKey, scopes }, (intent !== undefined ? { intent } : {}));
|
|
2445
2461
|
try {
|
|
2446
2462
|
const res = yield fetch(`${databaseUrl}/token`, {
|
|
@@ -2498,7 +2514,8 @@ function exchangeOAuthCode(options) {
|
|
|
2498
2514
|
return response;
|
|
2499
2515
|
}
|
|
2500
2516
|
catch (error) {
|
|
2501
|
-
if (error instanceof OAuthError ||
|
|
2517
|
+
if (error instanceof OAuthError ||
|
|
2518
|
+
error instanceof TokenErrorResponseError) {
|
|
2502
2519
|
throw error;
|
|
2503
2520
|
}
|
|
2504
2521
|
if (error instanceof TypeError) {
|
|
@@ -2536,7 +2553,7 @@ function fetchAuthProviders(databaseUrl_1) {
|
|
|
2536
2553
|
try {
|
|
2537
2554
|
const res = yield fetch(`${databaseUrl}/auth-providers`, {
|
|
2538
2555
|
method: 'GET',
|
|
2539
|
-
headers: {
|
|
2556
|
+
headers: { Accept: 'application/json' },
|
|
2540
2557
|
mode: 'cors',
|
|
2541
2558
|
});
|
|
2542
2559
|
if (res.status === 404) {
|
|
@@ -2866,7 +2883,7 @@ function tryParsePolicyAlert(res) {
|
|
|
2866
2883
|
* @param args
|
|
2867
2884
|
*/
|
|
2868
2885
|
function prodLog(level, ...args) {
|
|
2869
|
-
globalThis[
|
|
2886
|
+
globalThis['con' + 'sole'][level](...args);
|
|
2870
2887
|
}
|
|
2871
2888
|
|
|
2872
2889
|
/** This function changes or sets the current user as requested.
|
|
@@ -2978,8 +2995,10 @@ function login(db, hints) {
|
|
|
2978
2995
|
}
|
|
2979
2996
|
|
|
2980
2997
|
const swHolder = {};
|
|
2981
|
-
const swContainer = typeof self !== 'undefined' &&
|
|
2982
|
-
|
|
2998
|
+
const swContainer = typeof self !== 'undefined' &&
|
|
2999
|
+
self.document && // self.document is to verify we're not the SW ourself
|
|
3000
|
+
typeof navigator !== 'undefined' &&
|
|
3001
|
+
navigator.serviceWorker;
|
|
2983
3002
|
if (swContainer)
|
|
2984
3003
|
swContainer.ready.then((registration) => (swHolder.registration = registration));
|
|
2985
3004
|
if (typeof self !== 'undefined' && 'clients' in self && !self.document) {
|
|
@@ -3033,7 +3052,8 @@ class SWBroadcastChannel {
|
|
|
3033
3052
|
}
|
|
3034
3053
|
}
|
|
3035
3054
|
|
|
3036
|
-
const events = globalThis['lbc-events'] ||
|
|
3055
|
+
const events = globalThis['lbc-events'] ||
|
|
3056
|
+
(globalThis['lbc-events'] = new Map());
|
|
3037
3057
|
function addListener(name, listener) {
|
|
3038
3058
|
if (events.has(name)) {
|
|
3039
3059
|
events.get(name).push(listener);
|
|
@@ -3054,25 +3074,25 @@ function removeListener(name, listener) {
|
|
|
3054
3074
|
function dispatch(ev) {
|
|
3055
3075
|
const listeners = events.get(ev.type);
|
|
3056
3076
|
if (listeners) {
|
|
3057
|
-
listeners.forEach(listener => {
|
|
3077
|
+
listeners.forEach((listener) => {
|
|
3058
3078
|
try {
|
|
3059
3079
|
listener(ev);
|
|
3060
3080
|
}
|
|
3061
|
-
catch (_a) {
|
|
3062
|
-
}
|
|
3081
|
+
catch (_a) { }
|
|
3063
3082
|
});
|
|
3064
3083
|
}
|
|
3065
3084
|
}
|
|
3066
3085
|
class BroadcastedAndLocalEvent extends Observable {
|
|
3067
3086
|
constructor(name) {
|
|
3068
|
-
const bc = typeof BroadcastChannel ===
|
|
3069
|
-
? new SWBroadcastChannel(name)
|
|
3070
|
-
|
|
3087
|
+
const bc = typeof BroadcastChannel === 'undefined'
|
|
3088
|
+
? new SWBroadcastChannel(name)
|
|
3089
|
+
: new BroadcastChannel(name);
|
|
3090
|
+
super((subscriber) => {
|
|
3071
3091
|
function onCustomEvent(ev) {
|
|
3072
3092
|
subscriber.next(ev.detail);
|
|
3073
3093
|
}
|
|
3074
3094
|
function onMessageEvent(ev) {
|
|
3075
|
-
console.debug(
|
|
3095
|
+
console.debug('BroadcastedAndLocalEvent: onMessageEvent', ev);
|
|
3076
3096
|
subscriber.next(ev.data);
|
|
3077
3097
|
}
|
|
3078
3098
|
let unsubscribe;
|
|
@@ -3080,11 +3100,11 @@ class BroadcastedAndLocalEvent extends Observable {
|
|
|
3080
3100
|
addListener(`lbc-${name}`, onCustomEvent); // Works better in service worker
|
|
3081
3101
|
try {
|
|
3082
3102
|
if (bc instanceof SWBroadcastChannel) {
|
|
3083
|
-
unsubscribe = bc.subscribe(message => subscriber.next(message));
|
|
3103
|
+
unsubscribe = bc.subscribe((message) => subscriber.next(message));
|
|
3084
3104
|
}
|
|
3085
3105
|
else {
|
|
3086
|
-
console.debug(
|
|
3087
|
-
bc.addEventListener(
|
|
3106
|
+
console.debug('BroadcastedAndLocalEvent: bc.addEventListener()', name, 'bc is a', bc);
|
|
3107
|
+
bc.addEventListener('message', onMessageEvent);
|
|
3088
3108
|
}
|
|
3089
3109
|
}
|
|
3090
3110
|
catch (err) {
|
|
@@ -3098,7 +3118,7 @@ class BroadcastedAndLocalEvent extends Observable {
|
|
|
3098
3118
|
unsubscribe();
|
|
3099
3119
|
}
|
|
3100
3120
|
else {
|
|
3101
|
-
bc.removeEventListener(
|
|
3121
|
+
bc.removeEventListener('message', onMessageEvent);
|
|
3102
3122
|
}
|
|
3103
3123
|
};
|
|
3104
3124
|
});
|
|
@@ -3106,7 +3126,7 @@ class BroadcastedAndLocalEvent extends Observable {
|
|
|
3106
3126
|
this.bc = bc;
|
|
3107
3127
|
}
|
|
3108
3128
|
next(message) {
|
|
3109
|
-
console.debug(
|
|
3129
|
+
console.debug('BroadcastedAndLocalEvent: bc.postMessage()', Object.assign({}, message), 'bc is a', this.bc);
|
|
3110
3130
|
this.bc.postMessage(message);
|
|
3111
3131
|
const ev = new CustomEvent(`lbc-${this.name}`, { detail: message });
|
|
3112
3132
|
//self.dispatchEvent(ev);
|
|
@@ -3199,7 +3219,7 @@ function removeRedundantUpdateOps(muts) {
|
|
|
3199
3219
|
}
|
|
3200
3220
|
const strKey = '' + mut.keys[0];
|
|
3201
3221
|
const changeSpecs = mut.changeSpecs[0];
|
|
3202
|
-
if (Object.values(changeSpecs).some(v => typeof v ===
|
|
3222
|
+
if (Object.values(changeSpecs).some((v) => typeof v === 'object' && v && '@@propmod' in v)) {
|
|
3203
3223
|
continue; // Cannot optimize if any PropModification is present
|
|
3204
3224
|
}
|
|
3205
3225
|
let keyCoverage = updateCoverage.get(strKey);
|
|
@@ -3207,11 +3227,13 @@ function removeRedundantUpdateOps(muts) {
|
|
|
3207
3227
|
keyCoverage.push({ txid: mut.txid, updateSpec: changeSpecs });
|
|
3208
3228
|
}
|
|
3209
3229
|
else {
|
|
3210
|
-
updateCoverage.set(strKey, [
|
|
3230
|
+
updateCoverage.set(strKey, [
|
|
3231
|
+
{ txid: mut.txid, updateSpec: changeSpecs },
|
|
3232
|
+
]);
|
|
3211
3233
|
}
|
|
3212
3234
|
}
|
|
3213
3235
|
}
|
|
3214
|
-
muts = muts.filter(mut => {
|
|
3236
|
+
muts = muts.filter((mut) => {
|
|
3215
3237
|
// Only apply optimization to update mutations that are single-key
|
|
3216
3238
|
if (mut.type !== 'update')
|
|
3217
3239
|
return true;
|
|
@@ -3219,7 +3241,7 @@ function removeRedundantUpdateOps(muts) {
|
|
|
3219
3241
|
return true;
|
|
3220
3242
|
// Check if this has PropModifications - if so, skip optimization
|
|
3221
3243
|
const changeSpecs = mut.changeSpecs[0];
|
|
3222
|
-
if (Object.values(changeSpecs).some(v => typeof v ===
|
|
3244
|
+
if (Object.values(changeSpecs).some((v) => typeof v === 'object' && v && '@@propmod' in v)) {
|
|
3223
3245
|
return true; // Cannot optimize if any PropModification is present
|
|
3224
3246
|
}
|
|
3225
3247
|
// Keep track of properties that aren't overlapped by later transactions
|
|
@@ -3247,7 +3269,7 @@ function removeRedundantUpdateOps(muts) {
|
|
|
3247
3269
|
return muts;
|
|
3248
3270
|
}
|
|
3249
3271
|
function canonicalizeToUpdateOps(muts) {
|
|
3250
|
-
muts = muts.map(mut => {
|
|
3272
|
+
muts = muts.map((mut) => {
|
|
3251
3273
|
if (mut.type === 'modify' && mut.criteria.index === null) {
|
|
3252
3274
|
// The criteria is on primary key. Convert to an update operation instead.
|
|
3253
3275
|
// It is simpler for the server to handle and also more efficient.
|
|
@@ -3469,7 +3491,7 @@ function checkSyncRateLimitDelay(db) {
|
|
|
3469
3491
|
const delatMilliseconds = ((_b = (_a = syncRatelimitDelays.get(db)) === null || _a === void 0 ? void 0 : _a.getTime()) !== null && _b !== void 0 ? _b : 0) - Date.now();
|
|
3470
3492
|
if (delatMilliseconds > 0) {
|
|
3471
3493
|
console.debug(`Stalling sync request ${delatMilliseconds} ms to spare ratelimits`);
|
|
3472
|
-
yield new Promise(resolve => setTimeout(resolve, delatMilliseconds));
|
|
3494
|
+
yield new Promise((resolve) => setTimeout(resolve, delatMilliseconds));
|
|
3473
3495
|
}
|
|
3474
3496
|
});
|
|
3475
3497
|
}
|
|
@@ -3534,7 +3556,7 @@ function syncWithServer(changes, y, syncState, baseRevs, db, databaseUrl, schema
|
|
|
3534
3556
|
baseRevs,
|
|
3535
3557
|
changes: encodeIdsForServer(db.dx.core.schema, currentUser, changes),
|
|
3536
3558
|
y,
|
|
3537
|
-
dxcv: db.cloud.version
|
|
3559
|
+
dxcv: db.cloud.version,
|
|
3538
3560
|
};
|
|
3539
3561
|
console.debug('Sync request', syncRequest);
|
|
3540
3562
|
db.syncStateChangedEvent.next({
|
|
@@ -3574,19 +3596,22 @@ function modifyLocalObjectsWithNewUserId(syncifiedTables, currentUser, alreadySy
|
|
|
3574
3596
|
return __awaiter(this, void 0, void 0, function* () {
|
|
3575
3597
|
const ignoredRealms = new Set(alreadySyncedRealms || []);
|
|
3576
3598
|
for (const table of syncifiedTables) {
|
|
3577
|
-
if (table.name ===
|
|
3599
|
+
if (table.name === 'members') {
|
|
3578
3600
|
// members
|
|
3579
3601
|
yield table.toCollection().modify((member) => {
|
|
3580
|
-
if (!ignoredRealms.has(member.realmId) &&
|
|
3602
|
+
if (!ignoredRealms.has(member.realmId) &&
|
|
3603
|
+
(!member.userId || member.userId === UNAUTHORIZED_USER.userId)) {
|
|
3581
3604
|
member.userId = currentUser.userId;
|
|
3582
3605
|
}
|
|
3583
3606
|
});
|
|
3584
3607
|
}
|
|
3585
|
-
else if (table.name ===
|
|
3586
|
-
else if (table.name ===
|
|
3608
|
+
else if (table.name === 'roles') ;
|
|
3609
|
+
else if (table.name === 'realms') {
|
|
3587
3610
|
// realms
|
|
3588
3611
|
yield table.toCollection().modify((realm) => {
|
|
3589
|
-
if (!ignoredRealms.has(realm.realmId) &&
|
|
3612
|
+
if (!ignoredRealms.has(realm.realmId) &&
|
|
3613
|
+
(realm.owner === undefined ||
|
|
3614
|
+
realm.owner === UNAUTHORIZED_USER.userId)) {
|
|
3590
3615
|
realm.owner = currentUser.userId;
|
|
3591
3616
|
}
|
|
3592
3617
|
});
|
|
@@ -3619,8 +3644,8 @@ function throwIfCancelled(cancelToken) {
|
|
|
3619
3644
|
let isOnline = false;
|
|
3620
3645
|
if (typeof self !== 'undefined' && typeof navigator !== 'undefined') {
|
|
3621
3646
|
isOnline = navigator.onLine;
|
|
3622
|
-
self.addEventListener('online', () => isOnline = true);
|
|
3623
|
-
self.addEventListener('offline', () => isOnline = false);
|
|
3647
|
+
self.addEventListener('online', () => (isOnline = true));
|
|
3648
|
+
self.addEventListener('offline', () => (isOnline = false));
|
|
3624
3649
|
}
|
|
3625
3650
|
|
|
3626
3651
|
function updateBaseRevs(db, schema, latestRevisions, serverRev) {
|
|
@@ -3637,7 +3662,10 @@ function updateBaseRevs(db, schema, latestRevisions, serverRev) {
|
|
|
3637
3662
|
}));
|
|
3638
3663
|
// Clean up baseRevs for tables that do not exist anymore or are no longer marked for sync
|
|
3639
3664
|
// Resolve #2168 by also cleaning up baseRevs for tables that are not marked for sync
|
|
3640
|
-
yield db.$baseRevs
|
|
3665
|
+
yield db.$baseRevs
|
|
3666
|
+
.where('tableName')
|
|
3667
|
+
.noneOf(Object.keys(schema).filter((table) => schema[table].markedForSync))
|
|
3668
|
+
.delete();
|
|
3641
3669
|
});
|
|
3642
3670
|
}
|
|
3643
3671
|
|
|
@@ -3759,6 +3787,16 @@ function applyServerChanges(changes, db) {
|
|
|
3759
3787
|
}
|
|
3760
3788
|
break;
|
|
3761
3789
|
case 'update':
|
|
3790
|
+
if (!primaryKey.outbound && primaryKey.keyPath) {
|
|
3791
|
+
// The primary key should never be part of an updateSpec — it cannot change
|
|
3792
|
+
// and is already communicated via the operation's keys array.
|
|
3793
|
+
// For private singleton IDs (e.g. "#key:userId" on server, "#key" on client),
|
|
3794
|
+
// the encoded server-side key may leak into the changeSpec via getObjectDiff().
|
|
3795
|
+
// Strip it here unconditionally as a defensive measure.
|
|
3796
|
+
for (const changeSpec of mut.changeSpecs) {
|
|
3797
|
+
Dexie.delByKeyPath(changeSpec, primaryKey.keyPath);
|
|
3798
|
+
}
|
|
3799
|
+
}
|
|
3762
3800
|
yield bulkUpdate(table, keys, mut.changeSpecs);
|
|
3763
3801
|
break;
|
|
3764
3802
|
case 'delete':
|
|
@@ -3773,10 +3811,7 @@ function applyServerChanges(changes, db) {
|
|
|
3773
3811
|
const DEXIE_CLOUD_SYNCER_ID = 'dexie-cloud-syncer';
|
|
3774
3812
|
|
|
3775
3813
|
function listUpdatesSince(yTable, sinceIncluding) {
|
|
3776
|
-
return yTable
|
|
3777
|
-
.where('i')
|
|
3778
|
-
.between(sinceIncluding, Infinity, true)
|
|
3779
|
-
.toArray();
|
|
3814
|
+
return yTable.where('i').between(sinceIncluding, Infinity, true).toArray();
|
|
3780
3815
|
}
|
|
3781
3816
|
|
|
3782
3817
|
/** Queries the local database for YMessages to send to server.
|
|
@@ -3871,7 +3906,7 @@ function listYClientMessagesAndStateVector(db, tablesToSync) {
|
|
|
3871
3906
|
}
|
|
3872
3907
|
return {
|
|
3873
3908
|
yMessages: result,
|
|
3874
|
-
lastUpdateIds
|
|
3909
|
+
lastUpdateIds,
|
|
3875
3910
|
};
|
|
3876
3911
|
});
|
|
3877
3912
|
}
|
|
@@ -3880,7 +3915,8 @@ function getUpdatesTable(db, table, ydocProp) {
|
|
|
3880
3915
|
var _a, _b, _c;
|
|
3881
3916
|
if (!db.dx._allTables[table])
|
|
3882
3917
|
return undefined;
|
|
3883
|
-
const utbl = (_c = (_b = (_a = db
|
|
3918
|
+
const utbl = (_c = (_b = (_a = db
|
|
3919
|
+
.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;
|
|
3884
3920
|
if (!utbl) {
|
|
3885
3921
|
console.debug(`No updatesTable found for ${table}.${ydocProp}`);
|
|
3886
3922
|
return undefined;
|
|
@@ -4013,10 +4049,18 @@ const blobEndpointSupported = new Map();
|
|
|
4013
4049
|
*/
|
|
4014
4050
|
// TypedArray/DataView tags for size check
|
|
4015
4051
|
const ARRAYBUFFER_VIEW_TAGS = new Set([
|
|
4016
|
-
'Int8Array',
|
|
4017
|
-
'
|
|
4018
|
-
'
|
|
4019
|
-
'
|
|
4052
|
+
'Int8Array',
|
|
4053
|
+
'Uint8Array',
|
|
4054
|
+
'Uint8ClampedArray',
|
|
4055
|
+
'Int16Array',
|
|
4056
|
+
'Uint16Array',
|
|
4057
|
+
'Int32Array',
|
|
4058
|
+
'Uint32Array',
|
|
4059
|
+
'Float32Array',
|
|
4060
|
+
'Float64Array',
|
|
4061
|
+
'BigInt64Array',
|
|
4062
|
+
'BigUint64Array',
|
|
4063
|
+
'DataView',
|
|
4020
4064
|
]);
|
|
4021
4065
|
// Static Set for O(1) lookup of binary type tags
|
|
4022
4066
|
const BINARY_TYPE_TAGS = new Set([
|
|
@@ -4116,7 +4160,7 @@ function uploadBlob(databaseUrl, getCachedAccessToken, blob) {
|
|
|
4116
4160
|
const response = yield fetch(uploadUrl, {
|
|
4117
4161
|
method: 'PUT',
|
|
4118
4162
|
headers: {
|
|
4119
|
-
|
|
4163
|
+
Authorization: `Bearer ${accessToken}`,
|
|
4120
4164
|
'Content-Type': contentType,
|
|
4121
4165
|
},
|
|
4122
4166
|
body,
|
|
@@ -4132,8 +4176,7 @@ function uploadBlob(databaseUrl, getCachedAccessToken, blob) {
|
|
|
4132
4176
|
// The server returns the ref with version prefix (e.g., "1:blobId")
|
|
4133
4177
|
const result = yield response.json();
|
|
4134
4178
|
// Return BlobRef with server's ref (includes version) and original type preserved in _bt
|
|
4135
|
-
return Object.assign({ _bt: origType, ref: result.ref, size: size }, (origType === 'Blob' ? { ct: contentType } : {})
|
|
4136
|
-
);
|
|
4179
|
+
return Object.assign({ _bt: origType, ref: result.ref, size: size }, (origType === 'Blob' ? { ct: contentType } : {}));
|
|
4137
4180
|
});
|
|
4138
4181
|
}
|
|
4139
4182
|
function offloadBlobsAndMarkDirty(obj_1, databaseUrl_1, getCachedAccessToken_1) {
|
|
@@ -4141,7 +4184,10 @@ function offloadBlobsAndMarkDirty(obj_1, databaseUrl_1, getCachedAccessToken_1)
|
|
|
4141
4184
|
const dirtyFlag = { dirty: false };
|
|
4142
4185
|
const result = yield offloadBlobs(obj, databaseUrl, getCachedAccessToken, maxStringLength, dirtyFlag);
|
|
4143
4186
|
// Mark the object as dirty for sync if any blobs were offloaded
|
|
4144
|
-
if (dirtyFlag.dirty &&
|
|
4187
|
+
if (dirtyFlag.dirty &&
|
|
4188
|
+
typeof result === 'object' &&
|
|
4189
|
+
result !== null &&
|
|
4190
|
+
result.constructor === Object) {
|
|
4145
4191
|
result._hasBlobRefs = 1;
|
|
4146
4192
|
}
|
|
4147
4193
|
return result;
|
|
@@ -4157,7 +4203,9 @@ function offloadBlobs(obj_1, databaseUrl_1, getCachedAccessToken_1) {
|
|
|
4157
4203
|
return obj;
|
|
4158
4204
|
}
|
|
4159
4205
|
// Check if this is a long string that should be offloaded
|
|
4160
|
-
if (typeof obj === 'string' &&
|
|
4206
|
+
if (typeof obj === 'string' &&
|
|
4207
|
+
obj.length > maxStringLength &&
|
|
4208
|
+
maxStringLength !== Infinity) {
|
|
4161
4209
|
if (blobEndpointSupported.get(databaseUrl) === false) {
|
|
4162
4210
|
return obj;
|
|
4163
4211
|
}
|
|
@@ -4243,11 +4291,11 @@ function offloadBlobsInOperation(op_1, databaseUrl_1, getCachedAccessToken_1) {
|
|
|
4243
4291
|
switch (op.type) {
|
|
4244
4292
|
case 'insert':
|
|
4245
4293
|
case 'upsert': {
|
|
4246
|
-
const processedValues = yield Promise.all(op.values.map(value => offloadBlobsAndMarkDirty(value, databaseUrl, getCachedAccessToken, maxStringLength)));
|
|
4294
|
+
const processedValues = yield Promise.all(op.values.map((value) => offloadBlobsAndMarkDirty(value, databaseUrl, getCachedAccessToken, maxStringLength)));
|
|
4247
4295
|
return Object.assign(Object.assign({}, op), { values: processedValues });
|
|
4248
4296
|
}
|
|
4249
4297
|
case 'update': {
|
|
4250
|
-
const processedChangeSpecs = yield Promise.all(op.changeSpecs.map(spec => offloadBlobsAndMarkDirty(spec, databaseUrl, getCachedAccessToken, maxStringLength)));
|
|
4298
|
+
const processedChangeSpecs = yield Promise.all(op.changeSpecs.map((spec) => offloadBlobsAndMarkDirty(spec, databaseUrl, getCachedAccessToken, maxStringLength)));
|
|
4251
4299
|
return Object.assign(Object.assign({}, op), { changeSpecs: processedChangeSpecs });
|
|
4252
4300
|
}
|
|
4253
4301
|
case 'modify': {
|
|
@@ -4280,9 +4328,9 @@ function hasLargeBlobsInOperation(op, maxStringLength) {
|
|
|
4280
4328
|
switch (op.type) {
|
|
4281
4329
|
case 'insert':
|
|
4282
4330
|
case 'upsert':
|
|
4283
|
-
return op.values.some(value => hasLargeBlobs(value, maxStringLength));
|
|
4331
|
+
return op.values.some((value) => hasLargeBlobs(value, maxStringLength));
|
|
4284
4332
|
case 'update':
|
|
4285
|
-
return op.changeSpecs.some(spec => hasLargeBlobs(spec, maxStringLength));
|
|
4333
|
+
return op.changeSpecs.some((spec) => hasLargeBlobs(spec, maxStringLength));
|
|
4286
4334
|
case 'modify':
|
|
4287
4335
|
return hasLargeBlobs(op.changeSpec, maxStringLength);
|
|
4288
4336
|
default:
|
|
@@ -4294,7 +4342,9 @@ function hasLargeBlobs(obj, maxStringLength, visited = new WeakSet()) {
|
|
|
4294
4342
|
return false;
|
|
4295
4343
|
}
|
|
4296
4344
|
// Check long strings
|
|
4297
|
-
if (typeof obj === 'string' &&
|
|
4345
|
+
if (typeof obj === 'string' &&
|
|
4346
|
+
obj.length > maxStringLength &&
|
|
4347
|
+
maxStringLength !== Infinity) {
|
|
4298
4348
|
return true;
|
|
4299
4349
|
}
|
|
4300
4350
|
if (shouldOffloadBlob(obj)) {
|
|
@@ -4309,13 +4359,13 @@ function hasLargeBlobs(obj, maxStringLength, visited = new WeakSet()) {
|
|
|
4309
4359
|
}
|
|
4310
4360
|
visited.add(obj);
|
|
4311
4361
|
if (Array.isArray(obj)) {
|
|
4312
|
-
return obj.some(item => hasLargeBlobs(item, maxStringLength, visited));
|
|
4362
|
+
return obj.some((item) => hasLargeBlobs(item, maxStringLength, visited));
|
|
4313
4363
|
}
|
|
4314
4364
|
// Traverse plain objects (POJO-like) - use duck typing since IndexedDB
|
|
4315
4365
|
// may return objects where constructor !== Object
|
|
4316
4366
|
const proto = Object.getPrototypeOf(obj);
|
|
4317
4367
|
if (proto === Object.prototype || proto === null) {
|
|
4318
|
-
return Object.values(obj).some(value => hasLargeBlobs(value, maxStringLength, visited));
|
|
4368
|
+
return Object.values(obj).some((value) => hasLargeBlobs(value, maxStringLength, visited));
|
|
4319
4369
|
}
|
|
4320
4370
|
return false;
|
|
4321
4371
|
}
|
|
@@ -4369,7 +4419,7 @@ function updateYSyncStates(lastUpdateIdsBeforeSync, receivedUntilsAfterSync, db)
|
|
|
4369
4419
|
yield db.table(yTable).add({
|
|
4370
4420
|
i: DEXIE_CLOUD_SYNCER_ID,
|
|
4371
4421
|
unsentFrom,
|
|
4372
|
-
receivedUntil
|
|
4422
|
+
receivedUntil,
|
|
4373
4423
|
});
|
|
4374
4424
|
}
|
|
4375
4425
|
else {
|
|
@@ -4509,19 +4559,22 @@ function loadCachedAccessToken(db) {
|
|
|
4509
4559
|
return Promise.resolve(cached.accessToken);
|
|
4510
4560
|
}
|
|
4511
4561
|
const currentUser = db.cloud.currentUser.value;
|
|
4512
|
-
if (currentUser &&
|
|
4562
|
+
if (currentUser &&
|
|
4563
|
+
currentUser.accessToken &&
|
|
4564
|
+
((_b = (_a = currentUser.accessTokenExpiration) === null || _a === void 0 ? void 0 : _a.getTime()) !== null && _b !== void 0 ? _b : Infinity) >
|
|
4565
|
+
Date.now() + 5 * MINUTES) {
|
|
4513
4566
|
wm$2.set(db, {
|
|
4514
4567
|
accessToken: currentUser.accessToken,
|
|
4515
|
-
expiration: (_d = (_c = currentUser.accessTokenExpiration) === null || _c === void 0 ? void 0 : _c.getTime()) !== null && _d !== void 0 ? _d : Infinity
|
|
4568
|
+
expiration: (_d = (_c = currentUser.accessTokenExpiration) === null || _c === void 0 ? void 0 : _c.getTime()) !== null && _d !== void 0 ? _d : Infinity,
|
|
4516
4569
|
});
|
|
4517
4570
|
return Promise.resolve(currentUser.accessToken);
|
|
4518
4571
|
}
|
|
4519
|
-
return Dexie.ignoreTransaction(() => loadAccessToken(db).then(user => {
|
|
4572
|
+
return Dexie.ignoreTransaction(() => loadAccessToken(db).then((user) => {
|
|
4520
4573
|
var _a, _b;
|
|
4521
4574
|
if (user === null || user === void 0 ? void 0 : user.accessToken) {
|
|
4522
4575
|
wm$2.set(db, {
|
|
4523
4576
|
accessToken: user.accessToken,
|
|
4524
|
-
expiration: (_b = (_a = user.accessTokenExpiration) === null || _a === void 0 ? void 0 : _a.getTime()) !== null && _b !== void 0 ? _b : Infinity
|
|
4577
|
+
expiration: (_b = (_a = user.accessTokenExpiration) === null || _a === void 0 ? void 0 : _a.getTime()) !== null && _b !== void 0 ? _b : Infinity,
|
|
4525
4578
|
});
|
|
4526
4579
|
}
|
|
4527
4580
|
return (user === null || user === void 0 ? void 0 : user.accessToken) || null;
|
|
@@ -4532,7 +4585,8 @@ const CURRENT_SYNC_WORKER = 'currentSyncWorker';
|
|
|
4532
4585
|
function sync(db, options, schema, syncOptions) {
|
|
4533
4586
|
return _sync(db, options, schema, syncOptions)
|
|
4534
4587
|
.then((result) => {
|
|
4535
|
-
if (!(syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.justCheckIfNeeded)) {
|
|
4588
|
+
if (!(syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.justCheckIfNeeded)) {
|
|
4589
|
+
// && syncOptions?.purpose !== 'push') {
|
|
4536
4590
|
db.syncStateChangedEvent.next({
|
|
4537
4591
|
phase: 'in-sync',
|
|
4538
4592
|
});
|
|
@@ -4619,7 +4673,7 @@ function _sync(db_1, options_1, schema_1) {
|
|
|
4619
4673
|
const syncState = yield db.getPersistedSyncState();
|
|
4620
4674
|
let baseRevs = yield db.$baseRevs.toArray();
|
|
4621
4675
|
// Resolve #2168
|
|
4622
|
-
baseRevs = baseRevs.filter(br => tablesToSync.some(tbl => tbl.name === br.tableName));
|
|
4676
|
+
baseRevs = baseRevs.filter((br) => tablesToSync.some((tbl) => tbl.name === br.tableName));
|
|
4623
4677
|
let clientChanges = yield listClientChanges(mutationTables, db);
|
|
4624
4678
|
const yResults = yield listYClientMessagesAndStateVector(db, tablesToSync);
|
|
4625
4679
|
throwIfCancelled(cancelToken);
|
|
@@ -4635,7 +4689,7 @@ function _sync(db_1, options_1, schema_1) {
|
|
|
4635
4689
|
}
|
|
4636
4690
|
return [clientChanges, syncState, baseRevs, yResults];
|
|
4637
4691
|
}));
|
|
4638
|
-
const pushSyncIsNeeded = clientChangeSet.some((set) => set.muts.some((mut) => mut.keys.length > 0)) || yMessages.some(m => m.type === 'u-c');
|
|
4692
|
+
const pushSyncIsNeeded = clientChangeSet.some((set) => set.muts.some((mut) => mut.keys.length > 0)) || yMessages.some((m) => m.type === 'u-c');
|
|
4639
4693
|
if (justCheckIfNeeded) {
|
|
4640
4694
|
console.debug('Sync is needed:', pushSyncIsNeeded);
|
|
4641
4695
|
return pushSyncIsNeeded;
|
|
@@ -4779,7 +4833,7 @@ function _sync(db_1, options_1, schema_1) {
|
|
|
4779
4833
|
db.$syncState.put(newSyncState, 'syncState');
|
|
4780
4834
|
return {
|
|
4781
4835
|
done: addedClientChanges.length === 0,
|
|
4782
|
-
newSyncState
|
|
4836
|
+
newSyncState,
|
|
4783
4837
|
};
|
|
4784
4838
|
}));
|
|
4785
4839
|
if (!done) {
|
|
@@ -4787,7 +4841,7 @@ function _sync(db_1, options_1, schema_1) {
|
|
|
4787
4841
|
yield checkSyncRateLimitDelay(db);
|
|
4788
4842
|
return yield _sync(db, options, schema, { isInitialSync, cancelToken });
|
|
4789
4843
|
}
|
|
4790
|
-
const usingYProps = Object.values(schema).some(tbl => { var _a; return (_a = tbl.yProps) === null || _a === void 0 ? void 0 : _a.length; });
|
|
4844
|
+
const usingYProps = Object.values(schema).some((tbl) => { var _a; return (_a = tbl.yProps) === null || _a === void 0 ? void 0 : _a.length; });
|
|
4791
4845
|
const serverSupportsYprops = !!res.yMessages;
|
|
4792
4846
|
if (usingYProps && serverSupportsYprops) {
|
|
4793
4847
|
try {
|
|
@@ -5094,11 +5148,13 @@ class BlobDownloadTracker {
|
|
|
5094
5148
|
download(blobRef, dbUrl) {
|
|
5095
5149
|
let promise = this.inFlight.get(blobRef.ref);
|
|
5096
5150
|
if (!promise) {
|
|
5097
|
-
promise = loadCachedAccessToken(this.db)
|
|
5151
|
+
promise = loadCachedAccessToken(this.db)
|
|
5152
|
+
.then((accessToken) => {
|
|
5098
5153
|
if (!accessToken)
|
|
5099
|
-
throw new Error(
|
|
5154
|
+
throw new Error('No access token available for blob download');
|
|
5100
5155
|
return downloadBlob(blobRef, dbUrl, accessToken);
|
|
5101
|
-
})
|
|
5156
|
+
})
|
|
5157
|
+
.finally(() => this.inFlight.delete(blobRef.ref));
|
|
5102
5158
|
// When the promise settles (either fulfilled or rejected), remove it from the in-flight map
|
|
5103
5159
|
this.inFlight.set(blobRef.ref, promise);
|
|
5104
5160
|
}
|
|
@@ -5118,8 +5174,8 @@ function downloadBlob(blobRef, dbUrl, accessToken) {
|
|
|
5118
5174
|
const downloadUrl = `${dbUrl}/blob/${blobRef.ref}`;
|
|
5119
5175
|
const response = yield fetch(downloadUrl, {
|
|
5120
5176
|
headers: {
|
|
5121
|
-
|
|
5122
|
-
}
|
|
5177
|
+
Authorization: `Bearer ${accessToken}`,
|
|
5178
|
+
},
|
|
5123
5179
|
});
|
|
5124
5180
|
if (!response.ok) {
|
|
5125
5181
|
throw new Error(`Failed to download blob ${blobRef.ref}: ${response.status} ${response.statusText}`);
|
|
@@ -5211,7 +5267,9 @@ function DexieCloudDB(dx) {
|
|
|
5211
5267
|
return db.$syncState.get('schema').then((schema) => {
|
|
5212
5268
|
if (schema) {
|
|
5213
5269
|
for (const table of db.tables) {
|
|
5214
|
-
if (table.schema.primKey &&
|
|
5270
|
+
if (table.schema.primKey &&
|
|
5271
|
+
table.schema.primKey.keyPath &&
|
|
5272
|
+
schema[table.name]) {
|
|
5215
5273
|
schema[table.name].primaryKey = nameFromKeyPath(table.schema.primKey.keyPath);
|
|
5216
5274
|
}
|
|
5217
5275
|
}
|
|
@@ -5239,9 +5297,11 @@ function DexieCloudDB(dx) {
|
|
|
5239
5297
|
return db;
|
|
5240
5298
|
}
|
|
5241
5299
|
function nameFromKeyPath(keyPath) {
|
|
5242
|
-
return typeof keyPath === 'string'
|
|
5243
|
-
keyPath
|
|
5244
|
-
|
|
5300
|
+
return typeof keyPath === 'string'
|
|
5301
|
+
? keyPath
|
|
5302
|
+
: keyPath
|
|
5303
|
+
? '[' + [].join.call(keyPath, '+') + ']'
|
|
5304
|
+
: '';
|
|
5245
5305
|
}
|
|
5246
5306
|
|
|
5247
5307
|
// @ts-ignore
|
|
@@ -5263,7 +5323,7 @@ const safariVersion = isSafari
|
|
|
5263
5323
|
const DISABLE_SERVICEWORKER_STRATEGY = (isSafari && safariVersion <= 605) || // Disable for Safari for now.
|
|
5264
5324
|
isFirefox; // Disable for Firefox for now. Seems to have a bug in reading CryptoKeys from IDB from service workers
|
|
5265
5325
|
|
|
5266
|
-
const IS_SERVICE_WORKER = typeof self !==
|
|
5326
|
+
const IS_SERVICE_WORKER = typeof self !== 'undefined' && 'clients' in self && !self.document;
|
|
5267
5327
|
|
|
5268
5328
|
function throwVersionIncrementNeeded() {
|
|
5269
5329
|
throw new Dexie.SchemaError(`Version increment needed to allow dexie-cloud change tracking`);
|
|
@@ -5509,7 +5569,7 @@ function createImplicitPropSetterMiddleware(db) {
|
|
|
5509
5569
|
// We must also degrade from consistent modify operations for the
|
|
5510
5570
|
// same reason - object might be there on server. Must but put up instead.
|
|
5511
5571
|
// FUTURE: This clumpsy behavior of private IDs could be refined later.
|
|
5512
|
-
// Suggestion is to in future, treat private IDs as we treat all objects
|
|
5572
|
+
// Suggestion is to in future, treat private IDs as we treat all objects
|
|
5513
5573
|
// and sync operations normally. Only that deletions should become soft deletes
|
|
5514
5574
|
// for them - so that server knows when a private ID has been deleted on server
|
|
5515
5575
|
// not accept insert/upserts on them.
|
|
@@ -5532,19 +5592,20 @@ function createImplicitPropSetterMiddleware(db) {
|
|
|
5532
5592
|
}
|
|
5533
5593
|
|
|
5534
5594
|
function allSettled(possiblePromises) {
|
|
5535
|
-
return new Promise(resolve => {
|
|
5595
|
+
return new Promise((resolve) => {
|
|
5536
5596
|
if (possiblePromises.length === 0)
|
|
5537
5597
|
resolve([]);
|
|
5538
5598
|
let remaining = possiblePromises.length;
|
|
5539
5599
|
const results = new Array(remaining);
|
|
5540
|
-
possiblePromises.forEach((p, i) => Promise.resolve(p)
|
|
5600
|
+
possiblePromises.forEach((p, i) => Promise.resolve(p)
|
|
5601
|
+
.then((value) => (results[i] = { status: 'fulfilled', value }), (reason) => (results[i] = { status: 'rejected', reason }))
|
|
5541
5602
|
.then(() => --remaining || resolve(results)));
|
|
5542
5603
|
});
|
|
5543
5604
|
}
|
|
5544
5605
|
|
|
5545
5606
|
let counter$1 = 0;
|
|
5546
5607
|
function guardedTable(table) {
|
|
5547
|
-
const prop =
|
|
5608
|
+
const prop = '$lock' + ++counter$1;
|
|
5548
5609
|
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) });
|
|
5549
5610
|
}
|
|
5550
5611
|
function readLock(fn, prop) {
|
|
@@ -5553,7 +5614,9 @@ function readLock(fn, prop) {
|
|
|
5553
5614
|
const numWriters = writers.length;
|
|
5554
5615
|
const promise = (numWriters > 0
|
|
5555
5616
|
? writers[numWriters - 1].then(() => fn(req), () => fn(req))
|
|
5556
|
-
: fn(req)).finally(() => {
|
|
5617
|
+
: fn(req)).finally(() => {
|
|
5618
|
+
readers.splice(readers.indexOf(promise));
|
|
5619
|
+
});
|
|
5557
5620
|
readers.push(promise);
|
|
5558
5621
|
return promise;
|
|
5559
5622
|
};
|
|
@@ -5565,7 +5628,9 @@ function writeLock(fn, prop) {
|
|
|
5565
5628
|
? writers[writers.length - 1].then(() => fn(req), () => fn(req))
|
|
5566
5629
|
: readers.length > 0
|
|
5567
5630
|
? allSettled(readers).then(() => fn(req))
|
|
5568
|
-
: fn(req)).finally(() => {
|
|
5631
|
+
: fn(req)).finally(() => {
|
|
5632
|
+
writers.shift();
|
|
5633
|
+
});
|
|
5569
5634
|
writers.push(promise);
|
|
5570
5635
|
return promise;
|
|
5571
5636
|
};
|
|
@@ -5843,16 +5908,17 @@ function createMutationTrackingMiddleware({ currentUserObservable, db, }) {
|
|
|
5843
5908
|
userId,
|
|
5844
5909
|
values,
|
|
5845
5910
|
}
|
|
5846
|
-
: upsert && updates
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5911
|
+
: upsert && updates
|
|
5912
|
+
? {
|
|
5913
|
+
type: 'upsert',
|
|
5914
|
+
ts,
|
|
5915
|
+
opNo,
|
|
5916
|
+
keys,
|
|
5917
|
+
values,
|
|
5918
|
+
changeSpecs: updates.changeSpecs.filter((_, idx) => !failures[idx]),
|
|
5919
|
+
txid,
|
|
5920
|
+
userId,
|
|
5921
|
+
}
|
|
5856
5922
|
: criteria && changeSpec
|
|
5857
5923
|
? {
|
|
5858
5924
|
// Common changeSpec for all keys
|
|
@@ -5965,7 +6031,8 @@ class BlobSavingQueue {
|
|
|
5965
6031
|
return;
|
|
5966
6032
|
}
|
|
5967
6033
|
// Atomic update of just the blob property
|
|
5968
|
-
this.db
|
|
6034
|
+
this.db
|
|
6035
|
+
.transaction('rw', item.tableName, (tx) => {
|
|
5969
6036
|
const trans = tx.idbtrans;
|
|
5970
6037
|
trans.disableChangeTracking = true; // Don't regard this as a change for sync purposes
|
|
5971
6038
|
trans.disableAccessControl = true; // Bypass any access control checks since this is an internal operation
|
|
@@ -5974,7 +6041,7 @@ class BlobSavingQueue {
|
|
|
5974
6041
|
for (const blob of item.resolvedBlobs) {
|
|
5975
6042
|
updateSpec[blob.keyPath] = blob.data;
|
|
5976
6043
|
}
|
|
5977
|
-
tx.table(item.tableName).update(item.primaryKey, obj => {
|
|
6044
|
+
tx.table(item.tableName).update(item.primaryKey, (obj) => {
|
|
5978
6045
|
// Check that object still has the same unresolved blob refs before applying update (i.e. it hasn't been modified since we read it)
|
|
5979
6046
|
for (const blob of item.resolvedBlobs) {
|
|
5980
6047
|
// 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.
|
|
@@ -5995,9 +6062,11 @@ class BlobSavingQueue {
|
|
|
5995
6062
|
}
|
|
5996
6063
|
delete obj._hasBlobRefs; // Clear the _hasBlobRefs marker if all refs was resolved.
|
|
5997
6064
|
});
|
|
5998
|
-
})
|
|
6065
|
+
})
|
|
6066
|
+
.catch((error) => {
|
|
5999
6067
|
console.error(`Error saving resolved blobs on ${item.tableName}:${item.primaryKey}:`, error);
|
|
6000
|
-
})
|
|
6068
|
+
})
|
|
6069
|
+
.finally(() => {
|
|
6001
6070
|
// Process next item in the queue
|
|
6002
6071
|
return this.processQueue();
|
|
6003
6072
|
});
|
|
@@ -6048,7 +6117,7 @@ function createBlobResolveMiddleware(db) {
|
|
|
6048
6117
|
if ((_a = req.trans) === null || _a === void 0 ? void 0 : _a.disableBlobResolve) {
|
|
6049
6118
|
return downlevelTable.get(req);
|
|
6050
6119
|
}
|
|
6051
|
-
return downlevelTable.get(req).then(result => {
|
|
6120
|
+
return downlevelTable.get(req).then((result) => {
|
|
6052
6121
|
if (result && hasUnresolvedBlobRefs(result)) {
|
|
6053
6122
|
return resolveAndSave(downlevelTable, req.trans, req.key, result, blobSavingQueue, db);
|
|
6054
6123
|
}
|
|
@@ -6060,9 +6129,9 @@ function createBlobResolveMiddleware(db) {
|
|
|
6060
6129
|
if ((_a = req.trans) === null || _a === void 0 ? void 0 : _a.disableBlobResolve) {
|
|
6061
6130
|
return downlevelTable.getMany(req);
|
|
6062
6131
|
}
|
|
6063
|
-
return downlevelTable.getMany(req).then(results => {
|
|
6132
|
+
return downlevelTable.getMany(req).then((results) => {
|
|
6064
6133
|
// Check if any results need resolution
|
|
6065
|
-
const needsResolution = results.some(r => r && hasUnresolvedBlobRefs(r));
|
|
6134
|
+
const needsResolution = results.some((r) => r && hasUnresolvedBlobRefs(r));
|
|
6066
6135
|
if (!needsResolution)
|
|
6067
6136
|
return results;
|
|
6068
6137
|
return Dexie.Promise.all(results.map((result, index) => {
|
|
@@ -6078,19 +6147,19 @@ function createBlobResolveMiddleware(db) {
|
|
|
6078
6147
|
if ((_a = req.trans) === null || _a === void 0 ? void 0 : _a.disableBlobResolve) {
|
|
6079
6148
|
return downlevelTable.query(req);
|
|
6080
6149
|
}
|
|
6081
|
-
return downlevelTable.query(req).then(result => {
|
|
6150
|
+
return downlevelTable.query(req).then((result) => {
|
|
6082
6151
|
if (!result.result || !Array.isArray(result.result))
|
|
6083
6152
|
return result;
|
|
6084
6153
|
// Check if any results need resolution
|
|
6085
|
-
const needsResolution = result.result.some(r => r && hasUnresolvedBlobRefs(r));
|
|
6154
|
+
const needsResolution = result.result.some((r) => r && hasUnresolvedBlobRefs(r));
|
|
6086
6155
|
if (!needsResolution)
|
|
6087
6156
|
return result;
|
|
6088
|
-
return Dexie.Promise.all(result.result.map(item => {
|
|
6157
|
+
return Dexie.Promise.all(result.result.map((item) => {
|
|
6089
6158
|
if (item && hasUnresolvedBlobRefs(item)) {
|
|
6090
6159
|
return resolveAndSave(downlevelTable, req.trans, undefined, item, blobSavingQueue, db);
|
|
6091
6160
|
}
|
|
6092
6161
|
return item;
|
|
6093
|
-
})).then(resolved => (Object.assign(Object.assign({}, result), { result: resolved })));
|
|
6162
|
+
})).then((resolved) => (Object.assign(Object.assign({}, result), { result: resolved })));
|
|
6094
6163
|
});
|
|
6095
6164
|
},
|
|
6096
6165
|
openCursor(req) {
|
|
@@ -6098,7 +6167,7 @@ function createBlobResolveMiddleware(db) {
|
|
|
6098
6167
|
if ((_a = req.trans) === null || _a === void 0 ? void 0 : _a.disableBlobResolve) {
|
|
6099
6168
|
return downlevelTable.openCursor(req);
|
|
6100
6169
|
}
|
|
6101
|
-
return downlevelTable.openCursor(req).then(cursor => {
|
|
6170
|
+
return downlevelTable.openCursor(req).then((cursor) => {
|
|
6102
6171
|
if (!cursor)
|
|
6103
6172
|
return cursor; // No results, so no resolution needed
|
|
6104
6173
|
if (!req.values)
|
|
@@ -6128,7 +6197,7 @@ function createBlobResolvingCursor(cursor, table, blobSavingQueue, db) {
|
|
|
6128
6197
|
value: {
|
|
6129
6198
|
value: cursor.value,
|
|
6130
6199
|
enumerable: true,
|
|
6131
|
-
writable: true
|
|
6200
|
+
writable: true,
|
|
6132
6201
|
},
|
|
6133
6202
|
start: {
|
|
6134
6203
|
value(onNext) {
|
|
@@ -6140,17 +6209,17 @@ function createBlobResolvingCursor(cursor, table, blobSavingQueue, db) {
|
|
|
6140
6209
|
onNext();
|
|
6141
6210
|
return;
|
|
6142
6211
|
}
|
|
6143
|
-
resolveAndSave(table, cursor.trans, cursor.primaryKey, rawValue, blobSavingQueue, db, true).then(resolved => {
|
|
6212
|
+
resolveAndSave(table, cursor.trans, cursor.primaryKey, rawValue, blobSavingQueue, db, true).then((resolved) => {
|
|
6144
6213
|
wrappedCursor.value = resolved;
|
|
6145
6214
|
onNext();
|
|
6146
|
-
}, err => {
|
|
6215
|
+
}, (err) => {
|
|
6147
6216
|
console.error('Failed to resolve BlobRefs for cursor value:', err);
|
|
6148
6217
|
wrappedCursor.value = rawValue;
|
|
6149
6218
|
onNext();
|
|
6150
6219
|
});
|
|
6151
6220
|
});
|
|
6152
|
-
}
|
|
6153
|
-
}
|
|
6221
|
+
},
|
|
6222
|
+
},
|
|
6154
6223
|
});
|
|
6155
6224
|
return wrappedCursor;
|
|
6156
6225
|
}
|
|
@@ -6195,12 +6264,15 @@ obj, blobSavingQueue, db, isCursorValue = false // Flag to indicate if we're res
|
|
|
6195
6264
|
const resolvePromise = needsWaitFor
|
|
6196
6265
|
? Dexie.waitFor(resolutionPromise)
|
|
6197
6266
|
: Dexie.Promise.resolve(resolutionPromise);
|
|
6198
|
-
return resolvePromise
|
|
6267
|
+
return resolvePromise
|
|
6268
|
+
.then((resolved) => {
|
|
6199
6269
|
// Get primary key from the object
|
|
6200
6270
|
const primaryKey = table.schema.primaryKey;
|
|
6201
|
-
const key = pKey !== undefined
|
|
6202
|
-
?
|
|
6203
|
-
:
|
|
6271
|
+
const key = pKey !== undefined
|
|
6272
|
+
? pKey
|
|
6273
|
+
: primaryKey.keyPath
|
|
6274
|
+
? Dexie.getByKeyPath(obj, primaryKey.keyPath)
|
|
6275
|
+
: undefined;
|
|
6204
6276
|
if (key !== undefined) {
|
|
6205
6277
|
// Queue each resolved blob individually for atomic update
|
|
6206
6278
|
// This uses setTimeout(fn, 0) to completely isolate from
|
|
@@ -6211,13 +6283,16 @@ obj, blobSavingQueue, db, isCursorValue = false // Flag to indicate if we're res
|
|
|
6211
6283
|
else {
|
|
6212
6284
|
// For rw transactions, we can save directly without queueing
|
|
6213
6285
|
// since we're still in the same transaction context
|
|
6214
|
-
table
|
|
6286
|
+
table
|
|
6287
|
+
.mutate({ type: 'put', keys: [key], values: [resolved], trans })
|
|
6288
|
+
.catch((err) => {
|
|
6215
6289
|
console.error(`Failed to save resolved blob on ${table.name}:${key}:`, err);
|
|
6216
6290
|
});
|
|
6217
6291
|
}
|
|
6218
6292
|
}
|
|
6219
6293
|
return resolved;
|
|
6220
|
-
})
|
|
6294
|
+
})
|
|
6295
|
+
.catch((err) => {
|
|
6221
6296
|
console.error(`[dexie-cloud:blobResolve] Failed to resolve BlobRefs on ${table.name}:`, err);
|
|
6222
6297
|
return obj; // Return original object on error - never block the read pipeline
|
|
6223
6298
|
});
|
|
@@ -6246,9 +6321,13 @@ function overrideParseStoresSpec(origFunc, dexie) {
|
|
|
6246
6321
|
return; // Continue
|
|
6247
6322
|
}
|
|
6248
6323
|
// They have declared this table. Merge indexes in case they didn't declare all indexes we need.
|
|
6249
|
-
const requestedIndexes = schemaSrc
|
|
6250
|
-
|
|
6251
|
-
|
|
6324
|
+
const requestedIndexes = schemaSrc
|
|
6325
|
+
.split(',')
|
|
6326
|
+
.map((spec) => spec.trim());
|
|
6327
|
+
const builtInIndexes = DEXIE_CLOUD_SCHEMA[tableName]
|
|
6328
|
+
.split(',')
|
|
6329
|
+
.map((spec) => spec.trim());
|
|
6330
|
+
const requestedIndexSet = new Set(requestedIndexes.map((index) => index.replace(/([&*]|\+\+)/g, '')));
|
|
6252
6331
|
// Verify that primary key is unchanged
|
|
6253
6332
|
if (requestedIndexes[0] !== builtInIndexes[0]) {
|
|
6254
6333
|
// Primary key must match exactly
|
|
@@ -6257,7 +6336,7 @@ function overrideParseStoresSpec(origFunc, dexie) {
|
|
|
6257
6336
|
// Merge indexes
|
|
6258
6337
|
for (let i = 1; i < builtInIndexes.length; ++i) {
|
|
6259
6338
|
const builtInIndex = builtInIndexes[i];
|
|
6260
|
-
if (!requestedIndexSet.has(builtInIndex.replace(/([&*]|\+\+)/g,
|
|
6339
|
+
if (!requestedIndexSet.has(builtInIndex.replace(/([&*]|\+\+)/g, ''))) {
|
|
6261
6340
|
// Add built-in index if not already requested
|
|
6262
6341
|
storesClone[tableName] += `,${builtInIndex}`;
|
|
6263
6342
|
}
|
|
@@ -6266,7 +6345,7 @@ function overrideParseStoresSpec(origFunc, dexie) {
|
|
|
6266
6345
|
// Populate dexie.cloud.schema
|
|
6267
6346
|
const cloudSchema = dexie.cloud.schema || (dexie.cloud.schema = {});
|
|
6268
6347
|
const allPrefixes = new Set();
|
|
6269
|
-
Object.keys(storesClone).forEach(tableName => {
|
|
6348
|
+
Object.keys(storesClone).forEach((tableName) => {
|
|
6270
6349
|
var _a;
|
|
6271
6350
|
const schemaSrc = (_a = storesClone[tableName]) === null || _a === void 0 ? void 0 : _a.trim();
|
|
6272
6351
|
const cloudTableSchema = cloudSchema[tableName] || (cloudSchema[tableName] = {});
|
|
@@ -6395,7 +6474,7 @@ if (typeof document !== 'undefined') {
|
|
|
6395
6474
|
class TokenExpiredError extends Error {
|
|
6396
6475
|
constructor() {
|
|
6397
6476
|
super(...arguments);
|
|
6398
|
-
this.name =
|
|
6477
|
+
this.name = 'TokenExpiredError';
|
|
6399
6478
|
}
|
|
6400
6479
|
}
|
|
6401
6480
|
|
|
@@ -6619,7 +6698,7 @@ class WSConnection extends Subscription {
|
|
|
6619
6698
|
// Connect the WebSocket to given url:
|
|
6620
6699
|
console.debug('dexie-cloud WebSocket create');
|
|
6621
6700
|
const ws = (this.ws = new WebSocket(`${wsUrl}/changes?${searchParams}`));
|
|
6622
|
-
ws.binaryType =
|
|
6701
|
+
ws.binaryType = 'arraybuffer';
|
|
6623
6702
|
ws.onclose = (event) => {
|
|
6624
6703
|
if (!this.pinger)
|
|
6625
6704
|
return;
|
|
@@ -6658,10 +6737,17 @@ class WSConnection extends Subscription {
|
|
|
6658
6737
|
getOpenDocSignal(doc).next(); // Make yHandler reopen the document on server.
|
|
6659
6738
|
}
|
|
6660
6739
|
}
|
|
6661
|
-
else if (msg.type === 'u-ack' ||
|
|
6740
|
+
else if (msg.type === 'u-ack' ||
|
|
6741
|
+
msg.type === 'u-reject' ||
|
|
6742
|
+
msg.type === 'u-s' ||
|
|
6743
|
+
msg.type === 'in-sync' ||
|
|
6744
|
+
msg.type === 'outdated-server-rev' ||
|
|
6745
|
+
msg.type === 'y-complete-sync-done') {
|
|
6662
6746
|
applyYServerMessages([msg], this.db).then((_a) => __awaiter(this, [_a], void 0, function* ({ resyncNeeded, yServerRevision, receivedUntils }) {
|
|
6663
6747
|
if (yServerRevision) {
|
|
6664
|
-
yield this.db.$syncState.update('syncState', {
|
|
6748
|
+
yield this.db.$syncState.update('syncState', {
|
|
6749
|
+
yServerRevision: yServerRevision,
|
|
6750
|
+
});
|
|
6665
6751
|
}
|
|
6666
6752
|
if (msg.type === 'u-s' && receivedUntils) {
|
|
6667
6753
|
const utbl = getUpdatesTable(this.db, msg.table, msg.prop);
|
|
@@ -6864,7 +6950,9 @@ function isSyncNeeded(db) {
|
|
|
6864
6950
|
return __awaiter(this, void 0, void 0, function* () {
|
|
6865
6951
|
var _a;
|
|
6866
6952
|
return ((_a = db.cloud.options) === null || _a === void 0 ? void 0 : _a.databaseUrl) && db.cloud.schema
|
|
6867
|
-
? yield sync(db, db.cloud.options, db.cloud.schema, {
|
|
6953
|
+
? yield sync(db, db.cloud.options, db.cloud.schema, {
|
|
6954
|
+
justCheckIfNeeded: true,
|
|
6955
|
+
})
|
|
6868
6956
|
: false;
|
|
6869
6957
|
});
|
|
6870
6958
|
}
|
|
@@ -7076,243 +7164,243 @@ var n,l$1,u$1,i$1,r$1,o$1,e$1,f$1,c$1,s$1,a$1,p$1={},v$1=[],y=/acit|ex(?:s|g|n|p
|
|
|
7076
7164
|
const Styles = {
|
|
7077
7165
|
Alert: {
|
|
7078
7166
|
error: {
|
|
7079
|
-
color:
|
|
7080
|
-
fontWeight:
|
|
7167
|
+
color: 'red',
|
|
7168
|
+
fontWeight: 'bold',
|
|
7081
7169
|
},
|
|
7082
7170
|
warning: {
|
|
7083
|
-
color:
|
|
7084
|
-
fontWeight:
|
|
7171
|
+
color: '#f80',
|
|
7172
|
+
fontWeight: 'bold',
|
|
7085
7173
|
},
|
|
7086
7174
|
info: {
|
|
7087
|
-
color:
|
|
7088
|
-
}
|
|
7175
|
+
color: 'black',
|
|
7176
|
+
},
|
|
7089
7177
|
},
|
|
7090
7178
|
Darken: {
|
|
7091
|
-
position:
|
|
7179
|
+
position: 'fixed',
|
|
7092
7180
|
top: 0,
|
|
7093
7181
|
left: 0,
|
|
7094
7182
|
opacity: 0.5,
|
|
7095
|
-
backgroundColor:
|
|
7096
|
-
width:
|
|
7097
|
-
height:
|
|
7183
|
+
backgroundColor: '#000',
|
|
7184
|
+
width: '100vw',
|
|
7185
|
+
height: '100vh',
|
|
7098
7186
|
zIndex: 150,
|
|
7099
|
-
webkitBackdropFilter:
|
|
7100
|
-
backdropFilter:
|
|
7187
|
+
webkitBackdropFilter: 'blur(2px)',
|
|
7188
|
+
backdropFilter: 'blur(2px)',
|
|
7101
7189
|
},
|
|
7102
7190
|
DialogOuter: {
|
|
7103
|
-
position:
|
|
7191
|
+
position: 'fixed',
|
|
7104
7192
|
top: 0,
|
|
7105
7193
|
left: 0,
|
|
7106
|
-
width:
|
|
7107
|
-
height:
|
|
7194
|
+
width: '100vw',
|
|
7195
|
+
height: '100vh',
|
|
7108
7196
|
zIndex: 150,
|
|
7109
|
-
alignItems:
|
|
7110
|
-
display:
|
|
7111
|
-
justifyContent:
|
|
7112
|
-
padding:
|
|
7113
|
-
boxSizing:
|
|
7197
|
+
alignItems: 'center',
|
|
7198
|
+
display: 'flex',
|
|
7199
|
+
justifyContent: 'center',
|
|
7200
|
+
padding: '16px',
|
|
7201
|
+
boxSizing: 'border-box',
|
|
7114
7202
|
},
|
|
7115
7203
|
DialogInner: {
|
|
7116
|
-
position:
|
|
7117
|
-
color:
|
|
7118
|
-
backgroundColor:
|
|
7119
|
-
padding:
|
|
7120
|
-
marginBottom:
|
|
7121
|
-
maxWidth:
|
|
7122
|
-
width:
|
|
7123
|
-
maxHeight:
|
|
7124
|
-
overflowY:
|
|
7125
|
-
border:
|
|
7126
|
-
borderRadius:
|
|
7127
|
-
boxShadow:
|
|
7128
|
-
fontFamily:
|
|
7129
|
-
boxSizing:
|
|
7204
|
+
position: 'relative',
|
|
7205
|
+
color: '#222',
|
|
7206
|
+
backgroundColor: '#fff',
|
|
7207
|
+
padding: '24px',
|
|
7208
|
+
marginBottom: '2em',
|
|
7209
|
+
maxWidth: '400px',
|
|
7210
|
+
width: '100%',
|
|
7211
|
+
maxHeight: '90%',
|
|
7212
|
+
overflowY: 'auto',
|
|
7213
|
+
border: '3px solid #3d3d5d',
|
|
7214
|
+
borderRadius: '8px',
|
|
7215
|
+
boxShadow: '0 0 80px 10px #666',
|
|
7216
|
+
fontFamily: 'sans-serif',
|
|
7217
|
+
boxSizing: 'border-box',
|
|
7130
7218
|
},
|
|
7131
7219
|
Input: {
|
|
7132
|
-
height:
|
|
7133
|
-
width:
|
|
7134
|
-
maxWidth:
|
|
7135
|
-
borderColor:
|
|
7136
|
-
outline:
|
|
7137
|
-
fontSize:
|
|
7138
|
-
padding:
|
|
7139
|
-
boxSizing:
|
|
7140
|
-
backgroundColor:
|
|
7141
|
-
borderRadius:
|
|
7142
|
-
border:
|
|
7143
|
-
marginTop:
|
|
7144
|
-
fontFamily:
|
|
7220
|
+
height: '35px',
|
|
7221
|
+
width: '100%',
|
|
7222
|
+
maxWidth: '100%',
|
|
7223
|
+
borderColor: '#ccf4',
|
|
7224
|
+
outline: 'none',
|
|
7225
|
+
fontSize: '16px',
|
|
7226
|
+
padding: '8px',
|
|
7227
|
+
boxSizing: 'border-box',
|
|
7228
|
+
backgroundColor: '#f9f9f9',
|
|
7229
|
+
borderRadius: '4px',
|
|
7230
|
+
border: '1px solid #ccc',
|
|
7231
|
+
marginTop: '6px',
|
|
7232
|
+
fontFamily: 'inherit',
|
|
7145
7233
|
},
|
|
7146
7234
|
Button: {
|
|
7147
|
-
padding:
|
|
7148
|
-
margin:
|
|
7149
|
-
border:
|
|
7150
|
-
borderRadius:
|
|
7151
|
-
backgroundColor:
|
|
7152
|
-
cursor:
|
|
7153
|
-
fontSize:
|
|
7154
|
-
fontWeight:
|
|
7155
|
-
color:
|
|
7156
|
-
transition:
|
|
7235
|
+
padding: '10px 20px',
|
|
7236
|
+
margin: '0 4px',
|
|
7237
|
+
border: '1px solid #d1d5db',
|
|
7238
|
+
borderRadius: '6px',
|
|
7239
|
+
backgroundColor: '#ffffff',
|
|
7240
|
+
cursor: 'pointer',
|
|
7241
|
+
fontSize: '14px',
|
|
7242
|
+
fontWeight: '500',
|
|
7243
|
+
color: '#374151',
|
|
7244
|
+
transition: 'all 0.2s ease',
|
|
7157
7245
|
},
|
|
7158
7246
|
PrimaryButton: {
|
|
7159
|
-
padding:
|
|
7160
|
-
margin:
|
|
7161
|
-
border:
|
|
7162
|
-
borderRadius:
|
|
7163
|
-
backgroundColor:
|
|
7164
|
-
color:
|
|
7165
|
-
cursor:
|
|
7166
|
-
fontSize:
|
|
7167
|
-
fontWeight:
|
|
7168
|
-
transition:
|
|
7247
|
+
padding: '10px 20px',
|
|
7248
|
+
margin: '0 4px',
|
|
7249
|
+
border: '1px solid #3b82f6',
|
|
7250
|
+
borderRadius: '6px',
|
|
7251
|
+
backgroundColor: '#3b82f6',
|
|
7252
|
+
color: 'white',
|
|
7253
|
+
cursor: 'pointer',
|
|
7254
|
+
fontSize: '14px',
|
|
7255
|
+
fontWeight: '500',
|
|
7256
|
+
transition: 'all 0.2s ease',
|
|
7169
7257
|
},
|
|
7170
7258
|
ButtonsDiv: {
|
|
7171
|
-
display:
|
|
7172
|
-
justifyContent:
|
|
7173
|
-
gap:
|
|
7174
|
-
marginTop:
|
|
7175
|
-
paddingTop:
|
|
7259
|
+
display: 'flex',
|
|
7260
|
+
justifyContent: 'flex-end',
|
|
7261
|
+
gap: '12px',
|
|
7262
|
+
marginTop: '24px',
|
|
7263
|
+
paddingTop: '20px',
|
|
7176
7264
|
},
|
|
7177
7265
|
Label: {
|
|
7178
|
-
display:
|
|
7179
|
-
marginBottom:
|
|
7180
|
-
fontSize:
|
|
7181
|
-
fontWeight:
|
|
7182
|
-
color:
|
|
7266
|
+
display: 'block',
|
|
7267
|
+
marginBottom: '12px',
|
|
7268
|
+
fontSize: '14px',
|
|
7269
|
+
fontWeight: '500',
|
|
7270
|
+
color: '#333',
|
|
7183
7271
|
},
|
|
7184
7272
|
WindowHeader: {
|
|
7185
|
-
margin:
|
|
7186
|
-
fontSize:
|
|
7187
|
-
fontWeight:
|
|
7188
|
-
color:
|
|
7189
|
-
borderBottom:
|
|
7190
|
-
paddingBottom:
|
|
7273
|
+
margin: '0 0 20px 0',
|
|
7274
|
+
fontSize: '18px',
|
|
7275
|
+
fontWeight: '600',
|
|
7276
|
+
color: '#333',
|
|
7277
|
+
borderBottom: '1px solid #eee',
|
|
7278
|
+
paddingBottom: '10px',
|
|
7191
7279
|
},
|
|
7192
7280
|
// OAuth Provider Button Styles
|
|
7193
7281
|
ProviderButton: {
|
|
7194
|
-
display:
|
|
7195
|
-
alignItems:
|
|
7196
|
-
justifyContent:
|
|
7197
|
-
width:
|
|
7198
|
-
padding:
|
|
7199
|
-
marginBottom:
|
|
7200
|
-
border:
|
|
7201
|
-
borderRadius:
|
|
7202
|
-
backgroundColor:
|
|
7203
|
-
cursor:
|
|
7204
|
-
fontSize:
|
|
7205
|
-
fontWeight:
|
|
7206
|
-
color:
|
|
7207
|
-
transition:
|
|
7208
|
-
gap:
|
|
7282
|
+
display: 'flex',
|
|
7283
|
+
alignItems: 'center',
|
|
7284
|
+
justifyContent: 'center',
|
|
7285
|
+
width: '100%',
|
|
7286
|
+
padding: '12px 16px',
|
|
7287
|
+
marginBottom: '10px',
|
|
7288
|
+
border: '1px solid #d1d5db',
|
|
7289
|
+
borderRadius: '6px',
|
|
7290
|
+
backgroundColor: '#ffffff',
|
|
7291
|
+
cursor: 'pointer',
|
|
7292
|
+
fontSize: '14px',
|
|
7293
|
+
fontWeight: '500',
|
|
7294
|
+
color: '#374151',
|
|
7295
|
+
transition: 'all 0.2s ease',
|
|
7296
|
+
gap: '12px',
|
|
7209
7297
|
},
|
|
7210
7298
|
ProviderButtonIcon: {
|
|
7211
|
-
width:
|
|
7212
|
-
height:
|
|
7299
|
+
width: '20px',
|
|
7300
|
+
height: '20px',
|
|
7213
7301
|
flexShrink: 0,
|
|
7214
|
-
display:
|
|
7215
|
-
alignItems:
|
|
7216
|
-
justifyContent:
|
|
7302
|
+
display: 'flex',
|
|
7303
|
+
alignItems: 'center',
|
|
7304
|
+
justifyContent: 'center',
|
|
7217
7305
|
},
|
|
7218
7306
|
ProviderButtonText: {
|
|
7219
7307
|
flex: 1,
|
|
7220
|
-
textAlign:
|
|
7308
|
+
textAlign: 'left',
|
|
7221
7309
|
},
|
|
7222
7310
|
// Provider-specific colors
|
|
7223
7311
|
ProviderGoogle: {
|
|
7224
|
-
backgroundColor:
|
|
7225
|
-
border:
|
|
7226
|
-
color:
|
|
7312
|
+
backgroundColor: '#ffffff',
|
|
7313
|
+
border: '1px solid #dadce0',
|
|
7314
|
+
color: '#3c4043',
|
|
7227
7315
|
},
|
|
7228
7316
|
ProviderGitHub: {
|
|
7229
|
-
backgroundColor:
|
|
7230
|
-
border:
|
|
7231
|
-
color:
|
|
7317
|
+
backgroundColor: '#ffffff',
|
|
7318
|
+
border: '1px solid #dadce0',
|
|
7319
|
+
color: '#181717',
|
|
7232
7320
|
},
|
|
7233
7321
|
ProviderMicrosoft: {
|
|
7234
|
-
backgroundColor:
|
|
7235
|
-
border:
|
|
7236
|
-
color:
|
|
7322
|
+
backgroundColor: '#ffffff',
|
|
7323
|
+
border: '1px solid #dadce0',
|
|
7324
|
+
color: '#5e5e5e',
|
|
7237
7325
|
},
|
|
7238
7326
|
ProviderApple: {
|
|
7239
|
-
backgroundColor:
|
|
7240
|
-
border:
|
|
7241
|
-
color:
|
|
7327
|
+
backgroundColor: '#000000',
|
|
7328
|
+
border: '1px solid #000000',
|
|
7329
|
+
color: '#ffffff',
|
|
7242
7330
|
},
|
|
7243
7331
|
ProviderCustom: {
|
|
7244
|
-
backgroundColor:
|
|
7245
|
-
border:
|
|
7246
|
-
color:
|
|
7332
|
+
backgroundColor: '#ffffff',
|
|
7333
|
+
border: '1px solid #dadce0',
|
|
7334
|
+
color: '#181717',
|
|
7247
7335
|
},
|
|
7248
7336
|
// Divider styles
|
|
7249
7337
|
Divider: {
|
|
7250
|
-
display:
|
|
7251
|
-
alignItems:
|
|
7252
|
-
margin:
|
|
7253
|
-
color:
|
|
7254
|
-
fontSize:
|
|
7338
|
+
display: 'flex',
|
|
7339
|
+
alignItems: 'center',
|
|
7340
|
+
margin: '20px 0',
|
|
7341
|
+
color: '#6b7280',
|
|
7342
|
+
fontSize: '13px',
|
|
7255
7343
|
},
|
|
7256
7344
|
DividerLine: {
|
|
7257
7345
|
flex: 1,
|
|
7258
|
-
height:
|
|
7259
|
-
backgroundColor:
|
|
7346
|
+
height: '1px',
|
|
7347
|
+
backgroundColor: '#e5e7eb',
|
|
7260
7348
|
},
|
|
7261
7349
|
DividerText: {
|
|
7262
|
-
padding:
|
|
7263
|
-
color:
|
|
7350
|
+
padding: '0 12px',
|
|
7351
|
+
color: '#9ca3af',
|
|
7264
7352
|
},
|
|
7265
7353
|
// OTP Button (Continue with email)
|
|
7266
7354
|
OtpButton: {
|
|
7267
|
-
display:
|
|
7268
|
-
alignItems:
|
|
7269
|
-
justifyContent:
|
|
7270
|
-
width:
|
|
7271
|
-
padding:
|
|
7272
|
-
border:
|
|
7273
|
-
borderRadius:
|
|
7274
|
-
backgroundColor:
|
|
7275
|
-
cursor:
|
|
7276
|
-
fontSize:
|
|
7277
|
-
fontWeight:
|
|
7278
|
-
color:
|
|
7279
|
-
transition:
|
|
7280
|
-
gap:
|
|
7355
|
+
display: 'flex',
|
|
7356
|
+
alignItems: 'center',
|
|
7357
|
+
justifyContent: 'center',
|
|
7358
|
+
width: '100%',
|
|
7359
|
+
padding: '12px 16px',
|
|
7360
|
+
border: '1px solid #d1d5db',
|
|
7361
|
+
borderRadius: '6px',
|
|
7362
|
+
backgroundColor: '#f9fafb',
|
|
7363
|
+
cursor: 'pointer',
|
|
7364
|
+
fontSize: '14px',
|
|
7365
|
+
fontWeight: '500',
|
|
7366
|
+
color: '#374151',
|
|
7367
|
+
transition: 'all 0.2s ease',
|
|
7368
|
+
gap: '12px',
|
|
7281
7369
|
},
|
|
7282
7370
|
// Copy button for alerts with copyText
|
|
7283
7371
|
CopyButton: {
|
|
7284
|
-
display:
|
|
7285
|
-
alignItems:
|
|
7286
|
-
gap:
|
|
7287
|
-
padding:
|
|
7288
|
-
marginTop:
|
|
7289
|
-
border:
|
|
7290
|
-
borderRadius:
|
|
7291
|
-
backgroundColor:
|
|
7292
|
-
cursor:
|
|
7293
|
-
fontSize:
|
|
7294
|
-
fontWeight:
|
|
7295
|
-
color:
|
|
7296
|
-
transition:
|
|
7297
|
-
fontFamily:
|
|
7372
|
+
display: 'inline-flex',
|
|
7373
|
+
alignItems: 'center',
|
|
7374
|
+
gap: '4px',
|
|
7375
|
+
padding: '4px 10px',
|
|
7376
|
+
marginTop: '8px',
|
|
7377
|
+
border: '1px solid #d1d5db',
|
|
7378
|
+
borderRadius: '4px',
|
|
7379
|
+
backgroundColor: '#f9fafb',
|
|
7380
|
+
cursor: 'pointer',
|
|
7381
|
+
fontSize: '12px',
|
|
7382
|
+
fontWeight: '500',
|
|
7383
|
+
color: '#374151',
|
|
7384
|
+
transition: 'all 0.15s ease',
|
|
7385
|
+
fontFamily: 'monospace',
|
|
7298
7386
|
},
|
|
7299
7387
|
CopyButtonCopied: {
|
|
7300
|
-
display:
|
|
7301
|
-
alignItems:
|
|
7302
|
-
gap:
|
|
7303
|
-
padding:
|
|
7304
|
-
marginTop:
|
|
7305
|
-
border:
|
|
7306
|
-
borderRadius:
|
|
7307
|
-
backgroundColor:
|
|
7308
|
-
cursor:
|
|
7309
|
-
fontSize:
|
|
7310
|
-
fontWeight:
|
|
7311
|
-
color:
|
|
7312
|
-
fontFamily:
|
|
7388
|
+
display: 'inline-flex',
|
|
7389
|
+
alignItems: 'center',
|
|
7390
|
+
gap: '4px',
|
|
7391
|
+
padding: '4px 10px',
|
|
7392
|
+
marginTop: '8px',
|
|
7393
|
+
border: '1px solid #22c55e',
|
|
7394
|
+
borderRadius: '4px',
|
|
7395
|
+
backgroundColor: '#f0fdf4',
|
|
7396
|
+
cursor: 'default',
|
|
7397
|
+
fontSize: '12px',
|
|
7398
|
+
fontWeight: '500',
|
|
7399
|
+
color: '#16a34a',
|
|
7400
|
+
fontFamily: 'monospace',
|
|
7313
7401
|
}};
|
|
7314
7402
|
|
|
7315
|
-
function Dialog({ children, className }) {
|
|
7403
|
+
function Dialog({ children, className, }) {
|
|
7316
7404
|
return (_$1("div", { className: `dexie-dialog ${className || ''}` },
|
|
7317
7405
|
_$1("div", { style: Styles.Darken }),
|
|
7318
7406
|
_$1("div", { style: Styles.DialogOuter },
|
|
@@ -7336,7 +7424,7 @@ var t,r,u,i,o=0,f=[],c=l$1,e=c.__b,a=c.__r,v=c.diffed,l=c.__c,m=c.unmount,s=c.__
|
|
|
7336
7424
|
* @returns A final message where parameters have been replaced with values.
|
|
7337
7425
|
*/
|
|
7338
7426
|
function resolveText({ message, messageCode, messageParams }) {
|
|
7339
|
-
return message.replace(/\{\w+\}/
|
|
7427
|
+
return message.replace(/\{\w+\}/gi, (n) => messageParams[n.substring(1, n.length - 1)]);
|
|
7340
7428
|
}
|
|
7341
7429
|
|
|
7342
7430
|
/** Get style based on styleHint (for provider branding, etc.) */
|
|
@@ -7423,13 +7511,13 @@ function LoginDialog({ title, alerts, fields, options, submitLabel, cancelLabel,
|
|
|
7423
7511
|
alerts.map((alert, idx) => (_$1("div", { key: idx },
|
|
7424
7512
|
_$1("p", { style: Styles.Alert[alert.type] }, resolveText(alert)),
|
|
7425
7513
|
alert.copyText && _$1(CopyButton, { text: alert.copyText })))),
|
|
7426
|
-
hasOptions && (_$1("div", { class: "dxc-options" }, hasMultipleGroups
|
|
7427
|
-
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
|
|
7431
|
-
|
|
7432
|
-
|
|
7514
|
+
hasOptions && (_$1("div", { class: "dxc-options" }, hasMultipleGroups
|
|
7515
|
+
? // Render with dividers between groups
|
|
7516
|
+
Array.from(optionGroups.entries()).map(([groupName, groupOptions], groupIdx) => (_$1(k$1, { key: groupName },
|
|
7517
|
+
groupIdx > 0 && _$1(Divider, null),
|
|
7518
|
+
groupOptions.map((option) => (_$1(OptionButton, { key: `${option.name}-${option.value}`, option: option, onClick: () => handleOptionClick(option) }))))))
|
|
7519
|
+
: // Simple case: all options in one group
|
|
7520
|
+
options.map((option) => (_$1(OptionButton, { key: `${option.name}-${option.value}`, option: option, onClick: () => handleOptionClick(option) }))))),
|
|
7433
7521
|
hasOptions && hasFields && _$1(Divider, null),
|
|
7434
7522
|
hasFields && (_$1("form", { onSubmit: (ev) => {
|
|
7435
7523
|
ev.preventDefault();
|
|
@@ -7441,7 +7529,8 @@ function LoginDialog({ title, alerts, fields, options, submitLabel, cancelLabel,
|
|
|
7441
7529
|
const value = valueTransformer(type, (_a = ev.target) === null || _a === void 0 ? void 0 : _a['value']);
|
|
7442
7530
|
let updatedParams = Object.assign(Object.assign({}, params), { [fieldName]: value });
|
|
7443
7531
|
setParams(updatedParams);
|
|
7444
|
-
if (type === 'otp' &&
|
|
7532
|
+
if (type === 'otp' &&
|
|
7533
|
+
(value === null || value === void 0 ? void 0 : value.trim().length) === OTP_LENGTH) {
|
|
7445
7534
|
// Auto-submit when OTP is filled in.
|
|
7446
7535
|
onSubmit(updatedParams);
|
|
7447
7536
|
}
|
|
@@ -7483,7 +7572,10 @@ function CopyButton({ text }) {
|
|
|
7483
7572
|
const handleClick = () => {
|
|
7484
7573
|
var _a;
|
|
7485
7574
|
if (typeof navigator !== 'undefined' && ((_a = navigator.clipboard) === null || _a === void 0 ? void 0 : _a.writeText)) {
|
|
7486
|
-
navigator.clipboard
|
|
7575
|
+
navigator.clipboard
|
|
7576
|
+
.writeText(text)
|
|
7577
|
+
.then(scheduleCopiedReset)
|
|
7578
|
+
.catch(() => {
|
|
7487
7579
|
fallbackCopy(text, scheduleCopiedReset);
|
|
7488
7580
|
});
|
|
7489
7581
|
}
|
|
@@ -7554,7 +7646,7 @@ function setupDefaultGUI(db) {
|
|
|
7554
7646
|
},
|
|
7555
7647
|
get closed() {
|
|
7556
7648
|
return closed;
|
|
7557
|
-
}
|
|
7649
|
+
},
|
|
7558
7650
|
};
|
|
7559
7651
|
}
|
|
7560
7652
|
|
|
@@ -7599,14 +7691,14 @@ function computeSyncState(db) {
|
|
|
7599
7691
|
lazyWebSocketStatus,
|
|
7600
7692
|
db.syncStateChangedEvent.pipe(startWith({ phase: 'initial' })),
|
|
7601
7693
|
getCurrentUserEmitter(db.dx._novip),
|
|
7602
|
-
userIsReallyActive
|
|
7694
|
+
userIsReallyActive,
|
|
7603
7695
|
]).pipe(map(([status, syncState, user, userIsActive]) => {
|
|
7604
7696
|
var _a;
|
|
7605
7697
|
if (((_a = user.license) === null || _a === void 0 ? void 0 : _a.status) && user.license.status !== 'ok') {
|
|
7606
7698
|
return {
|
|
7607
7699
|
phase: 'offline',
|
|
7608
7700
|
status: 'offline',
|
|
7609
|
-
license: user.license.status
|
|
7701
|
+
license: user.license.status,
|
|
7610
7702
|
};
|
|
7611
7703
|
}
|
|
7612
7704
|
let { phase, error, progress } = syncState;
|
|
@@ -7626,7 +7718,8 @@ function computeSyncState(db) {
|
|
|
7626
7718
|
}
|
|
7627
7719
|
const previousPhase = db.cloud.syncState.value.phase;
|
|
7628
7720
|
//const previousStatus = db.cloud.syncState.value.status;
|
|
7629
|
-
if (previousPhase === 'error' &&
|
|
7721
|
+
if (previousPhase === 'error' &&
|
|
7722
|
+
(syncState.phase === 'pushing' || syncState.phase === 'pulling')) {
|
|
7630
7723
|
// We were in an errored state but is now doing sync. Show "connecting" icon.
|
|
7631
7724
|
adjustedStatus = 'connecting';
|
|
7632
7725
|
}
|
|
@@ -7641,7 +7734,7 @@ function computeSyncState(db) {
|
|
|
7641
7734
|
error,
|
|
7642
7735
|
progress,
|
|
7643
7736
|
status: isOnline ? adjustedStatus : 'offline',
|
|
7644
|
-
license: 'ok'
|
|
7737
|
+
license: 'ok',
|
|
7645
7738
|
};
|
|
7646
7739
|
return retState;
|
|
7647
7740
|
}));
|
|
@@ -7662,7 +7755,7 @@ function createSharedValueObservable(o, defaultValue) {
|
|
|
7662
7755
|
},
|
|
7663
7756
|
complete() {
|
|
7664
7757
|
observer.complete();
|
|
7665
|
-
}
|
|
7758
|
+
},
|
|
7666
7759
|
});
|
|
7667
7760
|
if (!didEmit && !subscription.closed) {
|
|
7668
7761
|
observer.next(currentValue);
|
|
@@ -7903,7 +7996,9 @@ function permissions(dexie, obj, tableName) {
|
|
|
7903
7996
|
const realm = permissionsLookup[realmId || dexie.cloud.currentUserId];
|
|
7904
7997
|
if (!realm)
|
|
7905
7998
|
return new PermissionChecker({}, tableName, !owner || owner === dexie.cloud.currentUserId);
|
|
7906
|
-
return new PermissionChecker(realm.permissions, tableName, realmId === undefined ||
|
|
7999
|
+
return new PermissionChecker(realm.permissions, tableName, realmId === undefined ||
|
|
8000
|
+
realmId === dexie.cloud.currentUserId ||
|
|
8001
|
+
owner === dexie.cloud.currentUserId);
|
|
7907
8002
|
};
|
|
7908
8003
|
const o = source.pipe(map(mapper));
|
|
7909
8004
|
o.getValue = () => mapper(source.getValue());
|
|
@@ -7945,7 +8040,19 @@ function createYHandler(db) {
|
|
|
7945
8040
|
return; // The table that holds the doc is not marked for sync - leave it to dexie. No syncing, no awareness.
|
|
7946
8041
|
}
|
|
7947
8042
|
let awareness;
|
|
8043
|
+
const existingDescriptor = Object.getOwnPropertyDescriptor(provider, 'awareness');
|
|
8044
|
+
if (existingDescriptor) {
|
|
8045
|
+
// Provider already initialized — likely a leaked handler from a previous db instance
|
|
8046
|
+
// (e.g. HMR where db.close() didn't fire). Destroy the stale awareness so the new
|
|
8047
|
+
// handler can take over cleanly.
|
|
8048
|
+
const staleAwareness = provider.awareness;
|
|
8049
|
+
if (staleAwareness) {
|
|
8050
|
+
staleAwareness.destroy();
|
|
8051
|
+
awarenessWeakMap.delete(doc);
|
|
8052
|
+
}
|
|
8053
|
+
}
|
|
7948
8054
|
Object.defineProperty(provider, 'awareness', {
|
|
8055
|
+
configurable: true,
|
|
7949
8056
|
get() {
|
|
7950
8057
|
if (awareness)
|
|
7951
8058
|
return awareness;
|
|
@@ -8128,10 +8235,12 @@ function parseOAuthCallback(url) {
|
|
|
8128
8235
|
const { code, provider, state, error } = payload;
|
|
8129
8236
|
// Check for error first
|
|
8130
8237
|
if (error) {
|
|
8131
|
-
if (error.toLowerCase().includes('access_denied') ||
|
|
8238
|
+
if (error.toLowerCase().includes('access_denied') ||
|
|
8239
|
+
error.toLowerCase().includes('access denied')) {
|
|
8132
8240
|
throw new OAuthError('access_denied', provider, error);
|
|
8133
8241
|
}
|
|
8134
|
-
if (error.toLowerCase().includes('email') &&
|
|
8242
|
+
if (error.toLowerCase().includes('email') &&
|
|
8243
|
+
error.toLowerCase().includes('verif')) {
|
|
8135
8244
|
throw new OAuthError('email_not_verified', provider, error);
|
|
8136
8245
|
}
|
|
8137
8246
|
throw new OAuthError('provider_error', provider, error);
|
|
@@ -8157,7 +8266,9 @@ function cleanupOAuthUrl() {
|
|
|
8157
8266
|
return;
|
|
8158
8267
|
}
|
|
8159
8268
|
url.searchParams.delete('dxc-auth');
|
|
8160
|
-
const cleanUrl = url.pathname +
|
|
8269
|
+
const cleanUrl = url.pathname +
|
|
8270
|
+
(url.searchParams.toString() ? `?${url.searchParams.toString()}` : '') +
|
|
8271
|
+
url.hash;
|
|
8161
8272
|
window.history.replaceState(null, '', cleanUrl);
|
|
8162
8273
|
}
|
|
8163
8274
|
|
|
@@ -8170,8 +8281,8 @@ function getTiedObjectId(realmId) {
|
|
|
8170
8281
|
|
|
8171
8282
|
const ydocTriggers = {};
|
|
8172
8283
|
const middlewares = new WeakMap();
|
|
8173
|
-
const txRunner = TriggerRunner(
|
|
8174
|
-
const unloadRunner = TriggerRunner(
|
|
8284
|
+
const txRunner = TriggerRunner('tx'); // Trigger registry for transaction completion. Avoids open docs.
|
|
8285
|
+
const unloadRunner = TriggerRunner('unload'); // Trigger registry for unload. Runs when a document is closed.
|
|
8175
8286
|
function TriggerRunner(name) {
|
|
8176
8287
|
let triggerExecPromise = null;
|
|
8177
8288
|
let triggerScheduled = false;
|
|
@@ -8210,7 +8321,7 @@ function TriggerRunner(name) {
|
|
|
8210
8321
|
yield triggerExecPromise.catch(() => { });
|
|
8211
8322
|
setTimeout(() => {
|
|
8212
8323
|
// setTimeout() is to escape from Promise.PSD zones and never run within liveQueries or transaction scopes
|
|
8213
|
-
console.log(
|
|
8324
|
+
console.log('Running trigger really!', name);
|
|
8214
8325
|
triggerScheduled = false;
|
|
8215
8326
|
const registryCopy = registry;
|
|
8216
8327
|
registry = new Map();
|
|
@@ -8377,7 +8488,7 @@ function dexieCloud(dexie) {
|
|
|
8377
8488
|
const downloading$ = createDownloadingState();
|
|
8378
8489
|
dexie.cloud = {
|
|
8379
8490
|
// @ts-ignore
|
|
8380
|
-
version: "4.4.
|
|
8491
|
+
version: "4.4.7",
|
|
8381
8492
|
options: Object.assign({}, DEFAULT_OPTIONS),
|
|
8382
8493
|
schema: null,
|
|
8383
8494
|
get currentUserId() {
|
|
@@ -8433,7 +8544,10 @@ function dexieCloud(dexie) {
|
|
|
8433
8544
|
const callback = parseOAuthCallback();
|
|
8434
8545
|
if (callback) {
|
|
8435
8546
|
// Store the pending auth code for processing when db is ready
|
|
8436
|
-
pendingOAuthCode = {
|
|
8547
|
+
pendingOAuthCode = {
|
|
8548
|
+
code: callback.code,
|
|
8549
|
+
provider: callback.provider,
|
|
8550
|
+
};
|
|
8437
8551
|
console.debug('[dexie-cloud] OAuth callback detected, auth code stored for processing');
|
|
8438
8552
|
}
|
|
8439
8553
|
}
|
|
@@ -8550,7 +8664,7 @@ function dexieCloud(dexie) {
|
|
|
8550
8664
|
if (eagerBlobDownloadInFlight)
|
|
8551
8665
|
return;
|
|
8552
8666
|
eagerBlobDownloadInFlight = Dexie.ignoreTransaction(() => downloadUnresolvedBlobs(db, downloading$))
|
|
8553
|
-
.catch(err => {
|
|
8667
|
+
.catch((err) => {
|
|
8554
8668
|
console.error('[dexie-cloud] Eager blob download failed:', err);
|
|
8555
8669
|
})
|
|
8556
8670
|
.finally(() => {
|
|
@@ -8643,7 +8757,10 @@ function dexieCloud(dexie) {
|
|
|
8643
8757
|
// Let's assign all props as the newPersistedSchems should be what we should be working with.
|
|
8644
8758
|
Object.assign(schema, newPersistedSchema);
|
|
8645
8759
|
}
|
|
8646
|
-
return [
|
|
8760
|
+
return [
|
|
8761
|
+
persistedSyncState === null || persistedSyncState === void 0 ? void 0 : persistedSyncState.initiallySynced,
|
|
8762
|
+
persistedSyncState === null || persistedSyncState === void 0 ? void 0 : persistedSyncState.realms,
|
|
8763
|
+
];
|
|
8647
8764
|
}));
|
|
8648
8765
|
if (initiallySynced) {
|
|
8649
8766
|
db.setInitiallySynced(true);
|
|
@@ -8652,8 +8769,10 @@ function dexieCloud(dexie) {
|
|
|
8652
8769
|
// Manage CurrentUser observable:
|
|
8653
8770
|
throwIfClosed();
|
|
8654
8771
|
if (!db.cloud.isServiceWorkerDB) {
|
|
8655
|
-
subscriptions.push(liveQuery(() => db.getCurrentUser().then(user => {
|
|
8656
|
-
if (!user.isLoggedIn &&
|
|
8772
|
+
subscriptions.push(liveQuery(() => db.getCurrentUser().then((user) => {
|
|
8773
|
+
if (!user.isLoggedIn &&
|
|
8774
|
+
typeof location !== 'undefined' &&
|
|
8775
|
+
/dxc-auth\=/.test(location.search)) {
|
|
8657
8776
|
// Still loading user because OAuth redirect just happened.
|
|
8658
8777
|
// Keep isLoading true.
|
|
8659
8778
|
return Object.assign(Object.assign({}, user), { isLoading: true });
|
|
@@ -8691,7 +8810,7 @@ function dexieCloud(dexie) {
|
|
|
8691
8810
|
type: 'error',
|
|
8692
8811
|
messageCode: 'GENERIC_ERROR',
|
|
8693
8812
|
message: error.message,
|
|
8694
|
-
messageParams: { provider: error.provider || 'unknown' }
|
|
8813
|
+
messageParams: { provider: error.provider || 'unknown' },
|
|
8695
8814
|
});
|
|
8696
8815
|
// Clean up URL (remove dxc-auth param)
|
|
8697
8816
|
cleanupOAuthUrl();
|
|
@@ -8741,7 +8860,8 @@ function dexieCloud(dexie) {
|
|
|
8741
8860
|
}
|
|
8742
8861
|
}
|
|
8743
8862
|
}
|
|
8744
|
-
if (user.isLoggedIn &&
|
|
8863
|
+
if (user.isLoggedIn &&
|
|
8864
|
+
(!lastSyncedRealms || !lastSyncedRealms.includes(user.userId))) {
|
|
8745
8865
|
// User has been logged in but this is not reflected in the sync state.
|
|
8746
8866
|
// This can happen if page is reloaded after login but before the sync call following
|
|
8747
8867
|
// the login was complete.
|
|
@@ -8804,7 +8924,7 @@ function dexieCloud(dexie) {
|
|
|
8804
8924
|
}
|
|
8805
8925
|
}
|
|
8806
8926
|
// @ts-ignore
|
|
8807
|
-
dexieCloud.version = "4.4.
|
|
8927
|
+
dexieCloud.version = "4.4.7";
|
|
8808
8928
|
Dexie.Cloud = dexieCloud;
|
|
8809
8929
|
|
|
8810
8930
|
export { dexieCloud as default, defineYDocTrigger, dexieCloud, getTiedObjectId, getTiedRealmId, resolveText };
|