dexie-cloud-addon 4.0.0-beta.15 → 4.0.0-beta.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/modern/dexie-cloud-addon.js +96 -36
- package/dist/modern/dexie-cloud-addon.js.map +1 -1
- package/dist/modern/dexie-cloud-addon.min.js +1 -1
- package/dist/modern/dexie-cloud-addon.min.js.map +1 -1
- package/dist/modern/service-worker.js +95 -35
- 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/module-es5/dexie-cloud-addon.js +94 -31
- package/dist/module-es5/dexie-cloud-addon.js.map +1 -1
- package/dist/module-es5/dexie-cloud-addon.min.js +1 -1
- package/dist/module-es5/dexie-cloud-addon.min.js.map +1 -1
- package/dist/types/DexieCloudAPI.d.ts +4 -1
- package/dist/types/DexieCloudEntity.d.ts +8 -0
- package/dist/types/WSObservable.d.ts +1 -0
- package/dist/types/WebSocketStatus.d.ts +1 -0
- package/dist/types/createMyMembersObservable.d.ts +14 -0
- package/dist/types/currentUserObservable.d.ts +3 -0
- package/dist/types/getGlobalRolesObservable.d.ts +5 -0
- package/dist/types/getInvitesObservable.d.ts +1 -1
- package/dist/types/helpers/BroadcastedLocalEvent.d.ts +8 -0
- package/dist/types/helpers/visibleState.d.ts +1 -0
- package/dist/types/permissionsLookup.d.ts +9 -0
- package/dist/types/permissionsLookupObservable.d.ts +14 -0
- package/dist/types/sync/globalizePrivateIds.d.ts +4 -0
- package/dist/types/sync/syncServerToClientOnly.d.ts +3 -0
- package/dist/types/types/CloudConnectionStatus.d.ts +0 -0
- package/dist/types/types/ConnectionStatus.d.ts +0 -0
- package/dist/types/types/LoginState.d.ts +41 -0
- package/dist/types/types/SyncConnectionStatus.d.ts +1 -0
- package/dist/types/types/SyncFlowStatus.d.ts +6 -0
- package/dist/types/types/SyncStatus.d.ts +6 -0
- package/dist/umd/dexie-cloud-addon.js +94 -31
- 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 +95 -35
- 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/dist/umd-modern/dexie-cloud-addon.js +93 -33
- package/dist/umd-modern/dexie-cloud-addon.js.map +1 -1
- package/package.json +2 -2
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* ==========================================================================
|
|
10
10
|
*
|
|
11
|
-
* Version 4.0.0-beta.
|
|
11
|
+
* Version 4.0.0-beta.16, Fri Apr 01 2022
|
|
12
12
|
*
|
|
13
13
|
* https://dexie.org
|
|
14
14
|
*
|
|
@@ -4763,7 +4763,7 @@ async function performInitialSync(db, cloudOptions, cloudSchema) {
|
|
|
4763
4763
|
console.debug("Done initial sync");
|
|
4764
4764
|
}
|
|
4765
4765
|
|
|
4766
|
-
const USER_INACTIVITY_TIMEOUT =
|
|
4766
|
+
const USER_INACTIVITY_TIMEOUT = 180000; // 3 minutes
|
|
4767
4767
|
const INACTIVE_WAIT_TIME = 20000;
|
|
4768
4768
|
// This observable will be emitted to later down....
|
|
4769
4769
|
const userIsActive = new BehaviorSubject(true);
|
|
@@ -4777,9 +4777,13 @@ const userIsActive = new BehaviorSubject(true);
|
|
|
4777
4777
|
// for just a short time.
|
|
4778
4778
|
const userIsReallyActive = new BehaviorSubject(true);
|
|
4779
4779
|
userIsActive
|
|
4780
|
-
.pipe(switchMap((isActive) =>
|
|
4781
|
-
|
|
4782
|
-
|
|
4780
|
+
.pipe(switchMap((isActive) => {
|
|
4781
|
+
//console.debug('SyncStatus: DUBB: isActive changed to', isActive);
|
|
4782
|
+
return isActive
|
|
4783
|
+
? of(true)
|
|
4784
|
+
: of(false).pipe(delay(INACTIVE_WAIT_TIME))
|
|
4785
|
+
;
|
|
4786
|
+
}), distinctUntilChanged())
|
|
4783
4787
|
.subscribe(userIsReallyActive);
|
|
4784
4788
|
//
|
|
4785
4789
|
// First create some corner-stone observables to build the flow on
|
|
@@ -4794,7 +4798,7 @@ const documentBecomesHidden = visibilityStateIsChanged.pipe(filter(() => documen
|
|
|
4794
4798
|
const documentBecomesVisible = visibilityStateIsChanged.pipe(filter(() => document.visibilityState === 'visible'));
|
|
4795
4799
|
// Any of various user-activity-related events happen:
|
|
4796
4800
|
const userDoesSomething = typeof window !== 'undefined'
|
|
4797
|
-
? merge(documentBecomesVisible, fromEvent(window, 'mousemove'), fromEvent(window, 'keydown'), fromEvent(window, 'wheel'), fromEvent(window, 'touchmove'))
|
|
4801
|
+
? merge(documentBecomesVisible, fromEvent(window, 'mousedown'), fromEvent(window, 'mousemove'), fromEvent(window, 'keydown'), fromEvent(window, 'wheel'), fromEvent(window, 'touchmove'))
|
|
4798
4802
|
: of({});
|
|
4799
4803
|
if (typeof document !== 'undefined') {
|
|
4800
4804
|
//
|
|
@@ -4845,6 +4849,7 @@ class WSConnection extends Subscription$1 {
|
|
|
4845
4849
|
constructor(databaseUrl, rev, realmSetHash, clientIdentity, token, tokenExpiration, subscriber, messageProducer, webSocketStatus) {
|
|
4846
4850
|
super(() => this.teardown());
|
|
4847
4851
|
this.id = ++counter;
|
|
4852
|
+
this.reconnecting = false;
|
|
4848
4853
|
console.debug('New WebSocket Connection', this.id, token ? 'authorized' : 'unauthorized');
|
|
4849
4854
|
this.databaseUrl = databaseUrl;
|
|
4850
4855
|
this.rev = rev;
|
|
@@ -4864,7 +4869,7 @@ class WSConnection extends Subscription$1 {
|
|
|
4864
4869
|
this.disconnect();
|
|
4865
4870
|
}
|
|
4866
4871
|
disconnect() {
|
|
4867
|
-
this.webSocketStatus.next(
|
|
4872
|
+
this.webSocketStatus.next('disconnected');
|
|
4868
4873
|
if (this.pinger) {
|
|
4869
4874
|
clearInterval(this.pinger);
|
|
4870
4875
|
this.pinger = null;
|
|
@@ -4882,11 +4887,18 @@ class WSConnection extends Subscription$1 {
|
|
|
4882
4887
|
}
|
|
4883
4888
|
}
|
|
4884
4889
|
reconnect() {
|
|
4885
|
-
this.
|
|
4886
|
-
|
|
4890
|
+
if (this.reconnecting)
|
|
4891
|
+
return;
|
|
4892
|
+
this.reconnecting = true;
|
|
4893
|
+
try {
|
|
4894
|
+
this.disconnect();
|
|
4895
|
+
}
|
|
4896
|
+
catch { }
|
|
4897
|
+
this.connect()
|
|
4898
|
+
.catch(() => { })
|
|
4899
|
+
.then(() => (this.reconnecting = false)); // finally()
|
|
4887
4900
|
}
|
|
4888
4901
|
async connect() {
|
|
4889
|
-
this.webSocketStatus.next("connecting");
|
|
4890
4902
|
this.lastServerActivity = new Date();
|
|
4891
4903
|
if (this.pauseUntil && this.pauseUntil > new Date()) {
|
|
4892
4904
|
console.debug('WS not reconnecting just yet', {
|
|
@@ -4901,12 +4913,14 @@ class WSConnection extends Subscription$1 {
|
|
|
4901
4913
|
if (!this.databaseUrl)
|
|
4902
4914
|
throw new Error(`Cannot connect without a database URL`);
|
|
4903
4915
|
if (this.closed) {
|
|
4916
|
+
//console.debug('SyncStatus: DUBB: Ooops it was closed!');
|
|
4904
4917
|
return;
|
|
4905
4918
|
}
|
|
4906
4919
|
if (this.tokenExpiration && this.tokenExpiration < new Date()) {
|
|
4907
4920
|
this.subscriber.error(new TokenExpiredError()); // Will be handled in connectWebSocket.ts.
|
|
4908
4921
|
return;
|
|
4909
4922
|
}
|
|
4923
|
+
this.webSocketStatus.next('connecting');
|
|
4910
4924
|
this.pinger = setInterval(async () => {
|
|
4911
4925
|
if (this.closed) {
|
|
4912
4926
|
console.debug('pinger check', this.id, 'CLOSED.');
|
|
@@ -4953,7 +4967,7 @@ class WSConnection extends Subscription$1 {
|
|
|
4953
4967
|
const searchParams = new URLSearchParams();
|
|
4954
4968
|
if (this.subscriber.closed)
|
|
4955
4969
|
return;
|
|
4956
|
-
searchParams.set('v',
|
|
4970
|
+
searchParams.set('v', '2');
|
|
4957
4971
|
searchParams.set('rev', this.rev);
|
|
4958
4972
|
searchParams.set('realmsHash', this.realmSetHash);
|
|
4959
4973
|
searchParams.set('clientId', this.clientIdentity);
|
|
@@ -4992,23 +5006,30 @@ class WSConnection extends Subscription$1 {
|
|
|
4992
5006
|
}
|
|
4993
5007
|
};
|
|
4994
5008
|
try {
|
|
5009
|
+
let everConnected = false;
|
|
4995
5010
|
await new Promise((resolve, reject) => {
|
|
4996
5011
|
ws.onopen = (event) => {
|
|
4997
5012
|
console.debug('dexie-cloud WebSocket onopen');
|
|
5013
|
+
everConnected = true;
|
|
4998
5014
|
resolve(null);
|
|
4999
5015
|
};
|
|
5000
5016
|
ws.onerror = (event) => {
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
5017
|
+
if (!everConnected) {
|
|
5018
|
+
const error = event.error || new Error('WebSocket Error');
|
|
5019
|
+
this.subscriber.error(error);
|
|
5020
|
+
this.webSocketStatus.next('error');
|
|
5021
|
+
reject(error);
|
|
5022
|
+
}
|
|
5023
|
+
else {
|
|
5024
|
+
this.reconnect();
|
|
5025
|
+
}
|
|
5006
5026
|
};
|
|
5007
5027
|
});
|
|
5008
|
-
this.messageProducerSubscription = this.messageProducer.subscribe(msg => {
|
|
5028
|
+
this.messageProducerSubscription = this.messageProducer.subscribe((msg) => {
|
|
5009
5029
|
if (!this.closed) {
|
|
5010
|
-
if (msg.type === 'ready' &&
|
|
5011
|
-
this.webSocketStatus.
|
|
5030
|
+
if (msg.type === 'ready' &&
|
|
5031
|
+
this.webSocketStatus.value !== 'connected') {
|
|
5032
|
+
this.webSocketStatus.next('connected');
|
|
5012
5033
|
}
|
|
5013
5034
|
this.ws?.send(TSON.stringify(msg));
|
|
5014
5035
|
}
|
|
@@ -5045,9 +5066,9 @@ function connectWebSocket(db) {
|
|
|
5045
5066
|
rev: syncState.serverRevision,
|
|
5046
5067
|
})));
|
|
5047
5068
|
function createObservable() {
|
|
5048
|
-
return db.cloud.persistedSyncState.pipe(filter(syncState => syncState?.serverRevision), // Don't connect before there's no initial sync performed.
|
|
5069
|
+
return db.cloud.persistedSyncState.pipe(filter((syncState) => syncState?.serverRevision), // Don't connect before there's no initial sync performed.
|
|
5049
5070
|
take(1), // Don't continue waking up whenever syncState change
|
|
5050
|
-
switchMap((syncState) => db.cloud.currentUser.pipe(map(userLogin => [userLogin, syncState]))), switchMap(([userLogin, syncState]) => userIsReallyActive.pipe(map((isActive) => [isActive ? userLogin : null, syncState]))), switchMap(async ([userLogin, syncState]) => [userLogin, await computeRealmSetHash(syncState)]), switchMap(([userLogin, realmSetHash]) =>
|
|
5071
|
+
switchMap((syncState) => db.cloud.currentUser.pipe(map((userLogin) => [userLogin, syncState]))), switchMap(([userLogin, syncState]) => userIsReallyActive.pipe(map((isActive) => [isActive ? userLogin : null, syncState]))), switchMap(async ([userLogin, syncState]) => [userLogin, await computeRealmSetHash(syncState)]), switchMap(([userLogin, realmSetHash]) =>
|
|
5051
5072
|
// Let server end query changes from last entry of same client-ID and forward.
|
|
5052
5073
|
// If no new entries, server won't bother the client. If new entries, server sends only those
|
|
5053
5074
|
// and the baseRev of the last from same client-ID.
|
|
@@ -5070,7 +5091,10 @@ function connectWebSocket(db) {
|
|
|
5070
5091
|
else {
|
|
5071
5092
|
return throwError(error);
|
|
5072
5093
|
}
|
|
5073
|
-
}), catchError((error) =>
|
|
5094
|
+
}), catchError((error) => {
|
|
5095
|
+
db.cloud.webSocketStatus.next("error");
|
|
5096
|
+
return from$1(waitAndReconnectWhenUserDoesSomething(error)).pipe(switchMap(() => createObservable()));
|
|
5097
|
+
}));
|
|
5074
5098
|
}
|
|
5075
5099
|
return createObservable().subscribe((msg) => {
|
|
5076
5100
|
if (msg) {
|
|
@@ -5494,6 +5518,21 @@ function createSharedValueObservable(o, defaultValue) {
|
|
|
5494
5518
|
return rv;
|
|
5495
5519
|
}
|
|
5496
5520
|
|
|
5521
|
+
const getGlobalRolesObservable = associate((db) => {
|
|
5522
|
+
return createSharedValueObservable(liveQuery(() => db.roles
|
|
5523
|
+
.where({ realmId: 'rlm-public' })
|
|
5524
|
+
.toArray()
|
|
5525
|
+
.then((roles) => {
|
|
5526
|
+
const rv = {};
|
|
5527
|
+
for (const role of roles
|
|
5528
|
+
.slice()
|
|
5529
|
+
.sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0))) {
|
|
5530
|
+
rv[role.name] = role;
|
|
5531
|
+
}
|
|
5532
|
+
return rv;
|
|
5533
|
+
})), {});
|
|
5534
|
+
});
|
|
5535
|
+
|
|
5497
5536
|
const getCurrentUserEmitter = associate((db) => new BehaviorSubject(UNAUTHORIZED_USER));
|
|
5498
5537
|
|
|
5499
5538
|
const getInternalAccessControlObservable = associate((db) => {
|
|
@@ -5595,18 +5634,38 @@ function mergePermissions(...permissions) {
|
|
|
5595
5634
|
}
|
|
5596
5635
|
|
|
5597
5636
|
const getPermissionsLookupObservable = associate((db) => {
|
|
5598
|
-
const o =
|
|
5599
|
-
|
|
5637
|
+
const o = createSharedValueObservable(combineLatest([
|
|
5638
|
+
getInternalAccessControlObservable(db._novip),
|
|
5639
|
+
getGlobalRolesObservable(db._novip),
|
|
5640
|
+
]).pipe(map(([{ selfMembers, realms, userId }, globalRoles]) => ({
|
|
5641
|
+
selfMembers,
|
|
5642
|
+
realms,
|
|
5643
|
+
userId,
|
|
5644
|
+
globalRoles,
|
|
5645
|
+
}))), {
|
|
5646
|
+
selfMembers: [],
|
|
5647
|
+
realms: [],
|
|
5648
|
+
userId: UNAUTHORIZED_USER.userId,
|
|
5649
|
+
globalRoles: {},
|
|
5650
|
+
});
|
|
5651
|
+
return mapValueObservable(o, ({ selfMembers, realms, userId, globalRoles }) => {
|
|
5600
5652
|
const rv = realms
|
|
5601
|
-
.map((realm) =>
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
5609
|
-
|
|
5653
|
+
.map((realm) => {
|
|
5654
|
+
const selfRealmMembers = selfMembers.filter((m) => m.realmId === realm.realmId);
|
|
5655
|
+
const directPermissionSets = selfRealmMembers
|
|
5656
|
+
.map((m) => m.permissions)
|
|
5657
|
+
.filter((p) => p);
|
|
5658
|
+
const rolePermissionSets = flatten(selfRealmMembers.map((m) => m.roles).filter((roleName) => roleName))
|
|
5659
|
+
.map((role) => globalRoles[role])
|
|
5660
|
+
.filter((role) => role)
|
|
5661
|
+
.map((role) => role.permissions);
|
|
5662
|
+
return {
|
|
5663
|
+
...realm,
|
|
5664
|
+
permissions: realm.owner === userId
|
|
5665
|
+
? { manage: '*' }
|
|
5666
|
+
: mergePermissions(...directPermissionSets, ...rolePermissionSets),
|
|
5667
|
+
};
|
|
5668
|
+
})
|
|
5610
5669
|
.reduce((p, c) => ({ ...p, [c.realmId]: c }), {
|
|
5611
5670
|
[userId]: {
|
|
5612
5671
|
realmId: userId,
|
|
@@ -5690,7 +5749,7 @@ function permissions(dexie, obj, tableName) {
|
|
|
5690
5749
|
const realm = permissionsLookup[realmId || dexie.cloud.currentUserId];
|
|
5691
5750
|
if (!realm)
|
|
5692
5751
|
return new PermissionChecker({}, tableName, !owner || owner === dexie.cloud.currentUserId);
|
|
5693
|
-
return new PermissionChecker(realm.permissions, tableName,
|
|
5752
|
+
return new PermissionChecker(realm.permissions, tableName, realmId === dexie.cloud.currentUserId || owner === dexie.cloud.currentUserId);
|
|
5694
5753
|
};
|
|
5695
5754
|
const o = source.pipe(map(mapper));
|
|
5696
5755
|
o.getValue = () => mapper(source.getValue());
|
|
@@ -5753,7 +5812,7 @@ function dexieCloud(dexie) {
|
|
|
5753
5812
|
currentUserEmitter.next(UNAUTHORIZED_USER);
|
|
5754
5813
|
});
|
|
5755
5814
|
dexie.cloud = {
|
|
5756
|
-
version: '4.0.0-beta.
|
|
5815
|
+
version: '4.0.0-beta.16',
|
|
5757
5816
|
options: { ...DEFAULT_OPTIONS },
|
|
5758
5817
|
schema: null,
|
|
5759
5818
|
serverState: null,
|
|
@@ -5774,6 +5833,7 @@ function dexieCloud(dexie) {
|
|
|
5774
5833
|
await login(db, hint);
|
|
5775
5834
|
},
|
|
5776
5835
|
invites: getInvitesObservable(dexie),
|
|
5836
|
+
roles: getGlobalRolesObservable(dexie),
|
|
5777
5837
|
configure(options) {
|
|
5778
5838
|
options = dexie.cloud.options = { ...dexie.cloud.options, ...options };
|
|
5779
5839
|
configuredProgramatically = true;
|
|
@@ -5994,7 +6054,7 @@ function dexieCloud(dexie) {
|
|
|
5994
6054
|
}
|
|
5995
6055
|
}
|
|
5996
6056
|
}
|
|
5997
|
-
dexieCloud.version = '4.0.0-beta.
|
|
6057
|
+
dexieCloud.version = '4.0.0-beta.16';
|
|
5998
6058
|
Dexie.Cloud = dexieCloud;
|
|
5999
6059
|
|
|
6000
6060
|
export { dexieCloud as default, dexieCloud, getTiedObjectId, getTiedRealmId };
|