dexie-cloud-addon 4.0.1-beta.46 → 4.0.1-beta.48
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/{types → modern}/DexieCloudAPI.d.ts +3 -0
- package/dist/{types → modern}/DexieCloudOptions.d.ts +1 -0
- package/dist/modern/InvalidLicenseError.d.ts +5 -0
- package/dist/{types → modern}/TSON.d.ts +1 -1
- package/dist/modern/authentication/TokenErrorResponseError.d.ts +10 -0
- package/dist/{types → modern}/authentication/authenticate.d.ts +3 -3
- package/dist/{types → modern}/authentication/interactWithUser.d.ts +3 -0
- package/dist/modern/authentication/logout.d.ts +5 -0
- package/dist/modern/authentication/waitUntil.d.ts +3 -0
- package/dist/{types → modern}/currentUserEmitter.d.ts +1 -1
- package/dist/{types → modern}/db/entities/UserLogin.d.ts +6 -0
- package/dist/modern/default-ui/LoginDialog.d.ts +3 -0
- package/dist/modern/dexie-cloud-addon.d.ts +3 -0
- package/dist/modern/dexie-cloud-addon.js +488 -367
- package/dist/modern/dexie-cloud-addon.js.map +1 -1
- package/dist/modern/dexie-cloud-addon.min.js +2 -2
- package/dist/modern/dexie-cloud-addon.min.js.map +1 -1
- package/dist/{types → modern}/dexie-cloud-client.d.ts +2 -0
- package/dist/modern/helpers/resolveText.d.ts +16 -0
- package/dist/modern/isEagerSyncDisabled.d.ts +2 -0
- package/dist/{types → modern}/middlewares/createMutationTrackingMiddleware.d.ts +1 -1
- package/dist/modern/prodLog.d.ts +9 -0
- package/dist/modern/service-worker.js +2027 -268
- package/dist/modern/service-worker.js.map +1 -1
- package/dist/modern/service-worker.min.js +2 -2
- package/dist/modern/service-worker.min.js.map +1 -1
- package/dist/modern/sync/performGuardedJob.d.ts +2 -0
- package/dist/modern/sync/ratelimit.d.ts +3 -0
- package/dist/{types → modern}/sync/sync.d.ts +0 -1
- package/dist/{types → modern}/types/DXCAlert.d.ts +1 -1
- package/dist/{types → modern}/types/DXCUserInteraction.d.ts +40 -2
- package/dist/{types → modern}/types/SyncState.d.ts +1 -0
- package/dist/umd/DISABLE_SERVICEWORKER_STRATEGY.d.ts +1 -0
- package/dist/umd/DXCWebSocketStatus.d.ts +1 -0
- package/dist/umd/DexieCloudAPI.d.ts +72 -0
- package/dist/umd/DexieCloudOptions.d.ts +22 -0
- package/dist/umd/DexieCloudSyncOptions.d.ts +4 -0
- package/dist/umd/DexieCloudTable.d.ts +18 -0
- package/dist/umd/InvalidLicenseError.d.ts +5 -0
- package/dist/umd/Invite.d.ts +8 -0
- package/dist/umd/PermissionChecker.d.ts +15 -0
- package/dist/umd/TSON.d.ts +17 -0
- package/dist/umd/WSObservable.d.ts +68 -0
- package/dist/umd/associate.d.ts +1 -0
- package/dist/umd/authentication/AuthPersistedContext.d.ts +9 -0
- package/dist/umd/authentication/TokenErrorResponseError.d.ts +10 -0
- package/dist/umd/authentication/TokenExpiredError.d.ts +3 -0
- package/dist/umd/authentication/UNAUTHORIZED_USER.d.ts +2 -0
- package/dist/umd/authentication/authenticate.d.ts +20 -0
- package/dist/umd/authentication/currentUserObservable.d.ts +1 -0
- package/dist/umd/authentication/interactWithUser.d.ts +21 -0
- package/dist/umd/authentication/login.d.ts +6 -0
- package/dist/umd/authentication/logout.d.ts +5 -0
- package/dist/umd/authentication/otpFetchTokenCallback.d.ts +3 -0
- package/dist/umd/authentication/setCurrentUser.d.ts +14 -0
- package/dist/umd/authentication/waitUntil.d.ts +3 -0
- package/dist/umd/computeSyncState.d.ts +4 -0
- package/dist/umd/createSharedValueObservable.d.ts +3 -0
- package/dist/umd/currentUserEmitter.d.ts +3 -0
- package/dist/umd/db/DexieCloudDB.d.ts +59 -0
- package/dist/umd/db/entities/BaseRevisionMapEntry.d.ts +5 -0
- package/dist/umd/db/entities/EntityCommon.d.ts +5 -0
- package/dist/umd/db/entities/GuardedJob.d.ts +5 -0
- package/dist/umd/db/entities/Member.d.ts +19 -0
- package/dist/umd/db/entities/PersistedSyncState.d.ts +14 -0
- package/dist/umd/db/entities/Realm.d.ts +16 -0
- package/dist/umd/db/entities/Role.d.ts +11 -0
- package/dist/umd/db/entities/UserLogin.d.ts +22 -0
- package/dist/umd/default-ui/Dialog.d.ts +5 -0
- package/dist/umd/default-ui/LoginDialog.d.ts +3 -0
- package/dist/umd/default-ui/Styles.d.ts +3 -0
- package/dist/umd/default-ui/index.d.ts +24 -0
- package/dist/umd/dexie-cloud-addon.d.ts +3 -0
- package/dist/umd/dexie-cloud-addon.js +505 -388
- package/dist/umd/dexie-cloud-addon.js.map +1 -1
- package/dist/umd/dexie-cloud-client.d.ts +13 -0
- package/dist/umd/errors/HttpError.d.ts +5 -0
- package/dist/umd/extend-dexie-interface.d.ts +23 -0
- package/dist/umd/getGlobalRolesObservable.d.ts +5 -0
- package/dist/umd/getInternalAccessControlObservable.d.ts +12 -0
- package/dist/umd/getInvitesObservable.d.ts +23 -0
- package/dist/umd/getPermissionsLookupObservable.d.ts +16 -0
- package/dist/umd/getTiedRealmId.d.ts +2 -0
- package/dist/umd/helpers/BroadcastedAndLocalEvent.d.ts +8 -0
- package/dist/umd/helpers/CancelToken.d.ts +4 -0
- package/dist/umd/helpers/IS_SERVICE_WORKER.d.ts +1 -0
- package/dist/umd/helpers/SWBroadcastChannel.d.ts +12 -0
- package/dist/umd/helpers/allSettled.d.ts +1 -0
- package/dist/umd/helpers/bulkUpdate.d.ts +4 -0
- package/dist/umd/helpers/computeRealmSetHash.d.ts +2 -0
- package/dist/umd/helpers/date-constants.d.ts +5 -0
- package/dist/umd/helpers/dbOnClosed.d.ts +2 -0
- package/dist/umd/helpers/flatten.d.ts +1 -0
- package/dist/umd/helpers/getMutationTable.d.ts +1 -0
- package/dist/umd/helpers/getSyncableTables.d.ts +4 -0
- package/dist/umd/helpers/getTableFromMutationTable.d.ts +1 -0
- package/dist/umd/helpers/makeArray.d.ts +1 -0
- package/dist/umd/helpers/randomString.d.ts +1 -0
- package/dist/umd/helpers/resolveText.d.ts +16 -0
- package/dist/umd/helpers/throwVersionIncrementNeeded.d.ts +1 -0
- package/dist/umd/helpers/visibilityState.d.ts +1 -0
- package/dist/umd/isEagerSyncDisabled.d.ts +2 -0
- package/dist/umd/isFirefox.d.ts +1 -0
- package/dist/umd/isSafari.d.ts +2 -0
- package/dist/umd/mapValueObservable.d.ts +5 -0
- package/dist/umd/mergePermissions.d.ts +2 -0
- package/dist/umd/middleware-helpers/guardedTable.d.ts +11 -0
- package/dist/umd/middleware-helpers/idGenerationHelpers.d.ts +18 -0
- package/dist/umd/middlewares/createIdGenerationMiddleware.d.ts +3 -0
- package/dist/umd/middlewares/createImplicitPropSetterMiddleware.d.ts +3 -0
- package/dist/umd/middlewares/createMutationTrackingMiddleware.d.ts +17 -0
- package/dist/umd/middlewares/outstandingTransaction.d.ts +4 -0
- package/dist/umd/overrideParseStoresSpec.d.ts +4 -0
- package/dist/umd/performInitialSync.d.ts +4 -0
- package/dist/umd/permissions.d.ts +9 -0
- package/dist/umd/prodLog.d.ts +9 -0
- package/dist/umd/service-worker.d.ts +1 -0
- package/dist/umd/service-worker.js +2078 -322
- package/dist/umd/service-worker.js.map +1 -1
- package/dist/umd/sync/LocalSyncWorker.d.ts +7 -0
- package/dist/umd/sync/SyncRequiredError.d.ts +3 -0
- package/dist/umd/sync/applyServerChanges.d.ts +3 -0
- package/dist/umd/sync/connectWebSocket.d.ts +2 -0
- package/dist/umd/sync/encodeIdsForServer.d.ts +4 -0
- package/dist/umd/sync/extractRealm.d.ts +2 -0
- package/dist/umd/sync/getLatestRevisionsPerTable.d.ts +6 -0
- package/dist/umd/sync/getTablesToSyncify.d.ts +3 -0
- package/dist/umd/sync/isOnline.d.ts +1 -0
- package/dist/umd/sync/isSyncNeeded.d.ts +2 -0
- package/dist/umd/sync/listClientChanges.d.ts +9 -0
- package/dist/umd/sync/listSyncifiedChanges.d.ts +5 -0
- package/dist/umd/sync/messageConsumerIsReady.d.ts +2 -0
- package/dist/umd/sync/messagesFromServerQueue.d.ts +8 -0
- package/dist/umd/sync/modifyLocalObjectsWithNewUserId.d.ts +4 -0
- package/dist/umd/sync/myId.d.ts +1 -0
- package/dist/umd/sync/numUnsyncedMutations.d.ts +2 -0
- package/dist/umd/sync/old_startSyncingClientChanges.d.ts +39 -0
- package/dist/umd/sync/performGuardedJob.d.ts +2 -0
- package/dist/umd/sync/ratelimit.d.ts +3 -0
- package/dist/umd/sync/registerSyncEvent.d.ts +3 -0
- package/dist/umd/sync/sync.d.ts +15 -0
- package/dist/umd/sync/syncIfPossible.d.ts +5 -0
- package/dist/umd/sync/syncWithServer.d.ts +6 -0
- package/dist/umd/sync/triggerSync.d.ts +2 -0
- package/dist/umd/sync/updateBaseRevs.d.ts +5 -0
- package/dist/umd/types/DXCAlert.d.ts +25 -0
- package/dist/umd/types/DXCInputField.d.ts +11 -0
- package/dist/umd/types/DXCUserInteraction.d.ts +93 -0
- package/dist/umd/types/NewIdOptions.d.ts +3 -0
- package/dist/umd/types/SWMessageEvent.d.ts +3 -0
- package/dist/umd/types/SWSyncEvent.d.ts +4 -0
- package/dist/umd/types/SyncState.d.ts +9 -0
- package/dist/umd/types/TXExpandos.d.ts +11 -0
- package/dist/umd/updateSchemaFromOptions.d.ts +3 -0
- package/dist/umd/userIsActive.d.ts +7 -0
- package/dist/umd/verifyConfig.d.ts +2 -0
- package/dist/umd/verifySchema.d.ts +2 -0
- package/package.json +14 -48
- package/LICENSE +0 -202
- package/copydts.sh +0 -5
- package/dist/types/default-ui/LoginDialog.d.ts +0 -6
- package/dist/types/helpers/resolveText.d.ts +0 -2
- package/dist/types/sync/performGuardedJob.d.ts +0 -4
- package/dist/umd/dexie-cloud-addon.min.js +0 -2
- package/dist/umd/dexie-cloud-addon.min.js.map +0 -1
- package/dist/umd/service-worker.min.js +0 -2
- package/dist/umd/service-worker.min.js.map +0 -1
- /package/dist/{types → modern}/DISABLE_SERVICEWORKER_STRATEGY.d.ts +0 -0
- /package/dist/{types → modern}/DXCWebSocketStatus.d.ts +0 -0
- /package/dist/{types → modern}/DexieCloudSyncOptions.d.ts +0 -0
- /package/dist/{types → modern}/DexieCloudTable.d.ts +0 -0
- /package/dist/{types → modern}/Invite.d.ts +0 -0
- /package/dist/{types → modern}/PermissionChecker.d.ts +0 -0
- /package/dist/{types → modern}/WSObservable.d.ts +0 -0
- /package/dist/{types → modern}/associate.d.ts +0 -0
- /package/dist/{types → modern}/authentication/AuthPersistedContext.d.ts +0 -0
- /package/dist/{types → modern}/authentication/TokenExpiredError.d.ts +0 -0
- /package/dist/{types → modern}/authentication/UNAUTHORIZED_USER.d.ts +0 -0
- /package/dist/{types → modern}/authentication/currentUserObservable.d.ts +0 -0
- /package/dist/{types → modern}/authentication/login.d.ts +0 -0
- /package/dist/{types → modern}/authentication/otpFetchTokenCallback.d.ts +0 -0
- /package/dist/{types → modern}/authentication/setCurrentUser.d.ts +0 -0
- /package/dist/{types → modern}/computeSyncState.d.ts +0 -0
- /package/dist/{types → modern}/createSharedValueObservable.d.ts +0 -0
- /package/dist/{types → modern}/db/DexieCloudDB.d.ts +0 -0
- /package/dist/{types → modern}/db/entities/BaseRevisionMapEntry.d.ts +0 -0
- /package/dist/{types → modern}/db/entities/EntityCommon.d.ts +0 -0
- /package/dist/{types → modern}/db/entities/GuardedJob.d.ts +0 -0
- /package/dist/{types → modern}/db/entities/Member.d.ts +0 -0
- /package/dist/{types → modern}/db/entities/PersistedSyncState.d.ts +0 -0
- /package/dist/{types → modern}/db/entities/Realm.d.ts +0 -0
- /package/dist/{types → modern}/db/entities/Role.d.ts +0 -0
- /package/dist/{types → modern}/default-ui/Dialog.d.ts +0 -0
- /package/dist/{types → modern}/default-ui/Styles.d.ts +0 -0
- /package/dist/{types → modern}/default-ui/index.d.ts +0 -0
- /package/dist/{types → modern}/errors/HttpError.d.ts +0 -0
- /package/dist/{types → modern}/extend-dexie-interface.d.ts +0 -0
- /package/dist/{types → modern}/getGlobalRolesObservable.d.ts +0 -0
- /package/dist/{types → modern}/getInternalAccessControlObservable.d.ts +0 -0
- /package/dist/{types → modern}/getInvitesObservable.d.ts +0 -0
- /package/dist/{types → modern}/getPermissionsLookupObservable.d.ts +0 -0
- /package/dist/{types → modern}/getTiedRealmId.d.ts +0 -0
- /package/dist/{types → modern}/helpers/BroadcastedAndLocalEvent.d.ts +0 -0
- /package/dist/{types → modern}/helpers/CancelToken.d.ts +0 -0
- /package/dist/{types → modern}/helpers/IS_SERVICE_WORKER.d.ts +0 -0
- /package/dist/{types → modern}/helpers/SWBroadcastChannel.d.ts +0 -0
- /package/dist/{types → modern}/helpers/allSettled.d.ts +0 -0
- /package/dist/{types → modern}/helpers/bulkUpdate.d.ts +0 -0
- /package/dist/{types → modern}/helpers/computeRealmSetHash.d.ts +0 -0
- /package/dist/{types → modern}/helpers/date-constants.d.ts +0 -0
- /package/dist/{types → modern}/helpers/dbOnClosed.d.ts +0 -0
- /package/dist/{types → modern}/helpers/flatten.d.ts +0 -0
- /package/dist/{types → modern}/helpers/getMutationTable.d.ts +0 -0
- /package/dist/{types → modern}/helpers/getSyncableTables.d.ts +0 -0
- /package/dist/{types → modern}/helpers/getTableFromMutationTable.d.ts +0 -0
- /package/dist/{types → modern}/helpers/makeArray.d.ts +0 -0
- /package/dist/{types → modern}/helpers/randomString.d.ts +0 -0
- /package/dist/{types → modern}/helpers/throwVersionIncrementNeeded.d.ts +0 -0
- /package/dist/{types → modern}/helpers/visibilityState.d.ts +0 -0
- /package/dist/{types → modern}/isFirefox.d.ts +0 -0
- /package/dist/{types → modern}/isSafari.d.ts +0 -0
- /package/dist/{types → modern}/mapValueObservable.d.ts +0 -0
- /package/dist/{types → modern}/mergePermissions.d.ts +0 -0
- /package/dist/{types → modern}/middleware-helpers/guardedTable.d.ts +0 -0
- /package/dist/{types → modern}/middleware-helpers/idGenerationHelpers.d.ts +0 -0
- /package/dist/{types → modern}/middlewares/createIdGenerationMiddleware.d.ts +0 -0
- /package/dist/{types → modern}/middlewares/createImplicitPropSetterMiddleware.d.ts +0 -0
- /package/dist/{types → modern}/middlewares/outstandingTransaction.d.ts +0 -0
- /package/dist/{types → modern}/overrideParseStoresSpec.d.ts +0 -0
- /package/dist/{types → modern}/performInitialSync.d.ts +0 -0
- /package/dist/{types → modern}/permissions.d.ts +0 -0
- /package/dist/{types → modern}/service-worker.d.ts +0 -0
- /package/dist/{types → modern}/sync/LocalSyncWorker.d.ts +0 -0
- /package/dist/{types → modern}/sync/SyncRequiredError.d.ts +0 -0
- /package/dist/{types → modern}/sync/applyServerChanges.d.ts +0 -0
- /package/dist/{types → modern}/sync/connectWebSocket.d.ts +0 -0
- /package/dist/{types → modern}/sync/encodeIdsForServer.d.ts +0 -0
- /package/dist/{types → modern}/sync/extractRealm.d.ts +0 -0
- /package/dist/{types → modern}/sync/getLatestRevisionsPerTable.d.ts +0 -0
- /package/dist/{types → modern}/sync/getTablesToSyncify.d.ts +0 -0
- /package/dist/{types → modern}/sync/isOnline.d.ts +0 -0
- /package/dist/{types → modern}/sync/isSyncNeeded.d.ts +0 -0
- /package/dist/{types → modern}/sync/listClientChanges.d.ts +0 -0
- /package/dist/{types → modern}/sync/listSyncifiedChanges.d.ts +0 -0
- /package/dist/{types → modern}/sync/messageConsumerIsReady.d.ts +0 -0
- /package/dist/{types → modern}/sync/messagesFromServerQueue.d.ts +0 -0
- /package/dist/{types → modern}/sync/modifyLocalObjectsWithNewUserId.d.ts +0 -0
- /package/dist/{types → modern}/sync/myId.d.ts +0 -0
- /package/dist/{types → modern}/sync/numUnsyncedMutations.d.ts +0 -0
- /package/dist/{types → modern}/sync/old_startSyncingClientChanges.d.ts +0 -0
- /package/dist/{types → modern}/sync/registerSyncEvent.d.ts +0 -0
- /package/dist/{types → modern}/sync/syncIfPossible.d.ts +0 -0
- /package/dist/{types → modern}/sync/syncWithServer.d.ts +0 -0
- /package/dist/{types → modern}/sync/triggerSync.d.ts +0 -0
- /package/dist/{types → modern}/sync/updateBaseRevs.d.ts +0 -0
- /package/dist/{types → modern}/types/DXCInputField.d.ts +0 -0
- /package/dist/{types → modern}/types/NewIdOptions.d.ts +0 -0
- /package/dist/{types → modern}/types/SWMessageEvent.d.ts +0 -0
- /package/dist/{types → modern}/types/SWSyncEvent.d.ts +0 -0
- /package/dist/{types → modern}/types/TXExpandos.d.ts +0 -0
- /package/dist/{types → modern}/updateSchemaFromOptions.d.ts +0 -0
- /package/dist/{types → modern}/userIsActive.d.ts +0 -0
- /package/dist/{types → modern}/verifyConfig.d.ts +0 -0
- /package/dist/{types → modern}/verifySchema.d.ts +0 -0
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* ==========================================================================
|
|
10
10
|
*
|
|
11
|
-
* Version 4.0.1-beta.
|
|
11
|
+
* Version 4.0.1-beta.48, Tue Oct 17 2023
|
|
12
12
|
*
|
|
13
13
|
* https://dexie.org
|
|
14
14
|
*
|
|
@@ -22,10 +22,6 @@
|
|
|
22
22
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.DexieCloud = {}, global.Dexie, global.rxjs));
|
|
23
23
|
})(this, (function (exports, Dexie, rxjs) { 'use strict';
|
|
24
24
|
|
|
25
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
26
|
-
|
|
27
|
-
var Dexie__default = /*#__PURE__*/_interopDefaultLegacy(Dexie);
|
|
28
|
-
|
|
29
25
|
/******************************************************************************
|
|
30
26
|
Copyright (c) Microsoft Corporation.
|
|
31
27
|
|
|
@@ -687,11 +683,7 @@
|
|
|
687
683
|
|
|
688
684
|
function reportUnhandledError(err) {
|
|
689
685
|
timeoutProvider.setTimeout(function () {
|
|
690
|
-
|
|
691
|
-
if (onUnhandledError) {
|
|
692
|
-
onUnhandledError(err);
|
|
693
|
-
}
|
|
694
|
-
else {
|
|
686
|
+
{
|
|
695
687
|
throw err;
|
|
696
688
|
}
|
|
697
689
|
});
|
|
@@ -699,38 +691,8 @@
|
|
|
699
691
|
|
|
700
692
|
function noop() { }
|
|
701
693
|
|
|
702
|
-
var COMPLETE_NOTIFICATION = (function () { return createNotification('C', undefined, undefined); })();
|
|
703
|
-
function errorNotification(error) {
|
|
704
|
-
return createNotification('E', undefined, error);
|
|
705
|
-
}
|
|
706
|
-
function nextNotification(value) {
|
|
707
|
-
return createNotification('N', value, undefined);
|
|
708
|
-
}
|
|
709
|
-
function createNotification(kind, value, error) {
|
|
710
|
-
return {
|
|
711
|
-
kind: kind,
|
|
712
|
-
value: value,
|
|
713
|
-
error: error,
|
|
714
|
-
};
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
var context = null;
|
|
718
694
|
function errorContext(cb) {
|
|
719
|
-
|
|
720
|
-
var isRoot = !context;
|
|
721
|
-
if (isRoot) {
|
|
722
|
-
context = { errorThrown: false, error: null };
|
|
723
|
-
}
|
|
724
|
-
cb();
|
|
725
|
-
if (isRoot) {
|
|
726
|
-
var _a = context, errorThrown = _a.errorThrown, error = _a.error;
|
|
727
|
-
context = null;
|
|
728
|
-
if (errorThrown) {
|
|
729
|
-
throw error;
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
else {
|
|
695
|
+
{
|
|
734
696
|
cb();
|
|
735
697
|
}
|
|
736
698
|
}
|
|
@@ -755,26 +717,20 @@
|
|
|
755
717
|
return new SafeSubscriber(next, error, complete);
|
|
756
718
|
};
|
|
757
719
|
Subscriber.prototype.next = function (value) {
|
|
758
|
-
if (this.isStopped)
|
|
759
|
-
handleStoppedNotification(nextNotification(value), this);
|
|
760
|
-
}
|
|
720
|
+
if (this.isStopped) ;
|
|
761
721
|
else {
|
|
762
722
|
this._next(value);
|
|
763
723
|
}
|
|
764
724
|
};
|
|
765
725
|
Subscriber.prototype.error = function (err) {
|
|
766
|
-
if (this.isStopped)
|
|
767
|
-
handleStoppedNotification(errorNotification(err), this);
|
|
768
|
-
}
|
|
726
|
+
if (this.isStopped) ;
|
|
769
727
|
else {
|
|
770
728
|
this.isStopped = true;
|
|
771
729
|
this._error(err);
|
|
772
730
|
}
|
|
773
731
|
};
|
|
774
732
|
Subscriber.prototype.complete = function () {
|
|
775
|
-
if (this.isStopped)
|
|
776
|
-
handleStoppedNotification(COMPLETE_NOTIFICATION, this);
|
|
777
|
-
}
|
|
733
|
+
if (this.isStopped) ;
|
|
778
734
|
else {
|
|
779
735
|
this.isStopped = true;
|
|
780
736
|
this._complete();
|
|
@@ -894,10 +850,6 @@
|
|
|
894
850
|
function defaultErrorHandler(err) {
|
|
895
851
|
throw err;
|
|
896
852
|
}
|
|
897
|
-
function handleStoppedNotification(notification, subscriber) {
|
|
898
|
-
var onStoppedNotification = config.onStoppedNotification;
|
|
899
|
-
onStoppedNotification && timeoutProvider.setTimeout(function () { return onStoppedNotification(notification, subscriber); });
|
|
900
|
-
}
|
|
901
853
|
var EMPTY_OBSERVER = {
|
|
902
854
|
closed: true,
|
|
903
855
|
next: noop,
|
|
@@ -1924,58 +1876,6 @@
|
|
|
1924
1876
|
identity;
|
|
1925
1877
|
}
|
|
1926
1878
|
|
|
1927
|
-
var TimeoutError = createErrorClass(function (_super) {
|
|
1928
|
-
return function TimeoutErrorImpl(info) {
|
|
1929
|
-
if (info === void 0) { info = null; }
|
|
1930
|
-
_super(this);
|
|
1931
|
-
this.message = 'Timeout has occurred';
|
|
1932
|
-
this.name = 'TimeoutError';
|
|
1933
|
-
this.info = info;
|
|
1934
|
-
};
|
|
1935
|
-
});
|
|
1936
|
-
function timeout(config, schedulerArg) {
|
|
1937
|
-
var _a = (isValidDate(config) ? { first: config } : typeof config === 'number' ? { each: config } : config), first = _a.first, each = _a.each, _b = _a.with, _with = _b === void 0 ? timeoutErrorFactory : _b, _c = _a.scheduler, scheduler = _c === void 0 ? schedulerArg !== null && schedulerArg !== void 0 ? schedulerArg : asyncScheduler : _c, _d = _a.meta, meta = _d === void 0 ? null : _d;
|
|
1938
|
-
if (first == null && each == null) {
|
|
1939
|
-
throw new TypeError('No timeout provided.');
|
|
1940
|
-
}
|
|
1941
|
-
return operate(function (source, subscriber) {
|
|
1942
|
-
var originalSourceSubscription;
|
|
1943
|
-
var timerSubscription;
|
|
1944
|
-
var lastValue = null;
|
|
1945
|
-
var seen = 0;
|
|
1946
|
-
var startTimer = function (delay) {
|
|
1947
|
-
timerSubscription = executeSchedule(subscriber, scheduler, function () {
|
|
1948
|
-
try {
|
|
1949
|
-
originalSourceSubscription.unsubscribe();
|
|
1950
|
-
innerFrom(_with({
|
|
1951
|
-
meta: meta,
|
|
1952
|
-
lastValue: lastValue,
|
|
1953
|
-
seen: seen,
|
|
1954
|
-
})).subscribe(subscriber);
|
|
1955
|
-
}
|
|
1956
|
-
catch (err) {
|
|
1957
|
-
subscriber.error(err);
|
|
1958
|
-
}
|
|
1959
|
-
}, delay);
|
|
1960
|
-
};
|
|
1961
|
-
originalSourceSubscription = source.subscribe(createOperatorSubscriber(subscriber, function (value) {
|
|
1962
|
-
timerSubscription === null || timerSubscription === void 0 ? void 0 : timerSubscription.unsubscribe();
|
|
1963
|
-
seen++;
|
|
1964
|
-
subscriber.next((lastValue = value));
|
|
1965
|
-
each > 0 && startTimer(each);
|
|
1966
|
-
}, undefined, undefined, function () {
|
|
1967
|
-
if (!(timerSubscription === null || timerSubscription === void 0 ? void 0 : timerSubscription.closed)) {
|
|
1968
|
-
timerSubscription === null || timerSubscription === void 0 ? void 0 : timerSubscription.unsubscribe();
|
|
1969
|
-
}
|
|
1970
|
-
lastValue = null;
|
|
1971
|
-
}));
|
|
1972
|
-
!seen && startTimer(first != null ? (typeof first === 'number' ? first : +first - scheduler.now()) : each);
|
|
1973
|
-
});
|
|
1974
|
-
}
|
|
1975
|
-
function timeoutErrorFactory(info) {
|
|
1976
|
-
throw new TimeoutError(info);
|
|
1977
|
-
}
|
|
1978
|
-
|
|
1979
1879
|
//const hasSW = 'serviceWorker' in navigator;
|
|
1980
1880
|
let hasComplainedAboutSyncEvent = false;
|
|
1981
1881
|
function registerSyncEvent(db, purpose) {
|
|
@@ -2036,6 +1936,7 @@
|
|
|
2036
1936
|
|
|
2037
1937
|
function triggerSync(db, purpose) {
|
|
2038
1938
|
if (db.cloud.usingServiceWorker) {
|
|
1939
|
+
console.debug('registering sync event');
|
|
2039
1940
|
registerSyncEvent(db, purpose);
|
|
2040
1941
|
}
|
|
2041
1942
|
else {
|
|
@@ -2064,17 +1965,34 @@
|
|
|
2064
1965
|
}
|
|
2065
1966
|
}
|
|
2066
1967
|
: (b) => {
|
|
2067
|
-
|
|
1968
|
+
const u8a = ArrayBuffer.isView(b) ? b : new Uint8Array(b);
|
|
1969
|
+
const CHUNK_SIZE = 0x1000;
|
|
1970
|
+
const strs = [];
|
|
1971
|
+
for (let i = 0, l = u8a.length; i < l; i += CHUNK_SIZE) {
|
|
1972
|
+
const chunk = u8a.subarray(i, i + CHUNK_SIZE);
|
|
1973
|
+
strs.push(String.fromCharCode.apply(null, chunk));
|
|
1974
|
+
}
|
|
1975
|
+
return btoa(strs.join(""));
|
|
2068
1976
|
};
|
|
2069
1977
|
|
|
1978
|
+
class TokenErrorResponseError extends Error {
|
|
1979
|
+
constructor({ title, message, messageCode, messageParams, }) {
|
|
1980
|
+
super(message);
|
|
1981
|
+
this.name = 'TokenErrorResponseError';
|
|
1982
|
+
this.title = title;
|
|
1983
|
+
this.messageCode = messageCode;
|
|
1984
|
+
this.messageParams = messageParams;
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
|
|
2070
1988
|
function interactWithUser(userInteraction, req) {
|
|
2071
1989
|
return new Promise((resolve, reject) => {
|
|
2072
|
-
const interactionProps = Object.assign(Object.assign({}, req), { onSubmit: (res) => {
|
|
1990
|
+
const interactionProps = Object.assign(Object.assign({ submitLabel: 'Submit', cancelLabel: 'Cancel' }, req), { onSubmit: (res) => {
|
|
2073
1991
|
userInteraction.next(undefined);
|
|
2074
1992
|
resolve(res);
|
|
2075
1993
|
}, onCancel: () => {
|
|
2076
1994
|
userInteraction.next(undefined);
|
|
2077
|
-
reject(new
|
|
1995
|
+
reject(new Dexie.AbortError('User cancelled'));
|
|
2078
1996
|
} });
|
|
2079
1997
|
userInteraction.next(interactionProps);
|
|
2080
1998
|
// Start subscribing for external updates to db.cloud.userInteraction, and if so, cancel this request.
|
|
@@ -2093,7 +2011,9 @@
|
|
|
2093
2011
|
type: 'message-alert',
|
|
2094
2012
|
title,
|
|
2095
2013
|
alerts,
|
|
2096
|
-
fields: {}
|
|
2014
|
+
fields: {},
|
|
2015
|
+
submitLabel: 'OK',
|
|
2016
|
+
cancelLabel: null,
|
|
2097
2017
|
});
|
|
2098
2018
|
}
|
|
2099
2019
|
function promptForEmail(userInteraction, title, emailHint) {
|
|
@@ -2152,22 +2072,48 @@
|
|
|
2152
2072
|
return otp;
|
|
2153
2073
|
});
|
|
2154
2074
|
}
|
|
2075
|
+
function confirmLogout(userInteraction, currentUserId, numUnsyncedChanges) {
|
|
2076
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2077
|
+
const alerts = [
|
|
2078
|
+
{
|
|
2079
|
+
type: 'warning',
|
|
2080
|
+
messageCode: 'LOGOUT_CONFIRMATION',
|
|
2081
|
+
message: `{numUnsyncedChanges} unsynced changes will get lost!
|
|
2082
|
+
Logout anyway?`,
|
|
2083
|
+
messageParams: {
|
|
2084
|
+
currentUserId,
|
|
2085
|
+
numUnsyncedChanges: numUnsyncedChanges.toString(),
|
|
2086
|
+
}
|
|
2087
|
+
},
|
|
2088
|
+
];
|
|
2089
|
+
return yield interactWithUser(userInteraction, {
|
|
2090
|
+
type: 'logout-confirmation',
|
|
2091
|
+
title: 'Confirm Logout',
|
|
2092
|
+
alerts,
|
|
2093
|
+
fields: {},
|
|
2094
|
+
submitLabel: 'Confirm logout',
|
|
2095
|
+
cancelLabel: 'Cancel'
|
|
2096
|
+
})
|
|
2097
|
+
.then(() => true)
|
|
2098
|
+
.catch(() => false);
|
|
2099
|
+
});
|
|
2100
|
+
}
|
|
2155
2101
|
|
|
2156
2102
|
function loadAccessToken(db) {
|
|
2157
|
-
var _a, _b;
|
|
2103
|
+
var _a, _b, _c;
|
|
2158
2104
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2159
2105
|
const currentUser = yield db.getCurrentUser();
|
|
2160
2106
|
const { accessToken, accessTokenExpiration, refreshToken, refreshTokenExpiration, claims, } = currentUser;
|
|
2161
2107
|
if (!accessToken)
|
|
2162
|
-
return;
|
|
2108
|
+
return null;
|
|
2163
2109
|
const expTime = (_a = accessTokenExpiration === null || accessTokenExpiration === void 0 ? void 0 : accessTokenExpiration.getTime()) !== null && _a !== void 0 ? _a : Infinity;
|
|
2164
|
-
if (expTime > Date.now()) {
|
|
2165
|
-
return
|
|
2110
|
+
if (expTime > Date.now() && (((_b = currentUser.license) === null || _b === void 0 ? void 0 : _b.status) || 'ok') === 'ok') {
|
|
2111
|
+
return currentUser;
|
|
2166
2112
|
}
|
|
2167
2113
|
if (!refreshToken) {
|
|
2168
2114
|
throw new Error(`Refresh token missing`);
|
|
2169
2115
|
}
|
|
2170
|
-
const refreshExpTime = (
|
|
2116
|
+
const refreshExpTime = (_c = refreshTokenExpiration === null || refreshTokenExpiration === void 0 ? void 0 : refreshTokenExpiration.getTime()) !== null && _c !== void 0 ? _c : Infinity;
|
|
2171
2117
|
if (refreshExpTime <= Date.now()) {
|
|
2172
2118
|
throw new Error(`Refresh token has expired`);
|
|
2173
2119
|
}
|
|
@@ -2175,8 +2121,10 @@
|
|
|
2175
2121
|
yield db.table('$logins').update(claims.sub, {
|
|
2176
2122
|
accessToken: refreshedLogin.accessToken,
|
|
2177
2123
|
accessTokenExpiration: refreshedLogin.accessTokenExpiration,
|
|
2124
|
+
claims: refreshedLogin.claims,
|
|
2125
|
+
license: refreshedLogin.license,
|
|
2178
2126
|
});
|
|
2179
|
-
return refreshedLogin
|
|
2127
|
+
return refreshedLogin;
|
|
2180
2128
|
});
|
|
2181
2129
|
}
|
|
2182
2130
|
function authenticate(url, context, fetchToken, userInteraction, hints) {
|
|
@@ -2224,10 +2172,24 @@
|
|
|
2224
2172
|
if (res.status !== 200)
|
|
2225
2173
|
throw new Error(`RefreshToken: Status ${res.status} from ${url}/token`);
|
|
2226
2174
|
const response = yield res.json();
|
|
2175
|
+
if (response.type === 'error') {
|
|
2176
|
+
throw new TokenErrorResponseError(response);
|
|
2177
|
+
}
|
|
2227
2178
|
login.accessToken = response.accessToken;
|
|
2228
2179
|
login.accessTokenExpiration = response.accessTokenExpiration
|
|
2229
2180
|
? new Date(response.accessTokenExpiration)
|
|
2230
2181
|
: undefined;
|
|
2182
|
+
login.claims = response.claims;
|
|
2183
|
+
login.license = {
|
|
2184
|
+
type: response.userType,
|
|
2185
|
+
status: response.claims.license || 'ok',
|
|
2186
|
+
};
|
|
2187
|
+
if (response.evalDaysLeft != null) {
|
|
2188
|
+
login.license.evalDaysLeft = response.evalDaysLeft;
|
|
2189
|
+
}
|
|
2190
|
+
if (response.userValidUntil != null) {
|
|
2191
|
+
login.license.validUntil = new Date(response.userValidUntil);
|
|
2192
|
+
}
|
|
2231
2193
|
return login;
|
|
2232
2194
|
});
|
|
2233
2195
|
}
|
|
@@ -2259,8 +2221,15 @@
|
|
|
2259
2221
|
public_key: publicKeyPEM,
|
|
2260
2222
|
hints,
|
|
2261
2223
|
});
|
|
2224
|
+
if (response2.type === 'error') {
|
|
2225
|
+
throw new TokenErrorResponseError(response2);
|
|
2226
|
+
}
|
|
2262
2227
|
if (response2.type !== 'tokens')
|
|
2263
2228
|
throw new Error(`Unexpected response type from token endpoint: ${response2.type}`);
|
|
2229
|
+
/*const licenseStatus = response2.claims.license || 'ok';
|
|
2230
|
+
if (licenseStatus !== 'ok') {
|
|
2231
|
+
throw new InvalidLicenseError(licenseStatus);
|
|
2232
|
+
}*/
|
|
2264
2233
|
context.accessToken = response2.accessToken;
|
|
2265
2234
|
context.accessTokenExpiration = new Date(response2.accessTokenExpiration);
|
|
2266
2235
|
context.refreshToken = response2.refreshToken;
|
|
@@ -2271,6 +2240,16 @@
|
|
|
2271
2240
|
context.email = response2.claims.email;
|
|
2272
2241
|
context.name = response2.claims.name;
|
|
2273
2242
|
context.claims = response2.claims;
|
|
2243
|
+
context.license = {
|
|
2244
|
+
type: response2.userType,
|
|
2245
|
+
status: response2.claims.license || 'ok',
|
|
2246
|
+
};
|
|
2247
|
+
if (response2.evalDaysLeft != null) {
|
|
2248
|
+
context.license.evalDaysLeft = response2.evalDaysLeft;
|
|
2249
|
+
}
|
|
2250
|
+
if (response2.userValidUntil != null) {
|
|
2251
|
+
context.license.validUntil = new Date(response2.userValidUntil);
|
|
2252
|
+
}
|
|
2274
2253
|
if (response2.alerts && response2.alerts.length > 0) {
|
|
2275
2254
|
yield interactWithUser(userInteraction, {
|
|
2276
2255
|
type: 'message-alert',
|
|
@@ -2282,12 +2261,36 @@
|
|
|
2282
2261
|
return context;
|
|
2283
2262
|
}
|
|
2284
2263
|
catch (error) {
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2264
|
+
if (error instanceof TokenErrorResponseError) {
|
|
2265
|
+
yield alertUser(userInteraction, error.title, {
|
|
2266
|
+
type: 'error',
|
|
2267
|
+
messageCode: error.messageCode,
|
|
2268
|
+
message: error.message,
|
|
2269
|
+
messageParams: {},
|
|
2270
|
+
});
|
|
2271
|
+
throw error;
|
|
2272
|
+
}
|
|
2273
|
+
let message = `We're having a problem authenticating right now.`;
|
|
2274
|
+
console.error(`Error authenticating`, error);
|
|
2275
|
+
if (error instanceof TypeError) {
|
|
2276
|
+
const isOffline = typeof navigator !== undefined && !navigator.onLine;
|
|
2277
|
+
if (isOffline) {
|
|
2278
|
+
message = `You seem to be offline. Please connect to the internet and try again.`;
|
|
2279
|
+
}
|
|
2280
|
+
else if (Dexie.debug || (typeof location !== 'undefined' && (location.hostname === 'localhost' || location.hostname === '127.0.0.1'))) {
|
|
2281
|
+
// The audience is most likely the developer. Suggest to whitelist the localhost origin:
|
|
2282
|
+
message = `Could not connect to server. Please verify that your origin '${location.origin}' is whitelisted using \`npx dexie-cloud whitelist\``;
|
|
2283
|
+
}
|
|
2284
|
+
else {
|
|
2285
|
+
message = `Could not connect to server. Please verify the connection.`;
|
|
2286
|
+
}
|
|
2287
|
+
yield alertUser(userInteraction, 'Authentication Failed', {
|
|
2288
|
+
type: 'error',
|
|
2289
|
+
messageCode: 'GENERIC_ERROR',
|
|
2290
|
+
message,
|
|
2291
|
+
messageParams: {},
|
|
2292
|
+
}).catch(() => { });
|
|
2293
|
+
}
|
|
2291
2294
|
throw error;
|
|
2292
2295
|
}
|
|
2293
2296
|
});
|
|
@@ -2334,6 +2337,75 @@
|
|
|
2334
2337
|
}
|
|
2335
2338
|
}
|
|
2336
2339
|
|
|
2340
|
+
const UNAUTHORIZED_USER = {
|
|
2341
|
+
userId: "unauthorized",
|
|
2342
|
+
name: "Unauthorized",
|
|
2343
|
+
claims: {
|
|
2344
|
+
sub: "unauthorized",
|
|
2345
|
+
},
|
|
2346
|
+
lastLogin: new Date(0)
|
|
2347
|
+
};
|
|
2348
|
+
try {
|
|
2349
|
+
Object.freeze(UNAUTHORIZED_USER);
|
|
2350
|
+
Object.freeze(UNAUTHORIZED_USER.claims);
|
|
2351
|
+
}
|
|
2352
|
+
catch (_a) { }
|
|
2353
|
+
|
|
2354
|
+
function waitUntil(o, // Works with Dexie's liveQuery observables if we'd need that
|
|
2355
|
+
predicate) {
|
|
2356
|
+
return rxjs.firstValueFrom(rxjs.from(o).pipe(rxjs.filter(predicate)));
|
|
2357
|
+
}
|
|
2358
|
+
|
|
2359
|
+
function logout(db) {
|
|
2360
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2361
|
+
const numUnsyncedChanges = yield _logout(db);
|
|
2362
|
+
if (numUnsyncedChanges) {
|
|
2363
|
+
if (yield confirmLogout(db.cloud.userInteraction, db.cloud.currentUserId, numUnsyncedChanges)) {
|
|
2364
|
+
yield _logout(db, { deleteUnsyncedData: true });
|
|
2365
|
+
}
|
|
2366
|
+
else {
|
|
2367
|
+
throw new Error(`User cancelled logout due to unsynced changes`);
|
|
2368
|
+
}
|
|
2369
|
+
}
|
|
2370
|
+
});
|
|
2371
|
+
}
|
|
2372
|
+
function _logout(db, { deleteUnsyncedData = false } = {}) {
|
|
2373
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2374
|
+
// Clear the database without emptying configuration options.
|
|
2375
|
+
const [numUnsynced, loggedOut] = yield db.dx.transaction('rw', db.dx.tables, (tx) => __awaiter(this, void 0, void 0, function* () {
|
|
2376
|
+
// @ts-ignore
|
|
2377
|
+
const idbtrans = tx.idbtrans;
|
|
2378
|
+
idbtrans.disableChangeTracking = true;
|
|
2379
|
+
idbtrans.disableAccessControl = true;
|
|
2380
|
+
const mutationTables = tx.storeNames.filter((tableName) => tableName.endsWith('_mutations'));
|
|
2381
|
+
// Count unsynced changes
|
|
2382
|
+
const unsyncCounts = yield Promise.all(mutationTables.map((mutationTable) => tx.table(mutationTable).count()));
|
|
2383
|
+
const sumUnSynced = unsyncCounts.reduce((a, b) => a + b, 0);
|
|
2384
|
+
if (sumUnSynced > 0 && !deleteUnsyncedData) {
|
|
2385
|
+
// Let caller ask user if they want to delete unsynced data.
|
|
2386
|
+
return [sumUnSynced, false];
|
|
2387
|
+
}
|
|
2388
|
+
// Either there are no unsynched changes, or caller provided flag deleteUnsynchedData = true.
|
|
2389
|
+
// Clear all tables except $jobs and $syncState (except the persisted sync state which is
|
|
2390
|
+
// also cleared because we're going to rebuild it using a fresh sync).
|
|
2391
|
+
db.$syncState.delete('syncState');
|
|
2392
|
+
for (const table of db.dx.tables) {
|
|
2393
|
+
if (table.name !== '$jobs' && table.name !== '$syncState') {
|
|
2394
|
+
table.clear();
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
return [sumUnSynced, true];
|
|
2398
|
+
}));
|
|
2399
|
+
if (loggedOut) {
|
|
2400
|
+
// Wait for currentUser observable to emit UNAUTHORIZED_USER
|
|
2401
|
+
yield waitUntil(db.cloud.currentUser, (user) => user.userId === UNAUTHORIZED_USER.userId);
|
|
2402
|
+
// Then perform an initial sync
|
|
2403
|
+
yield db.cloud.sync({ purpose: 'pull', wait: true });
|
|
2404
|
+
}
|
|
2405
|
+
return numUnsynced;
|
|
2406
|
+
});
|
|
2407
|
+
}
|
|
2408
|
+
|
|
2337
2409
|
class HttpError extends Error {
|
|
2338
2410
|
constructor(res, message) {
|
|
2339
2411
|
super(message || `${res.status} ${res.statusText}`);
|
|
@@ -2387,8 +2459,9 @@
|
|
|
2387
2459
|
throw new HttpError(res1, errMsg);
|
|
2388
2460
|
}
|
|
2389
2461
|
const response = yield res1.json();
|
|
2390
|
-
if (response.type === 'tokens') {
|
|
2462
|
+
if (response.type === 'tokens' || response.type === 'error') {
|
|
2391
2463
|
// Demo user request can get a "tokens" response right away
|
|
2464
|
+
// Error can also be returned right away.
|
|
2392
2465
|
return response;
|
|
2393
2466
|
}
|
|
2394
2467
|
else if (tokenRequest.grant_type === 'otp') {
|
|
@@ -2420,12 +2493,6 @@
|
|
|
2420
2493
|
}
|
|
2421
2494
|
if (res2.status !== 200) {
|
|
2422
2495
|
const errMsg = yield res2.text();
|
|
2423
|
-
yield alertUser(userInteraction, "OTP Authentication Failed", {
|
|
2424
|
-
type: 'error',
|
|
2425
|
-
messageCode: 'GENERIC_ERROR',
|
|
2426
|
-
message: errMsg,
|
|
2427
|
-
messageParams: {}
|
|
2428
|
-
}).catch(() => { });
|
|
2429
2496
|
throw new HttpError(res2, errMsg);
|
|
2430
2497
|
}
|
|
2431
2498
|
const response2 = yield res2.json();
|
|
@@ -2438,6 +2505,18 @@
|
|
|
2438
2505
|
};
|
|
2439
2506
|
}
|
|
2440
2507
|
|
|
2508
|
+
/** A way to log to console in production without terser stripping out
|
|
2509
|
+
* it from the release bundle.
|
|
2510
|
+
* This should be used very rarely and only in places where it's
|
|
2511
|
+
* absolutely necessary to log something in production.
|
|
2512
|
+
*
|
|
2513
|
+
* @param level
|
|
2514
|
+
* @param args
|
|
2515
|
+
*/
|
|
2516
|
+
function prodLog(level, ...args) {
|
|
2517
|
+
globalThis["con" + "sole"][level](...args);
|
|
2518
|
+
}
|
|
2519
|
+
|
|
2441
2520
|
/** This function changes or sets the current user as requested.
|
|
2442
2521
|
*
|
|
2443
2522
|
* Use cases:
|
|
@@ -2464,102 +2543,76 @@
|
|
|
2464
2543
|
}));
|
|
2465
2544
|
user.isLoggedIn = true;
|
|
2466
2545
|
user.lastLogin = new Date();
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
}));
|
|
2470
|
-
yield new Promise((resolve) => {
|
|
2471
|
-
if (db.cloud.currentUserId === user.userId) {
|
|
2472
|
-
resolve(null);
|
|
2546
|
+
try {
|
|
2547
|
+
yield user.save();
|
|
2473
2548
|
}
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
if (
|
|
2477
|
-
|
|
2478
|
-
|
|
2549
|
+
catch (e) {
|
|
2550
|
+
try {
|
|
2551
|
+
if (e.name === 'DataCloneError') {
|
|
2552
|
+
// We've seen this buggy behavior in some browsers and in case it happens
|
|
2553
|
+
// again we really need to collect the details to understand what's going on.
|
|
2554
|
+
prodLog('debug', `Login context property names:`, Object.keys(user));
|
|
2555
|
+
prodLog('debug', `Login context property names:`, Object.keys(user));
|
|
2556
|
+
prodLog('debug', `Login context:`, user);
|
|
2557
|
+
prodLog('debug', `Login context JSON:`, JSON.stringify(user));
|
|
2479
2558
|
}
|
|
2480
|
-
}
|
|
2559
|
+
}
|
|
2560
|
+
catch (_a) { }
|
|
2561
|
+
throw e;
|
|
2481
2562
|
}
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
// V: Samma med andra windows.
|
|
2486
|
-
// V: Så kanske göra om den till att häröra från liveQuery som läser $logins.orderBy('lastLogin').last().
|
|
2487
|
-
// V: Då bara vara medveten om:
|
|
2488
|
-
// V: En sån observable börjar hämta data vid första subscribe
|
|
2489
|
-
// V: Vi har inget "inital value" men kan emulera det till att vara ANONYMOUS_USER
|
|
2490
|
-
// V: Om requireAuth är true, så borde db.on(ready) hålla databasen stängd för alla utom denna observable.
|
|
2491
|
-
// V: Om inte så behöver den inte blocka.
|
|
2492
|
-
// Andra tankar:
|
|
2493
|
-
// * Man kan inte byta användare när man är offline. Skulle gå att flytta realms till undanstuff-tabell vid user-change.
|
|
2494
|
-
// men troligen inte värt det.
|
|
2495
|
-
// * Istället: sälj inte inte switch-user funktionalitet utan tala enbart om inloggat vs icke inloggat läge.
|
|
2496
|
-
// * populate $logins med ANONYMOUS så att en påbörjad inloggning inte räknas, alternativt ha en boolean prop!
|
|
2497
|
-
// Kanske bäst ha en boolean prop!
|
|
2498
|
-
// * Alternativ switch-user funktionalitet:
|
|
2499
|
-
// * DBCore gömmer data från realms man inte har tillgång till.
|
|
2500
|
-
// * Cursor impl behövs också då.
|
|
2501
|
-
// * Då blir det snabba user switch.
|
|
2502
|
-
// * claims-settet som skickas till servern blir summan av alla claims. Då måste servern stödja multipla tokens eller
|
|
2503
|
-
// att ens token är ett samlad.
|
|
2563
|
+
console.debug('Saved new user', user.email);
|
|
2564
|
+
}));
|
|
2565
|
+
yield waitUntil(db.cloud.currentUser, (currentUser) => currentUser.userId === user.userId);
|
|
2504
2566
|
});
|
|
2505
2567
|
}
|
|
2506
2568
|
|
|
2507
2569
|
function login(db, hints) {
|
|
2570
|
+
var _a;
|
|
2508
2571
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2509
2572
|
const currentUser = yield db.getCurrentUser();
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
throw new Error(`Must logout before changing user`);
|
|
2517
|
-
}
|
|
2573
|
+
const origUserId = currentUser.userId;
|
|
2574
|
+
if (currentUser.isLoggedIn && (!hints || (!hints.email && !hints.userId))) {
|
|
2575
|
+
const licenseStatus = ((_a = currentUser.license) === null || _a === void 0 ? void 0 : _a.status) || 'ok';
|
|
2576
|
+
if (licenseStatus === 'ok' && currentUser.accessToken && (!currentUser.accessTokenExpiration || currentUser.accessTokenExpiration.getTime() > Date.now())) {
|
|
2577
|
+
// Already authenticated according to given hints. And license is valid.
|
|
2578
|
+
return false;
|
|
2518
2579
|
}
|
|
2519
|
-
|
|
2520
|
-
|
|
2580
|
+
if (currentUser.refreshToken && (!currentUser.refreshTokenExpiration || currentUser.refreshTokenExpiration.getTime() > Date.now())) {
|
|
2581
|
+
// Refresh the token
|
|
2582
|
+
yield loadAccessToken(db);
|
|
2583
|
+
return false;
|
|
2584
|
+
}
|
|
2585
|
+
// No refresh token - must re-authenticate:
|
|
2521
2586
|
}
|
|
2522
2587
|
const context = new AuthPersistedContext(db, {
|
|
2523
2588
|
claims: {},
|
|
2524
2589
|
lastLogin: new Date(0),
|
|
2525
2590
|
});
|
|
2526
2591
|
yield authenticate(db.cloud.options.databaseUrl, context, db.cloud.options.fetchTokens || otpFetchTokenCallback(db), db.cloud.userInteraction, hints);
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2592
|
+
if (origUserId !== UNAUTHORIZED_USER.userId && context.userId !== origUserId) {
|
|
2593
|
+
// User was logged in before, but now logged in as another user.
|
|
2594
|
+
yield logout(db);
|
|
2595
|
+
}
|
|
2596
|
+
/*try {
|
|
2597
|
+
await context.save();
|
|
2598
|
+
} catch (e) {
|
|
2599
|
+
try {
|
|
2600
|
+
if (e.name === 'DataCloneError') {
|
|
2601
|
+
console.debug(`Login context property names:`, Object.keys(context));
|
|
2602
|
+
console.debug(`Login context:`, context);
|
|
2603
|
+
console.debug(`Login context JSON:`, JSON.stringify(context));
|
|
2604
|
+
}
|
|
2605
|
+
} catch {}
|
|
2606
|
+
throw e;
|
|
2607
|
+
}*/
|
|
2541
2608
|
yield setCurrentUser(db, context);
|
|
2542
2609
|
// Make sure to resync as the new login will be authorized
|
|
2543
2610
|
// for new realms.
|
|
2544
2611
|
triggerSync(db, "pull");
|
|
2545
|
-
return
|
|
2612
|
+
return context.userId !== origUserId;
|
|
2546
2613
|
});
|
|
2547
2614
|
}
|
|
2548
2615
|
|
|
2549
|
-
const UNAUTHORIZED_USER = {
|
|
2550
|
-
userId: "unauthorized",
|
|
2551
|
-
name: "Unauthorized",
|
|
2552
|
-
claims: {
|
|
2553
|
-
sub: "unauthorized",
|
|
2554
|
-
},
|
|
2555
|
-
lastLogin: new Date(0)
|
|
2556
|
-
};
|
|
2557
|
-
try {
|
|
2558
|
-
Object.freeze(UNAUTHORIZED_USER);
|
|
2559
|
-
Object.freeze(UNAUTHORIZED_USER.claims);
|
|
2560
|
-
}
|
|
2561
|
-
catch (_a) { }
|
|
2562
|
-
|
|
2563
2616
|
const swHolder = {};
|
|
2564
2617
|
const swContainer = typeof self !== 'undefined' && self.document && // self.document is to verify we're not the SW ourself
|
|
2565
2618
|
typeof navigator !== 'undefined' && navigator.serviceWorker;
|
|
@@ -3065,13 +3118,13 @@
|
|
|
3065
3118
|
},
|
|
3066
3119
|
};
|
|
3067
3120
|
|
|
3068
|
-
const _global = typeof globalThis !== "undefined"
|
|
3121
|
+
const _global = typeof globalThis !== "undefined" // All modern environments (node, bun, deno, browser, workers, webview etc)
|
|
3069
3122
|
? globalThis
|
|
3070
|
-
: typeof self !== "undefined"
|
|
3123
|
+
: typeof self !== "undefined" // Older browsers, workers, webview, window etc
|
|
3071
3124
|
? self
|
|
3072
|
-
: typeof global
|
|
3125
|
+
: typeof global !== "undefined" // Older versions of node
|
|
3073
3126
|
? global
|
|
3074
|
-
: undefined;
|
|
3127
|
+
: undefined; // Unsupported environment. No idea to return 'this' since we are in a module or a function scope anyway.
|
|
3075
3128
|
|
|
3076
3129
|
var TypedArraysDefs = [
|
|
3077
3130
|
"Int8Array",
|
|
@@ -3437,7 +3490,7 @@
|
|
|
3437
3490
|
const rewrittenKey = `${key}:${currentUser.userId}`;
|
|
3438
3491
|
mutClone.keys[keyIndex] = rewrittenKey;
|
|
3439
3492
|
if (rewriteValues) {
|
|
3440
|
-
|
|
3493
|
+
Dexie.setByKeyPath(mutClone.values[keyIndex], primaryKey.keyPath, rewrittenKey);
|
|
3441
3494
|
}
|
|
3442
3495
|
}
|
|
3443
3496
|
});
|
|
@@ -3456,6 +3509,40 @@
|
|
|
3456
3509
|
: change.muts.map((m) => (Object.assign(Object.assign({}, m), { keys: m.keys.slice() }))) });
|
|
3457
3510
|
}
|
|
3458
3511
|
|
|
3512
|
+
// If we get Ratelimit-Limit and Ratelimit-Remaining where Ratelimit-Remaining is below
|
|
3513
|
+
// (Ratelimit-Limit / 2), we should delay the next sync by (Ratelimit-Reset / Ratelimit-Remaining)
|
|
3514
|
+
// seconds (given that there is a Ratelimit-Reset header).
|
|
3515
|
+
let syncRatelimitDelays = new WeakMap();
|
|
3516
|
+
function checkSyncRateLimitDelay(db) {
|
|
3517
|
+
var _a, _b;
|
|
3518
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
3519
|
+
const delatMilliseconds = ((_b = (_a = syncRatelimitDelays.get(db)) === null || _a === void 0 ? void 0 : _a.getTime()) !== null && _b !== void 0 ? _b : 0) - Date.now();
|
|
3520
|
+
if (delatMilliseconds > 0) {
|
|
3521
|
+
console.debug(`Stalling sync request ${delatMilliseconds} ms to spare ratelimits`);
|
|
3522
|
+
yield new Promise(resolve => setTimeout(resolve, delatMilliseconds));
|
|
3523
|
+
}
|
|
3524
|
+
});
|
|
3525
|
+
}
|
|
3526
|
+
function updateSyncRateLimitDelays(db, res) {
|
|
3527
|
+
const limit = res.headers.get('Ratelimit-Limit');
|
|
3528
|
+
const remaining = res.headers.get('Ratelimit-Remaining');
|
|
3529
|
+
const reset = res.headers.get('Ratelimit-Reset');
|
|
3530
|
+
if (limit && remaining && reset) {
|
|
3531
|
+
const limitNum = Number(limit);
|
|
3532
|
+
const remainingNum = Math.max(0, Number(remaining));
|
|
3533
|
+
const willResetInSeconds = Number(reset);
|
|
3534
|
+
if (remainingNum < limitNum / 2) {
|
|
3535
|
+
const delay = Math.ceil(willResetInSeconds / (remainingNum + 1));
|
|
3536
|
+
syncRatelimitDelays.set(db, new Date(Date.now() + delay * 1000));
|
|
3537
|
+
console.debug(`Sync ratelimit delay set to ${delay} seconds`);
|
|
3538
|
+
}
|
|
3539
|
+
else {
|
|
3540
|
+
syncRatelimitDelays.delete(db);
|
|
3541
|
+
console.debug(`Sync ratelimit delay cleared`);
|
|
3542
|
+
}
|
|
3543
|
+
}
|
|
3544
|
+
}
|
|
3545
|
+
|
|
3459
3546
|
//import {BisonWebStreamReader} from "dreambase-library/dist/typeson-simplified/BisonWebStreamReader";
|
|
3460
3547
|
function syncWithServer(changes, syncState, baseRevs, db, databaseUrl, schema, clientIdentity, currentUser) {
|
|
3461
3548
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -3464,9 +3551,20 @@
|
|
|
3464
3551
|
//
|
|
3465
3552
|
const headers = {
|
|
3466
3553
|
Accept: 'application/json, application/x-bison, application/x-bison-stream',
|
|
3467
|
-
'Content-Type': 'application/tson'
|
|
3554
|
+
'Content-Type': 'application/tson',
|
|
3468
3555
|
};
|
|
3469
|
-
const
|
|
3556
|
+
const updatedUser = yield loadAccessToken(db);
|
|
3557
|
+
/*
|
|
3558
|
+
if (updatedUser?.license && changes.length > 0) {
|
|
3559
|
+
if (updatedUser.license.status === 'expired') {
|
|
3560
|
+
throw new Error(`License has expired`);
|
|
3561
|
+
}
|
|
3562
|
+
if (updatedUser.license.status === 'deactivated') {
|
|
3563
|
+
throw new Error(`License deactivated`);
|
|
3564
|
+
}
|
|
3565
|
+
}
|
|
3566
|
+
*/
|
|
3567
|
+
const accessToken = updatedUser === null || updatedUser === void 0 ? void 0 : updatedUser.accessToken;
|
|
3470
3568
|
if (accessToken) {
|
|
3471
3569
|
headers.Authorization = `Bearer ${accessToken}`;
|
|
3472
3570
|
}
|
|
@@ -3475,27 +3573,31 @@
|
|
|
3475
3573
|
dbID: syncState === null || syncState === void 0 ? void 0 : syncState.remoteDbId,
|
|
3476
3574
|
clientIdentity,
|
|
3477
3575
|
schema: schema || {},
|
|
3478
|
-
lastPull: syncState
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3576
|
+
lastPull: syncState
|
|
3577
|
+
? {
|
|
3578
|
+
serverRevision: syncState.serverRevision,
|
|
3579
|
+
realms: syncState.realms,
|
|
3580
|
+
inviteRealms: syncState.inviteRealms,
|
|
3581
|
+
}
|
|
3582
|
+
: undefined,
|
|
3483
3583
|
baseRevs,
|
|
3484
|
-
changes: encodeIdsForServer(db.dx.core.schema, currentUser, changes)
|
|
3584
|
+
changes: encodeIdsForServer(db.dx.core.schema, currentUser, changes),
|
|
3485
3585
|
};
|
|
3486
|
-
console.debug(
|
|
3586
|
+
console.debug('Sync request', syncRequest);
|
|
3487
3587
|
db.syncStateChangedEvent.next({
|
|
3488
3588
|
phase: 'pushing',
|
|
3489
3589
|
});
|
|
3490
3590
|
const res = yield fetch(`${databaseUrl}/sync`, {
|
|
3491
3591
|
method: 'post',
|
|
3492
3592
|
headers,
|
|
3493
|
-
|
|
3593
|
+
credentials: 'include',
|
|
3594
|
+
body: TSON.stringify(syncRequest),
|
|
3494
3595
|
});
|
|
3495
3596
|
//const contentLength = Number(res.headers.get('content-length'));
|
|
3496
3597
|
db.syncStateChangedEvent.next({
|
|
3497
|
-
phase: 'pulling'
|
|
3598
|
+
phase: 'pulling',
|
|
3498
3599
|
});
|
|
3600
|
+
updateSyncRateLimitDelays(db, res);
|
|
3499
3601
|
if (!res.ok) {
|
|
3500
3602
|
throw new HttpError(res);
|
|
3501
3603
|
}
|
|
@@ -3552,7 +3654,7 @@
|
|
|
3552
3654
|
|
|
3553
3655
|
function throwIfCancelled(cancelToken) {
|
|
3554
3656
|
if (cancelToken === null || cancelToken === void 0 ? void 0 : cancelToken.cancelled)
|
|
3555
|
-
throw new
|
|
3657
|
+
throw new Dexie.AbortError(`Operation was cancelled`);
|
|
3556
3658
|
}
|
|
3557
3659
|
|
|
3558
3660
|
/* Need this because navigator.onLine seems to say "false" when it is actually online.
|
|
@@ -3604,7 +3706,7 @@
|
|
|
3604
3706
|
}
|
|
3605
3707
|
}
|
|
3606
3708
|
else {
|
|
3607
|
-
|
|
3709
|
+
Dexie.setByKeyPath(obj, keyPath, value);
|
|
3608
3710
|
}
|
|
3609
3711
|
}
|
|
3610
3712
|
resultKeys.push(key);
|
|
@@ -3619,7 +3721,7 @@
|
|
|
3619
3721
|
|
|
3620
3722
|
function applyServerChanges(changes, db) {
|
|
3621
3723
|
return __awaiter(this, void 0, void 0, function* () {
|
|
3622
|
-
console.debug('Applying server changes', changes,
|
|
3724
|
+
console.debug('Applying server changes', changes, Dexie.currentTransaction);
|
|
3623
3725
|
for (const { table: tableName, muts } of changes) {
|
|
3624
3726
|
const table = db.table(tableName);
|
|
3625
3727
|
if (!table)
|
|
@@ -3656,7 +3758,7 @@
|
|
|
3656
3758
|
else {
|
|
3657
3759
|
keys.forEach((key, i) => {
|
|
3658
3760
|
// Make sure inbound keys are consistent
|
|
3659
|
-
|
|
3761
|
+
Dexie.setByKeyPath(mut.values[i], primaryKey.keyPath, key);
|
|
3660
3762
|
});
|
|
3661
3763
|
yield table.bulkAdd(mut.values);
|
|
3662
3764
|
}
|
|
@@ -3668,7 +3770,7 @@
|
|
|
3668
3770
|
else {
|
|
3669
3771
|
keys.forEach((key, i) => {
|
|
3670
3772
|
// Make sure inbound keys are consistent
|
|
3671
|
-
|
|
3773
|
+
Dexie.setByKeyPath(mut.values[i], primaryKey.keyPath, key);
|
|
3672
3774
|
});
|
|
3673
3775
|
yield table.bulkPut(mut.values);
|
|
3674
3776
|
}
|
|
@@ -3697,12 +3799,13 @@
|
|
|
3697
3799
|
function sync(db, options, schema, syncOptions) {
|
|
3698
3800
|
return _sync
|
|
3699
3801
|
.apply(this, arguments)
|
|
3700
|
-
.then(() => {
|
|
3802
|
+
.then((result) => {
|
|
3701
3803
|
if (!(syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.justCheckIfNeeded)) { // && syncOptions?.purpose !== 'push') {
|
|
3702
3804
|
db.syncStateChangedEvent.next({
|
|
3703
3805
|
phase: 'in-sync',
|
|
3704
3806
|
});
|
|
3705
3807
|
}
|
|
3808
|
+
return result;
|
|
3706
3809
|
})
|
|
3707
3810
|
.catch((error) => __awaiter(this, void 0, void 0, function* () {
|
|
3708
3811
|
if (syncOptions === null || syncOptions === void 0 ? void 0 : syncOptions.justCheckIfNeeded)
|
|
@@ -3917,6 +4020,7 @@
|
|
|
3917
4020
|
}));
|
|
3918
4021
|
if (!done) {
|
|
3919
4022
|
console.debug('MORE SYNC NEEDED. Go for it again!');
|
|
4023
|
+
yield checkSyncRateLimitDelay(db);
|
|
3920
4024
|
return yield _sync(db, options, schema, { isInitialSync, cancelToken });
|
|
3921
4025
|
}
|
|
3922
4026
|
console.debug('SYNC DONE', { isInitialSync });
|
|
@@ -4053,6 +4157,8 @@
|
|
|
4053
4157
|
yield db.table('$logins').update(user.userId, {
|
|
4054
4158
|
accessToken: refreshedLogin.accessToken,
|
|
4055
4159
|
accessTokenExpiration: refreshedLogin.accessTokenExpiration,
|
|
4160
|
+
claims: refreshedLogin.claims,
|
|
4161
|
+
license: refreshedLogin.license,
|
|
4056
4162
|
});
|
|
4057
4163
|
// Updating $logins will trigger emission of db.cloud.currentUser observable, which
|
|
4058
4164
|
// in turn will lead to that connectWebSocket.ts will reconnect the socket with the
|
|
@@ -4129,7 +4235,7 @@
|
|
|
4129
4235
|
return; // Ignore message
|
|
4130
4236
|
}
|
|
4131
4237
|
// Verify also that the message is based on the exact same set of realms
|
|
4132
|
-
const ourRealmSetHash = yield
|
|
4238
|
+
const ourRealmSetHash = yield Dexie.waitFor(
|
|
4133
4239
|
// Keep TX in non-IDB work
|
|
4134
4240
|
computeRealmSetHash(syncState));
|
|
4135
4241
|
console.debug('ourRealmSetHash', ourRealmSetHash);
|
|
@@ -4336,7 +4442,7 @@
|
|
|
4336
4442
|
const IS_SERVICE_WORKER = typeof self !== "undefined" && "clients" in self && !self.document;
|
|
4337
4443
|
|
|
4338
4444
|
function throwVersionIncrementNeeded() {
|
|
4339
|
-
throw new
|
|
4445
|
+
throw new Dexie.SchemaError(`Version increment needed to allow dexie-cloud change tracking`);
|
|
4340
4446
|
}
|
|
4341
4447
|
|
|
4342
4448
|
const { toString } = {};
|
|
@@ -4452,14 +4558,14 @@
|
|
|
4452
4558
|
if (!table.schema.primaryKey.outbound) {
|
|
4453
4559
|
if (!valueClones)
|
|
4454
4560
|
valueClones = req.values.slice();
|
|
4455
|
-
valueClones[idx] =
|
|
4456
|
-
|
|
4561
|
+
valueClones[idx] = Dexie.deepClone(valueClones[idx]);
|
|
4562
|
+
Dexie.setByKeyPath(valueClones[idx], table.schema.primaryKey.keyPath, keys[idx]);
|
|
4457
4563
|
}
|
|
4458
4564
|
}
|
|
4459
4565
|
else if (typeof key !== 'string' ||
|
|
4460
4566
|
(!key.startsWith(idPrefix) && !key.startsWith('#' + idPrefix))) {
|
|
4461
4567
|
// Key was specified by caller. Verify it complies with id prefix.
|
|
4462
|
-
throw new
|
|
4568
|
+
throw new Dexie.ConstraintError(`The ID "${key}" is not valid for table "${tableName}". ` +
|
|
4463
4569
|
`Primary '@' keys requires the key to be prefixed with "${idPrefix}" (or "#${idPrefix}).\n` +
|
|
4464
4570
|
`If you want to generate IDs programmatically, remove '@' from the schema to get rid of this constraint. Dexie Cloud supports custom IDs as long as they are random and globally unique.`);
|
|
4465
4571
|
}
|
|
@@ -4484,7 +4590,7 @@
|
|
|
4484
4590
|
const type = Array.isArray(key)
|
|
4485
4591
|
? key.map(toStringTag).join(',')
|
|
4486
4592
|
: toStringTag(key);
|
|
4487
|
-
throw new
|
|
4593
|
+
throw new Dexie.ConstraintError(`Invalid primary key type ${type} for table ${tableName}. Tables marked for sync has primary keys of type string or Array of string (and optional numbers)`);
|
|
4488
4594
|
}
|
|
4489
4595
|
});
|
|
4490
4596
|
}
|
|
@@ -4621,6 +4727,13 @@
|
|
|
4621
4727
|
|
|
4622
4728
|
const outstandingTransactions = new rxjs.BehaviorSubject(new Set());
|
|
4623
4729
|
|
|
4730
|
+
function isEagerSyncDisabled(db) {
|
|
4731
|
+
var _a, _b, _c, _d;
|
|
4732
|
+
return (((_a = db.cloud.options) === null || _a === void 0 ? void 0 : _a.disableEagerSync) ||
|
|
4733
|
+
((_c = (_b = db.cloud.currentUser.value) === null || _b === void 0 ? void 0 : _b.license) === null || _c === void 0 ? void 0 : _c.status) !== 'ok' ||
|
|
4734
|
+
!((_d = db.cloud.options) === null || _d === void 0 ? void 0 : _d.databaseUrl));
|
|
4735
|
+
}
|
|
4736
|
+
|
|
4624
4737
|
/** Tracks all mutations in the same transaction as the mutations -
|
|
4625
4738
|
* so it is guaranteed that no mutation goes untracked - and if transaction
|
|
4626
4739
|
* aborts, the mutations won't be tracked.
|
|
@@ -4629,7 +4742,7 @@
|
|
|
4629
4742
|
* changes to server and cleanup the tracked mutations once the server has
|
|
4630
4743
|
* ackowledged that it got them.
|
|
4631
4744
|
*/
|
|
4632
|
-
function createMutationTrackingMiddleware({ currentUserObservable, db }) {
|
|
4745
|
+
function createMutationTrackingMiddleware({ currentUserObservable, db, }) {
|
|
4633
4746
|
return {
|
|
4634
4747
|
stack: 'dbcore',
|
|
4635
4748
|
name: 'MutationTrackingMiddleware',
|
|
@@ -4640,7 +4753,7 @@
|
|
|
4640
4753
|
try {
|
|
4641
4754
|
mutTableMap = new Map(ordinaryTables.map((tbl) => [
|
|
4642
4755
|
tbl.name,
|
|
4643
|
-
core.table(`$${tbl.name}_mutations`)
|
|
4756
|
+
core.table(`$${tbl.name}_mutations`),
|
|
4644
4757
|
]));
|
|
4645
4758
|
}
|
|
4646
4759
|
catch (_a) {
|
|
@@ -4674,15 +4787,9 @@
|
|
|
4674
4787
|
outstandingTransactions.next(outstandingTransactions.value);
|
|
4675
4788
|
};
|
|
4676
4789
|
const txComplete = () => {
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
console.debug('registering sync event');
|
|
4681
|
-
registerSyncEvent(db, "push");
|
|
4682
|
-
}
|
|
4683
|
-
else {
|
|
4684
|
-
db.localSyncEvent.next({ purpose: "push" });
|
|
4685
|
-
}
|
|
4790
|
+
if (tx.mutationsAdded &&
|
|
4791
|
+
!isEagerSyncDisabled(db)) {
|
|
4792
|
+
triggerSync(db, 'push');
|
|
4686
4793
|
}
|
|
4687
4794
|
removeTransaction();
|
|
4688
4795
|
};
|
|
@@ -4749,7 +4856,7 @@
|
|
|
4749
4856
|
.query({
|
|
4750
4857
|
query: { range: req.range, index: schema.primaryKey },
|
|
4751
4858
|
trans: req.trans,
|
|
4752
|
-
values: false
|
|
4859
|
+
values: false,
|
|
4753
4860
|
})
|
|
4754
4861
|
// Do a delete request instead, but keep the criteria info for the server to execute
|
|
4755
4862
|
.then((res) => {
|
|
@@ -4757,7 +4864,7 @@
|
|
|
4757
4864
|
type: 'delete',
|
|
4758
4865
|
keys: res.result,
|
|
4759
4866
|
trans: req.trans,
|
|
4760
|
-
criteria: { index: null, range: req.range }
|
|
4867
|
+
criteria: { index: null, range: req.range },
|
|
4761
4868
|
});
|
|
4762
4869
|
})
|
|
4763
4870
|
: mutateAndLog(req);
|
|
@@ -4765,7 +4872,7 @@
|
|
|
4765
4872
|
function mutateAndLog(req) {
|
|
4766
4873
|
const trans = req.trans;
|
|
4767
4874
|
trans.mutationsAdded = true;
|
|
4768
|
-
const { txid, currentUser: { userId } } = trans;
|
|
4875
|
+
const { txid, currentUser: { userId }, } = trans;
|
|
4769
4876
|
const { type } = req;
|
|
4770
4877
|
const opNo = ++trans.opCount;
|
|
4771
4878
|
return table.mutate(req).then((res) => {
|
|
@@ -4786,7 +4893,7 @@
|
|
|
4786
4893
|
keys,
|
|
4787
4894
|
criteria: req.criteria,
|
|
4788
4895
|
txid,
|
|
4789
|
-
userId
|
|
4896
|
+
userId,
|
|
4790
4897
|
}
|
|
4791
4898
|
: req.type === 'add'
|
|
4792
4899
|
? {
|
|
@@ -4796,7 +4903,7 @@
|
|
|
4796
4903
|
keys,
|
|
4797
4904
|
txid,
|
|
4798
4905
|
userId,
|
|
4799
|
-
values
|
|
4906
|
+
values,
|
|
4800
4907
|
}
|
|
4801
4908
|
: req.criteria && req.changeSpec
|
|
4802
4909
|
? {
|
|
@@ -4808,7 +4915,7 @@
|
|
|
4808
4915
|
criteria: req.criteria,
|
|
4809
4916
|
changeSpec: req.changeSpec,
|
|
4810
4917
|
txid,
|
|
4811
|
-
userId
|
|
4918
|
+
userId,
|
|
4812
4919
|
}
|
|
4813
4920
|
: updates
|
|
4814
4921
|
? {
|
|
@@ -4819,7 +4926,7 @@
|
|
|
4819
4926
|
keys: updates.keys,
|
|
4820
4927
|
changeSpecs: updates.changeSpecs,
|
|
4821
4928
|
txid,
|
|
4822
|
-
userId
|
|
4929
|
+
userId,
|
|
4823
4930
|
}
|
|
4824
4931
|
: {
|
|
4825
4932
|
type: 'upsert',
|
|
@@ -4828,7 +4935,7 @@
|
|
|
4828
4935
|
keys,
|
|
4829
4936
|
values,
|
|
4830
4937
|
txid,
|
|
4831
|
-
userId
|
|
4938
|
+
userId,
|
|
4832
4939
|
};
|
|
4833
4940
|
return keys.length > 0 || ('criteria' in req && req.criteria)
|
|
4834
4941
|
? mutsTable
|
|
@@ -4838,7 +4945,7 @@
|
|
|
4838
4945
|
});
|
|
4839
4946
|
}
|
|
4840
4947
|
} });
|
|
4841
|
-
}
|
|
4948
|
+
},
|
|
4842
4949
|
};
|
|
4843
4950
|
}
|
|
4844
4951
|
|
|
@@ -5197,6 +5304,20 @@
|
|
|
5197
5304
|
}
|
|
5198
5305
|
}
|
|
5199
5306
|
|
|
5307
|
+
class InvalidLicenseError extends Error {
|
|
5308
|
+
constructor(license) {
|
|
5309
|
+
super(license === 'expired'
|
|
5310
|
+
? `License expired`
|
|
5311
|
+
: license === 'deactivated'
|
|
5312
|
+
? `User deactivated`
|
|
5313
|
+
: 'Invalid license');
|
|
5314
|
+
this.name = 'InvalidLicenseError';
|
|
5315
|
+
if (license) {
|
|
5316
|
+
this.license = license;
|
|
5317
|
+
}
|
|
5318
|
+
}
|
|
5319
|
+
}
|
|
5320
|
+
|
|
5200
5321
|
function sleep(ms) {
|
|
5201
5322
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
5202
5323
|
}
|
|
@@ -5230,7 +5351,12 @@
|
|
|
5230
5351
|
function createObservable() {
|
|
5231
5352
|
return db.cloud.persistedSyncState.pipe(filter((syncState) => syncState === null || syncState === void 0 ? void 0 : syncState.serverRevision), // Don't connect before there's no initial sync performed.
|
|
5232
5353
|
take(1), // Don't continue waking up whenever syncState change
|
|
5233
|
-
switchMap((syncState) => db.cloud.currentUser.pipe(map((userLogin) => [userLogin, syncState]))), switchMap(([userLogin, syncState]) =>
|
|
5354
|
+
switchMap((syncState) => db.cloud.currentUser.pipe(map((userLogin) => [userLogin, syncState]))), switchMap(([userLogin, syncState]) => {
|
|
5355
|
+
/*if (userLogin.license?.status && userLogin.license.status !== 'ok') {
|
|
5356
|
+
throw new InvalidLicenseError();
|
|
5357
|
+
}*/
|
|
5358
|
+
return userIsReallyActive.pipe(map((isActive) => [isActive ? userLogin : null, syncState]));
|
|
5359
|
+
}), switchMap(([userLogin, syncState]) => {
|
|
5234
5360
|
if ((userLogin === null || userLogin === void 0 ? void 0 : userLogin.isLoggedIn) && !(syncState === null || syncState === void 0 ? void 0 : syncState.realms.includes(userLogin.userId))) {
|
|
5235
5361
|
// We're in an in-between state when user is logged in but the user's realms are not yet synced.
|
|
5236
5362
|
// Don't make this change reconnect the websocket just yet. Wait till syncState is updated
|
|
@@ -5259,14 +5385,20 @@
|
|
|
5259
5385
|
yield db.table('$logins').update(user.userId, {
|
|
5260
5386
|
accessToken: refreshedLogin.accessToken,
|
|
5261
5387
|
accessTokenExpiration: refreshedLogin.accessTokenExpiration,
|
|
5388
|
+
claims: refreshedLogin.claims,
|
|
5389
|
+
license: refreshedLogin.license,
|
|
5262
5390
|
});
|
|
5263
5391
|
})), switchMap(() => createObservable()));
|
|
5264
5392
|
}
|
|
5265
5393
|
else {
|
|
5266
|
-
return rxjs.throwError(error);
|
|
5394
|
+
return rxjs.throwError(() => error);
|
|
5267
5395
|
}
|
|
5268
5396
|
}), catchError((error) => {
|
|
5269
5397
|
db.cloud.webSocketStatus.next("error");
|
|
5398
|
+
if (error instanceof InvalidLicenseError) {
|
|
5399
|
+
// Don't retry. Just throw and don't try connect again.
|
|
5400
|
+
return rxjs.throwError(() => error);
|
|
5401
|
+
}
|
|
5270
5402
|
return rxjs.from(waitAndReconnectWhenUserDoesSomething(error)).pipe(switchMap(() => createObservable()));
|
|
5271
5403
|
}));
|
|
5272
5404
|
}
|
|
@@ -5295,97 +5427,12 @@
|
|
|
5295
5427
|
});
|
|
5296
5428
|
}
|
|
5297
5429
|
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
const GUARDED_JOB_TIMEOUT = 1 * MINUTES;
|
|
5305
|
-
function performGuardedJob(db, jobName, jobsTableName, job, { awaitRemoteJob } = {}) {
|
|
5306
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
5307
|
-
// Start working.
|
|
5308
|
-
//
|
|
5309
|
-
// Check if someone else is working on this already.
|
|
5310
|
-
//
|
|
5311
|
-
const jobsTable = db.table(jobsTableName);
|
|
5312
|
-
function aquireLock() {
|
|
5313
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
5314
|
-
const gotTheLock = yield db.transaction('rw!', jobsTableName, () => __awaiter(this, void 0, void 0, function* () {
|
|
5315
|
-
const currentWork = yield jobsTable.get(jobName);
|
|
5316
|
-
if (!currentWork) {
|
|
5317
|
-
// No one else is working. Let's record that we are.
|
|
5318
|
-
yield jobsTable.add({
|
|
5319
|
-
nodeId: myId,
|
|
5320
|
-
started: new Date(),
|
|
5321
|
-
heartbeat: new Date()
|
|
5322
|
-
}, jobName);
|
|
5323
|
-
return true;
|
|
5324
|
-
}
|
|
5325
|
-
else if (currentWork.heartbeat.getTime() <
|
|
5326
|
-
Date.now() - GUARDED_JOB_TIMEOUT) {
|
|
5327
|
-
console.warn(`Latest ${jobName} worker seem to have died.\n`, `The dead job started:`, currentWork.started, `\n`, `Last heart beat was:`, currentWork.heartbeat, '\n', `We're now taking over!`);
|
|
5328
|
-
// Now, take over!
|
|
5329
|
-
yield jobsTable.put({
|
|
5330
|
-
nodeId: myId,
|
|
5331
|
-
started: new Date(),
|
|
5332
|
-
heartbeat: new Date()
|
|
5333
|
-
}, jobName);
|
|
5334
|
-
return true;
|
|
5335
|
-
}
|
|
5336
|
-
return false;
|
|
5337
|
-
}));
|
|
5338
|
-
if (gotTheLock)
|
|
5339
|
-
return true;
|
|
5340
|
-
// Someone else took the job.
|
|
5341
|
-
if (awaitRemoteJob) {
|
|
5342
|
-
try {
|
|
5343
|
-
const jobDoneObservable = rxjs.from(Dexie.liveQuery(() => jobsTable.get(jobName))).pipe(timeout(GUARDED_JOB_TIMEOUT), filter((job) => !job)); // Wait til job is not there anymore.
|
|
5344
|
-
yield jobDoneObservable.toPromise();
|
|
5345
|
-
return false;
|
|
5346
|
-
}
|
|
5347
|
-
catch (err) {
|
|
5348
|
-
if (err.name !== 'TimeoutError') {
|
|
5349
|
-
throw err;
|
|
5350
|
-
}
|
|
5351
|
-
// Timeout stopped us! Try aquire the lock now.
|
|
5352
|
-
// It will likely succeed this time unless
|
|
5353
|
-
// another client took it.
|
|
5354
|
-
return yield aquireLock();
|
|
5355
|
-
}
|
|
5356
|
-
}
|
|
5357
|
-
return false;
|
|
5358
|
-
});
|
|
5359
|
-
}
|
|
5360
|
-
if (yield aquireLock()) {
|
|
5361
|
-
// We own the lock entry and can do our job undisturbed.
|
|
5362
|
-
// We're not within a transaction, but these type of locks
|
|
5363
|
-
// spans over transactions.
|
|
5364
|
-
// Start our heart beat during the job.
|
|
5365
|
-
// Use setInterval to make sure we are updating heartbeat even during long-lived fetch calls.
|
|
5366
|
-
const heartbeat = setInterval(() => {
|
|
5367
|
-
jobsTable.update(jobName, (job) => {
|
|
5368
|
-
if (job.nodeId === myId) {
|
|
5369
|
-
job.heartbeat = new Date();
|
|
5370
|
-
}
|
|
5371
|
-
});
|
|
5372
|
-
}, GUARDED_JOB_HEARTBEAT);
|
|
5373
|
-
try {
|
|
5374
|
-
return yield job();
|
|
5375
|
-
}
|
|
5376
|
-
finally {
|
|
5377
|
-
// Stop heartbeat
|
|
5378
|
-
clearInterval(heartbeat);
|
|
5379
|
-
// Remove the persisted job state:
|
|
5380
|
-
yield db.transaction('rw!', jobsTableName, () => __awaiter(this, void 0, void 0, function* () {
|
|
5381
|
-
const currentWork = yield jobsTable.get(jobName);
|
|
5382
|
-
if (currentWork && currentWork.nodeId === myId) {
|
|
5383
|
-
yield jobsTable.delete(jobName);
|
|
5384
|
-
}
|
|
5385
|
-
}));
|
|
5386
|
-
}
|
|
5387
|
-
}
|
|
5388
|
-
});
|
|
5430
|
+
function performGuardedJob(db, jobName, job) {
|
|
5431
|
+
if (typeof navigator === 'undefined' || !navigator.locks) {
|
|
5432
|
+
// No support for guarding jobs. IE11, node.js, etc.
|
|
5433
|
+
return job();
|
|
5434
|
+
}
|
|
5435
|
+
return navigator.locks.request(db.name + '|' + jobName, () => job());
|
|
5389
5436
|
}
|
|
5390
5437
|
|
|
5391
5438
|
const ongoingSyncs = new WeakMap();
|
|
@@ -5439,6 +5486,9 @@
|
|
|
5439
5486
|
function _syncIfPossible() {
|
|
5440
5487
|
return __awaiter(this, void 0, void 0, function* () {
|
|
5441
5488
|
try {
|
|
5489
|
+
// Check if should delay sync due to ratelimit:
|
|
5490
|
+
yield checkSyncRateLimitDelay(db);
|
|
5491
|
+
// Check if we need to lock the sync job. Not needed if we are the service worker.
|
|
5442
5492
|
if (db.cloud.isServiceWorkerDB) {
|
|
5443
5493
|
// We are the dedicated sync SW:
|
|
5444
5494
|
yield sync(db, cloudOptions, cloudSchema, options);
|
|
@@ -5446,7 +5496,7 @@
|
|
|
5446
5496
|
else if (!db.cloud.usingServiceWorker) {
|
|
5447
5497
|
// We use a flow that is better suited for the case when multiple workers want to
|
|
5448
5498
|
// do the same thing.
|
|
5449
|
-
yield performGuardedJob(db, CURRENT_SYNC_WORKER,
|
|
5499
|
+
yield performGuardedJob(db, CURRENT_SYNC_WORKER, () => sync(db, cloudOptions, cloudSchema, options));
|
|
5450
5500
|
}
|
|
5451
5501
|
else {
|
|
5452
5502
|
assert(false);
|
|
@@ -5468,19 +5518,29 @@
|
|
|
5468
5518
|
}
|
|
5469
5519
|
}
|
|
5470
5520
|
|
|
5521
|
+
const SECONDS = 1000;
|
|
5522
|
+
const MINUTES = 60 * SECONDS;
|
|
5523
|
+
|
|
5471
5524
|
function LocalSyncWorker(db, cloudOptions, cloudSchema) {
|
|
5472
5525
|
let localSyncEventSubscription = null;
|
|
5473
5526
|
//let syncHandler: ((event: Event) => void) | null = null;
|
|
5474
5527
|
//let periodicSyncHandler: ((event: Event) => void) | null = null;
|
|
5475
5528
|
let cancelToken = { cancelled: false };
|
|
5529
|
+
let retryHandle = null;
|
|
5530
|
+
let retryPurpose = null; // "pull" is superset of "push"
|
|
5476
5531
|
function syncAndRetry(purpose, retryNum = 1) {
|
|
5477
5532
|
// Use setTimeout() to get onto a clean stack and
|
|
5478
5533
|
// break free from possible active transaction:
|
|
5479
5534
|
setTimeout(() => {
|
|
5535
|
+
if (retryHandle)
|
|
5536
|
+
clearTimeout(retryHandle);
|
|
5537
|
+
const combPurpose = retryPurpose === 'pull' ? 'pull' : purpose;
|
|
5538
|
+
retryHandle = null;
|
|
5539
|
+
retryPurpose = null;
|
|
5480
5540
|
syncIfPossible(db, cloudOptions, cloudSchema, {
|
|
5481
5541
|
cancelToken,
|
|
5482
5542
|
retryImmediatelyOnFetchError: true,
|
|
5483
|
-
purpose,
|
|
5543
|
+
purpose: combPurpose,
|
|
5484
5544
|
}).catch((e) => {
|
|
5485
5545
|
console.error('error in syncIfPossible()', e);
|
|
5486
5546
|
if (cancelToken.cancelled) {
|
|
@@ -5490,7 +5550,13 @@
|
|
|
5490
5550
|
// Mimic service worker sync event: retry 3 times
|
|
5491
5551
|
// * first retry after 5 minutes
|
|
5492
5552
|
// * second retry 15 minutes later
|
|
5493
|
-
|
|
5553
|
+
const combinedPurpose = retryPurpose && retryPurpose === 'pull' ? 'pull' : purpose;
|
|
5554
|
+
const handle = setTimeout(() => syncAndRetry(combinedPurpose, retryNum + 1), [0, 5, 15][retryNum] * MINUTES);
|
|
5555
|
+
// Cancel the previous retryHandle if it exists to avoid scheduling loads of retries.
|
|
5556
|
+
if (retryHandle)
|
|
5557
|
+
clearTimeout(retryHandle);
|
|
5558
|
+
retryHandle = handle;
|
|
5559
|
+
retryPurpose = combinedPurpose;
|
|
5494
5560
|
}
|
|
5495
5561
|
});
|
|
5496
5562
|
}, 0);
|
|
@@ -5538,11 +5604,11 @@
|
|
|
5538
5604
|
for (const table of db.tables) {
|
|
5539
5605
|
if ((_b = (_a = db.cloud.schema) === null || _a === void 0 ? void 0 : _a[table.name]) === null || _b === void 0 ? void 0 : _b.markedForSync) {
|
|
5540
5606
|
if (table.schema.primKey.auto) {
|
|
5541
|
-
throw new
|
|
5607
|
+
throw new Dexie.SchemaError(`Table ${table.name} is both autoIncremented and synced. ` +
|
|
5542
5608
|
`Use db.cloud.configure({unsyncedTables: [${JSON.stringify(table.name)}]}) to blacklist it from sync`);
|
|
5543
5609
|
}
|
|
5544
5610
|
if (!table.schema.primKey.keyPath) {
|
|
5545
|
-
throw new
|
|
5611
|
+
throw new Dexie.SchemaError(`Table ${table.name} cannot be both synced and outbound. ` +
|
|
5546
5612
|
`Use db.cloud.configure({unsyncedTables: [${JSON.stringify(table.name)}]}) to blacklist it from sync`);
|
|
5547
5613
|
}
|
|
5548
5614
|
}
|
|
@@ -5557,10 +5623,12 @@
|
|
|
5557
5623
|
},
|
|
5558
5624
|
Alert: {
|
|
5559
5625
|
error: {
|
|
5560
|
-
color: "red"
|
|
5626
|
+
color: "red",
|
|
5627
|
+
fontWeight: "bold"
|
|
5561
5628
|
},
|
|
5562
5629
|
warning: {
|
|
5563
|
-
color: "
|
|
5630
|
+
color: "#f80",
|
|
5631
|
+
fontWeight: "bold"
|
|
5564
5632
|
},
|
|
5565
5633
|
info: {
|
|
5566
5634
|
color: "black"
|
|
@@ -5601,7 +5669,8 @@
|
|
|
5601
5669
|
border: "3px solid #3d3d5d",
|
|
5602
5670
|
borderRadius: "8px",
|
|
5603
5671
|
boxShadow: "0 0 80px 10px #666",
|
|
5604
|
-
width: "auto"
|
|
5672
|
+
width: "auto",
|
|
5673
|
+
fontFamily: "sans-serif",
|
|
5605
5674
|
},
|
|
5606
5675
|
Input: {
|
|
5607
5676
|
height: "35px",
|
|
@@ -5622,11 +5691,26 @@
|
|
|
5622
5691
|
|
|
5623
5692
|
var t,r,u,i,o=0,c=[],f=[],e=l$1.__b,a=l$1.__r,v=l$1.diffed,l=l$1.__c,m=l$1.unmount;function d(t,u){l$1.__h&&l$1.__h(r,t,o||u),o=0;var i=r.__H||(r.__H={__:[],__h:[]});return t>=i.__.length&&i.__.push({__V:f}),i.__[t]}function p(n){return o=1,y(z,n)}function y(n,u,i){var o=d(t++,2);if(o.t=n,!o.__c&&(o.__=[i?i(u):z(void 0,u),function(n){var t=o.__N?o.__N[0]:o.__[0],r=o.t(t,n);t!==r&&(o.__N=[r,o.__[1]],o.__c.setState({}));}],o.__c=r,!r.u)){r.u=!0;var c=r.shouldComponentUpdate;r.shouldComponentUpdate=function(n,t,r){if(!o.__c.__H)return !0;var u=o.__c.__H.__.filter(function(n){return n.__c});if(u.every(function(n){return !n.__N}))return !c||c.call(this,n,t,r);var i=!1;return u.forEach(function(n){if(n.__N){var t=n.__[0];n.__=n.__N,n.__N=void 0,t!==n.__[0]&&(i=!0);}}),!!i&&(!c||c.call(this,n,t,r))};}return o.__N||o.__}function s(u,i){var o=d(t++,4);!l$1.__s&&w(o.__H,i)&&(o.__=u,o.i=i,r.__h.push(o));}function _(n){return o=5,F(function(){return {current:n}},[])}function F(n,r){var u=d(t++,7);return w(u.__H,r)?(u.__V=n(),u.i=r,u.__h=n,u.__V):u.__}function b(){for(var t;t=c.shift();)if(t.__P&&t.__H)try{t.__H.__h.forEach(j),t.__H.__h.forEach(k),t.__H.__h=[];}catch(r){t.__H.__h=[],l$1.__e(r,t.__v);}}l$1.__b=function(n){r=null,e&&e(n);},l$1.__r=function(n){a&&a(n),t=0;var i=(r=n.__c).__H;i&&(u===r?(i.__h=[],r.__h=[],i.__.forEach(function(n){n.__N&&(n.__=n.__N),n.__V=f,n.__N=n.i=void 0;})):(i.__h.forEach(j),i.__h.forEach(k),i.__h=[])),u=r;},l$1.diffed=function(t){v&&v(t);var o=t.__c;o&&o.__H&&(o.__H.__h.length&&(1!==c.push(o)&&i===l$1.requestAnimationFrame||((i=l$1.requestAnimationFrame)||function(n){var t,r=function(){clearTimeout(u),g&&cancelAnimationFrame(t),setTimeout(n);},u=setTimeout(r,100);g&&(t=requestAnimationFrame(r));})(b)),o.__H.__.forEach(function(n){n.i&&(n.__H=n.i),n.__V!==f&&(n.__=n.__V),n.i=void 0,n.__V=f;})),u=r=null;},l$1.__c=function(t,r){r.some(function(t){try{t.__h.forEach(j),t.__h=t.__h.filter(function(n){return !n.__||k(n)});}catch(u){r.some(function(n){n.__h&&(n.__h=[]);}),r=[],l$1.__e(u,t.__v);}}),l&&l(t,r);},l$1.unmount=function(t){m&&m(t);var r,u=t.__c;u&&u.__H&&(u.__H.__.forEach(function(n){try{j(n);}catch(n){r=n;}}),r&&l$1.__e(r,u.__v));};var g="function"==typeof requestAnimationFrame;function j(n){var t=r,u=n.__c;"function"==typeof u&&(n.__c=void 0,u()),r=t;}function k(n){var t=r;n.__c=n.__(),r=t;}function w(n,t){return !n||n.length!==t.length||t.some(function(t,r){return t!==n[r]})}function z(n,t){return "function"==typeof t?t(n):t}
|
|
5624
5693
|
|
|
5694
|
+
/** Resolve a message template with parameters.
|
|
5695
|
+
*
|
|
5696
|
+
* Example:
|
|
5697
|
+
* resolveText({
|
|
5698
|
+
* message: "Hello {name}!",
|
|
5699
|
+
* messageCode: "HELLO",
|
|
5700
|
+
* messageParams: {name: "David"}
|
|
5701
|
+
* }) => "Hello David!"
|
|
5702
|
+
*
|
|
5703
|
+
* @param message Template message with {vars} in it.
|
|
5704
|
+
* @param messageCode Unique code for the message. Can be used for translation.
|
|
5705
|
+
* @param messageParams Parameters to be used in the message.
|
|
5706
|
+
* @returns A final message where parameters have been replaced with values.
|
|
5707
|
+
*/
|
|
5625
5708
|
function resolveText({ message, messageCode, messageParams }) {
|
|
5626
|
-
return message.replace(/\{\w+\}/ig, n => messageParams[n.
|
|
5709
|
+
return message.replace(/\{\w+\}/ig, n => messageParams[n.substring(1, n.length - 1)]);
|
|
5627
5710
|
}
|
|
5628
5711
|
|
|
5629
|
-
|
|
5712
|
+
const OTP_LENGTH = 8;
|
|
5713
|
+
function LoginDialog({ title, type, alerts, fields, submitLabel, cancelLabel, onCancel, onSubmit, }) {
|
|
5630
5714
|
const [params, setParams] = p({});
|
|
5631
5715
|
const firstFieldRef = _(null);
|
|
5632
5716
|
s(() => { var _a; return (_a = firstFieldRef.current) === null || _a === void 0 ? void 0 : _a.focus(); }, []);
|
|
@@ -5634,21 +5718,34 @@
|
|
|
5634
5718
|
h(p$1, null,
|
|
5635
5719
|
h("h3", { style: Styles.WindowHeader }, title),
|
|
5636
5720
|
alerts.map((alert) => (h("p", { style: Styles.Alert[alert.type] }, resolveText(alert)))),
|
|
5637
|
-
h("form", { onSubmit: ev => {
|
|
5721
|
+
h("form", { onSubmit: (ev) => {
|
|
5638
5722
|
ev.preventDefault();
|
|
5639
5723
|
onSubmit(params);
|
|
5640
|
-
} }, Object.entries(fields).map(([fieldName, { type, label, placeholder }], idx) => (h("label", { style: Styles.Label },
|
|
5724
|
+
} }, Object.entries(fields).map(([fieldName, { type, label, placeholder }], idx) => (h("label", { style: Styles.Label, key: idx },
|
|
5641
5725
|
label ? `${label}: ` : '',
|
|
5642
|
-
h("input", { ref: idx === 0 ? firstFieldRef : undefined, type: type, name: fieldName, autoComplete: "on", style: Styles.Input, autoFocus: true, placeholder: placeholder, value: params[fieldName] || '', onInput: (ev) => {
|
|
5726
|
+
h("input", { ref: idx === 0 ? firstFieldRef : undefined, type: type, name: fieldName, autoComplete: "on", style: Styles.Input, autoFocus: true, placeholder: placeholder, value: params[fieldName] || '', onInput: (ev) => {
|
|
5727
|
+
var _a;
|
|
5728
|
+
const value = valueTransformer(type, (_a = ev.target) === null || _a === void 0 ? void 0 : _a['value']);
|
|
5729
|
+
let updatedParams = Object.assign(Object.assign({}, params), { [fieldName]: value });
|
|
5730
|
+
setParams(updatedParams);
|
|
5731
|
+
if (type === 'otp' && (value === null || value === void 0 ? void 0 : value.trim().length) === OTP_LENGTH) {
|
|
5732
|
+
// Auto-submit when OTP is filled in.
|
|
5733
|
+
onSubmit(updatedParams);
|
|
5734
|
+
}
|
|
5735
|
+
} })))))),
|
|
5643
5736
|
h("div", { style: Styles.ButtonsDiv },
|
|
5644
|
-
h(
|
|
5645
|
-
|
|
5737
|
+
h(p$1, null,
|
|
5738
|
+
h("button", { type: "submit", style: Styles.Button, onClick: () => onSubmit(params) }, submitLabel),
|
|
5739
|
+
cancelLabel && (h("button", { style: Styles.Button, onClick: onCancel }, cancelLabel))))));
|
|
5646
5740
|
}
|
|
5647
5741
|
function valueTransformer(type, value) {
|
|
5648
5742
|
switch (type) {
|
|
5649
|
-
case
|
|
5650
|
-
|
|
5651
|
-
|
|
5743
|
+
case 'email':
|
|
5744
|
+
return value.toLowerCase();
|
|
5745
|
+
case 'otp':
|
|
5746
|
+
return value.toUpperCase();
|
|
5747
|
+
default:
|
|
5748
|
+
return value;
|
|
5652
5749
|
}
|
|
5653
5750
|
}
|
|
5654
5751
|
|
|
@@ -5702,11 +5799,20 @@
|
|
|
5702
5799
|
}
|
|
5703
5800
|
};
|
|
5704
5801
|
}
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5802
|
+
|
|
5803
|
+
function associate(factory) {
|
|
5804
|
+
const wm = new WeakMap();
|
|
5805
|
+
return (x) => {
|
|
5806
|
+
let rv = wm.get(x);
|
|
5807
|
+
if (!rv) {
|
|
5808
|
+
rv = factory(x);
|
|
5809
|
+
wm.set(x, rv);
|
|
5810
|
+
}
|
|
5811
|
+
return rv;
|
|
5812
|
+
};
|
|
5813
|
+
}
|
|
5814
|
+
|
|
5815
|
+
const getCurrentUserEmitter = associate((db) => new rxjs.BehaviorSubject(UNAUTHORIZED_USER));
|
|
5710
5816
|
|
|
5711
5817
|
function computeSyncState(db) {
|
|
5712
5818
|
let _prevStatus = db.cloud.webSocketStatus.value;
|
|
@@ -5734,8 +5840,17 @@
|
|
|
5734
5840
|
return rxjs.combineLatest([
|
|
5735
5841
|
lazyWebSocketStatus,
|
|
5736
5842
|
db.syncStateChangedEvent.pipe(startWith({ phase: 'initial' })),
|
|
5843
|
+
getCurrentUserEmitter(db.dx._novip),
|
|
5737
5844
|
userIsReallyActive
|
|
5738
|
-
]).pipe(map(([status, syncState, userIsActive]) => {
|
|
5845
|
+
]).pipe(map(([status, syncState, user, userIsActive]) => {
|
|
5846
|
+
var _a;
|
|
5847
|
+
if (((_a = user.license) === null || _a === void 0 ? void 0 : _a.status) && user.license.status !== 'ok') {
|
|
5848
|
+
return {
|
|
5849
|
+
phase: 'offline',
|
|
5850
|
+
status: 'offline',
|
|
5851
|
+
license: user.license.status
|
|
5852
|
+
};
|
|
5853
|
+
}
|
|
5739
5854
|
let { phase, error, progress } = syncState;
|
|
5740
5855
|
let adjustedStatus = status;
|
|
5741
5856
|
if (phase === 'error') {
|
|
@@ -5768,23 +5883,12 @@
|
|
|
5768
5883
|
error,
|
|
5769
5884
|
progress,
|
|
5770
5885
|
status: isOnline ? adjustedStatus : 'offline',
|
|
5886
|
+
license: 'ok'
|
|
5771
5887
|
};
|
|
5772
5888
|
return retState;
|
|
5773
5889
|
}));
|
|
5774
5890
|
}
|
|
5775
5891
|
|
|
5776
|
-
function associate(factory) {
|
|
5777
|
-
const wm = new WeakMap();
|
|
5778
|
-
return (x) => {
|
|
5779
|
-
let rv = wm.get(x);
|
|
5780
|
-
if (!rv) {
|
|
5781
|
-
rv = factory(x);
|
|
5782
|
-
wm.set(x, rv);
|
|
5783
|
-
}
|
|
5784
|
-
return rv;
|
|
5785
|
-
};
|
|
5786
|
-
}
|
|
5787
|
-
|
|
5788
5892
|
function createSharedValueObservable(o, defaultValue) {
|
|
5789
5893
|
let currentValue = defaultValue;
|
|
5790
5894
|
let shared = rxjs.from(o).pipe(rxjs.map((x) => (currentValue = x)), rxjs.share({ resetOnRefCountZero: () => rxjs.timer(1000) }));
|
|
@@ -5826,8 +5930,6 @@
|
|
|
5826
5930
|
})), {});
|
|
5827
5931
|
});
|
|
5828
5932
|
|
|
5829
|
-
const getCurrentUserEmitter = associate((db) => new rxjs.BehaviorSubject(UNAUTHORIZED_USER));
|
|
5830
|
-
|
|
5831
5933
|
const getInternalAccessControlObservable = associate((db) => {
|
|
5832
5934
|
return createSharedValueObservable(getCurrentUserEmitter(db._novip).pipe(switchMap((currentUser) => Dexie.liveQuery(() => db.transaction('r', 'realms', 'members', () => Promise.all([
|
|
5833
5935
|
db.members.where({ userId: currentUser.userId }).toArray(),
|
|
@@ -6106,7 +6208,7 @@
|
|
|
6106
6208
|
let closed = false;
|
|
6107
6209
|
function throwIfClosed() {
|
|
6108
6210
|
if (closed)
|
|
6109
|
-
throw new
|
|
6211
|
+
throw new Dexie.DatabaseClosedError();
|
|
6110
6212
|
}
|
|
6111
6213
|
dbOnClosed(dexie, () => {
|
|
6112
6214
|
subscriptions.forEach((subscription) => subscription.unsubscribe());
|
|
@@ -6117,7 +6219,7 @@
|
|
|
6117
6219
|
});
|
|
6118
6220
|
const syncComplete = new rxjs.Subject();
|
|
6119
6221
|
dexie.cloud = {
|
|
6120
|
-
version: '
|
|
6222
|
+
version: '{version}',
|
|
6121
6223
|
options: Object.assign({}, DEFAULT_OPTIONS),
|
|
6122
6224
|
schema: null,
|
|
6123
6225
|
get currentUserId() {
|
|
@@ -6153,11 +6255,24 @@
|
|
|
6153
6255
|
}
|
|
6154
6256
|
updateSchemaFromOptions(dexie.cloud.schema, dexie.cloud.options);
|
|
6155
6257
|
},
|
|
6258
|
+
logout({ force } = {}) {
|
|
6259
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
6260
|
+
force
|
|
6261
|
+
? yield _logout(DexieCloudDB(dexie), { deleteUnsyncedData: true })
|
|
6262
|
+
: yield logout(DexieCloudDB(dexie));
|
|
6263
|
+
});
|
|
6264
|
+
},
|
|
6156
6265
|
sync({ wait, purpose } = { wait: true, purpose: 'push' }) {
|
|
6266
|
+
var _a;
|
|
6157
6267
|
return __awaiter(this, void 0, void 0, function* () {
|
|
6158
6268
|
if (wait === undefined)
|
|
6159
6269
|
wait = true;
|
|
6160
6270
|
const db = DexieCloudDB(dexie);
|
|
6271
|
+
const licenseStatus = ((_a = db.cloud.currentUser.value.license) === null || _a === void 0 ? void 0 : _a.status) || 'ok';
|
|
6272
|
+
if (licenseStatus !== 'ok') {
|
|
6273
|
+
// Refresh access token to check for updated license
|
|
6274
|
+
yield loadAccessToken(db);
|
|
6275
|
+
}
|
|
6161
6276
|
if (purpose === 'pull') {
|
|
6162
6277
|
const syncState = db.cloud.persistedSyncState.value;
|
|
6163
6278
|
triggerSync(db, purpose);
|
|
@@ -6195,7 +6310,7 @@
|
|
|
6195
6310
|
return permissions(dexie._novip, obj, tableName);
|
|
6196
6311
|
},
|
|
6197
6312
|
};
|
|
6198
|
-
dexie.Version.prototype['_parseStoresSpec'] =
|
|
6313
|
+
dexie.Version.prototype['_parseStoresSpec'] = Dexie.override(dexie.Version.prototype['_parseStoresSpec'], (origFunc) => overrideParseStoresSpec(origFunc, dexie));
|
|
6199
6314
|
dexie.Table.prototype.newId = function ({ colocateWith } = {}) {
|
|
6200
6315
|
const shardKey = colocateWith && colocateWith.substr(colocateWith.length - 3);
|
|
6201
6316
|
return generateKey(dexie.cloud.schema[this.name].idPrefix || '', shardKey);
|
|
@@ -6361,7 +6476,9 @@
|
|
|
6361
6476
|
db.syncStateChangedEvent.next({
|
|
6362
6477
|
phase: 'not-in-sync',
|
|
6363
6478
|
});
|
|
6364
|
-
|
|
6479
|
+
if (!isEagerSyncDisabled(db)) {
|
|
6480
|
+
triggerSync(db, 'push');
|
|
6481
|
+
}
|
|
6365
6482
|
}), rxjs.fromEvent(self, 'offline').subscribe(() => {
|
|
6366
6483
|
console.debug('offline!');
|
|
6367
6484
|
db.syncStateChangedEvent.next({
|
|
@@ -6378,10 +6495,10 @@
|
|
|
6378
6495
|
});
|
|
6379
6496
|
}
|
|
6380
6497
|
}
|
|
6381
|
-
dexieCloud.version = '
|
|
6382
|
-
|
|
6498
|
+
dexieCloud.version = '{version}';
|
|
6499
|
+
Dexie.Cloud = dexieCloud;
|
|
6383
6500
|
|
|
6384
|
-
exports
|
|
6501
|
+
exports.default = dexieCloud;
|
|
6385
6502
|
exports.dexieCloud = dexieCloud;
|
|
6386
6503
|
exports.getTiedObjectId = getTiedObjectId;
|
|
6387
6504
|
exports.getTiedRealmId = getTiedRealmId;
|