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
|
@@ -4752,7 +4752,7 @@
|
|
|
4752
4752
|
console.debug("Done initial sync");
|
|
4753
4753
|
}
|
|
4754
4754
|
|
|
4755
|
-
const USER_INACTIVITY_TIMEOUT =
|
|
4755
|
+
const USER_INACTIVITY_TIMEOUT = 180000; // 3 minutes
|
|
4756
4756
|
const INACTIVE_WAIT_TIME = 20000;
|
|
4757
4757
|
// This observable will be emitted to later down....
|
|
4758
4758
|
const userIsActive = new rxjs.BehaviorSubject(true);
|
|
@@ -4766,9 +4766,13 @@
|
|
|
4766
4766
|
// for just a short time.
|
|
4767
4767
|
const userIsReallyActive = new rxjs.BehaviorSubject(true);
|
|
4768
4768
|
userIsActive
|
|
4769
|
-
.pipe(switchMap((isActive) =>
|
|
4770
|
-
|
|
4771
|
-
|
|
4769
|
+
.pipe(switchMap((isActive) => {
|
|
4770
|
+
//console.debug('SyncStatus: DUBB: isActive changed to', isActive);
|
|
4771
|
+
return isActive
|
|
4772
|
+
? rxjs.of(true)
|
|
4773
|
+
: rxjs.of(false).pipe(delay(INACTIVE_WAIT_TIME))
|
|
4774
|
+
;
|
|
4775
|
+
}), distinctUntilChanged())
|
|
4772
4776
|
.subscribe(userIsReallyActive);
|
|
4773
4777
|
//
|
|
4774
4778
|
// First create some corner-stone observables to build the flow on
|
|
@@ -4783,7 +4787,7 @@
|
|
|
4783
4787
|
const documentBecomesVisible = visibilityStateIsChanged.pipe(filter(() => document.visibilityState === 'visible'));
|
|
4784
4788
|
// Any of various user-activity-related events happen:
|
|
4785
4789
|
const userDoesSomething = typeof window !== 'undefined'
|
|
4786
|
-
? rxjs.merge(documentBecomesVisible, rxjs.fromEvent(window, 'mousemove'), rxjs.fromEvent(window, 'keydown'), rxjs.fromEvent(window, 'wheel'), rxjs.fromEvent(window, 'touchmove'))
|
|
4790
|
+
? rxjs.merge(documentBecomesVisible, rxjs.fromEvent(window, 'mousedown'), rxjs.fromEvent(window, 'mousemove'), rxjs.fromEvent(window, 'keydown'), rxjs.fromEvent(window, 'wheel'), rxjs.fromEvent(window, 'touchmove'))
|
|
4787
4791
|
: rxjs.of({});
|
|
4788
4792
|
if (typeof document !== 'undefined') {
|
|
4789
4793
|
//
|
|
@@ -4834,6 +4838,7 @@
|
|
|
4834
4838
|
constructor(databaseUrl, rev, realmSetHash, clientIdentity, token, tokenExpiration, subscriber, messageProducer, webSocketStatus) {
|
|
4835
4839
|
super(() => this.teardown());
|
|
4836
4840
|
this.id = ++counter;
|
|
4841
|
+
this.reconnecting = false;
|
|
4837
4842
|
console.debug('New WebSocket Connection', this.id, token ? 'authorized' : 'unauthorized');
|
|
4838
4843
|
this.databaseUrl = databaseUrl;
|
|
4839
4844
|
this.rev = rev;
|
|
@@ -4853,7 +4858,7 @@
|
|
|
4853
4858
|
this.disconnect();
|
|
4854
4859
|
}
|
|
4855
4860
|
disconnect() {
|
|
4856
|
-
this.webSocketStatus.next(
|
|
4861
|
+
this.webSocketStatus.next('disconnected');
|
|
4857
4862
|
if (this.pinger) {
|
|
4858
4863
|
clearInterval(this.pinger);
|
|
4859
4864
|
this.pinger = null;
|
|
@@ -4871,11 +4876,18 @@
|
|
|
4871
4876
|
}
|
|
4872
4877
|
}
|
|
4873
4878
|
reconnect() {
|
|
4874
|
-
this.
|
|
4875
|
-
|
|
4879
|
+
if (this.reconnecting)
|
|
4880
|
+
return;
|
|
4881
|
+
this.reconnecting = true;
|
|
4882
|
+
try {
|
|
4883
|
+
this.disconnect();
|
|
4884
|
+
}
|
|
4885
|
+
catch { }
|
|
4886
|
+
this.connect()
|
|
4887
|
+
.catch(() => { })
|
|
4888
|
+
.then(() => (this.reconnecting = false)); // finally()
|
|
4876
4889
|
}
|
|
4877
4890
|
async connect() {
|
|
4878
|
-
this.webSocketStatus.next("connecting");
|
|
4879
4891
|
this.lastServerActivity = new Date();
|
|
4880
4892
|
if (this.pauseUntil && this.pauseUntil > new Date()) {
|
|
4881
4893
|
console.debug('WS not reconnecting just yet', {
|
|
@@ -4890,12 +4902,14 @@
|
|
|
4890
4902
|
if (!this.databaseUrl)
|
|
4891
4903
|
throw new Error(`Cannot connect without a database URL`);
|
|
4892
4904
|
if (this.closed) {
|
|
4905
|
+
//console.debug('SyncStatus: DUBB: Ooops it was closed!');
|
|
4893
4906
|
return;
|
|
4894
4907
|
}
|
|
4895
4908
|
if (this.tokenExpiration && this.tokenExpiration < new Date()) {
|
|
4896
4909
|
this.subscriber.error(new TokenExpiredError()); // Will be handled in connectWebSocket.ts.
|
|
4897
4910
|
return;
|
|
4898
4911
|
}
|
|
4912
|
+
this.webSocketStatus.next('connecting');
|
|
4899
4913
|
this.pinger = setInterval(async () => {
|
|
4900
4914
|
if (this.closed) {
|
|
4901
4915
|
console.debug('pinger check', this.id, 'CLOSED.');
|
|
@@ -4942,7 +4956,7 @@
|
|
|
4942
4956
|
const searchParams = new URLSearchParams();
|
|
4943
4957
|
if (this.subscriber.closed)
|
|
4944
4958
|
return;
|
|
4945
|
-
searchParams.set('v',
|
|
4959
|
+
searchParams.set('v', '2');
|
|
4946
4960
|
searchParams.set('rev', this.rev);
|
|
4947
4961
|
searchParams.set('realmsHash', this.realmSetHash);
|
|
4948
4962
|
searchParams.set('clientId', this.clientIdentity);
|
|
@@ -4981,23 +4995,30 @@
|
|
|
4981
4995
|
}
|
|
4982
4996
|
};
|
|
4983
4997
|
try {
|
|
4998
|
+
let everConnected = false;
|
|
4984
4999
|
await new Promise((resolve, reject) => {
|
|
4985
5000
|
ws.onopen = (event) => {
|
|
4986
5001
|
console.debug('dexie-cloud WebSocket onopen');
|
|
5002
|
+
everConnected = true;
|
|
4987
5003
|
resolve(null);
|
|
4988
5004
|
};
|
|
4989
5005
|
ws.onerror = (event) => {
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
5006
|
+
if (!everConnected) {
|
|
5007
|
+
const error = event.error || new Error('WebSocket Error');
|
|
5008
|
+
this.subscriber.error(error);
|
|
5009
|
+
this.webSocketStatus.next('error');
|
|
5010
|
+
reject(error);
|
|
5011
|
+
}
|
|
5012
|
+
else {
|
|
5013
|
+
this.reconnect();
|
|
5014
|
+
}
|
|
4995
5015
|
};
|
|
4996
5016
|
});
|
|
4997
|
-
this.messageProducerSubscription = this.messageProducer.subscribe(msg => {
|
|
5017
|
+
this.messageProducerSubscription = this.messageProducer.subscribe((msg) => {
|
|
4998
5018
|
if (!this.closed) {
|
|
4999
|
-
if (msg.type === 'ready' &&
|
|
5000
|
-
this.webSocketStatus.
|
|
5019
|
+
if (msg.type === 'ready' &&
|
|
5020
|
+
this.webSocketStatus.value !== 'connected') {
|
|
5021
|
+
this.webSocketStatus.next('connected');
|
|
5001
5022
|
}
|
|
5002
5023
|
this.ws?.send(TSON.stringify(msg));
|
|
5003
5024
|
}
|
|
@@ -5034,9 +5055,9 @@
|
|
|
5034
5055
|
rev: syncState.serverRevision,
|
|
5035
5056
|
})));
|
|
5036
5057
|
function createObservable() {
|
|
5037
|
-
return db.cloud.persistedSyncState.pipe(filter(syncState => syncState?.serverRevision), // Don't connect before there's no initial sync performed.
|
|
5058
|
+
return db.cloud.persistedSyncState.pipe(filter((syncState) => syncState?.serverRevision), // Don't connect before there's no initial sync performed.
|
|
5038
5059
|
take(1), // Don't continue waking up whenever syncState change
|
|
5039
|
-
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]) =>
|
|
5060
|
+
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]) =>
|
|
5040
5061
|
// Let server end query changes from last entry of same client-ID and forward.
|
|
5041
5062
|
// If no new entries, server won't bother the client. If new entries, server sends only those
|
|
5042
5063
|
// and the baseRev of the last from same client-ID.
|
|
@@ -5059,7 +5080,10 @@
|
|
|
5059
5080
|
else {
|
|
5060
5081
|
return rxjs.throwError(error);
|
|
5061
5082
|
}
|
|
5062
|
-
}), catchError((error) =>
|
|
5083
|
+
}), catchError((error) => {
|
|
5084
|
+
db.cloud.webSocketStatus.next("error");
|
|
5085
|
+
return rxjs.from(waitAndReconnectWhenUserDoesSomething(error)).pipe(switchMap(() => createObservable()));
|
|
5086
|
+
}));
|
|
5063
5087
|
}
|
|
5064
5088
|
return createObservable().subscribe((msg) => {
|
|
5065
5089
|
if (msg) {
|
|
@@ -5483,6 +5507,21 @@
|
|
|
5483
5507
|
return rv;
|
|
5484
5508
|
}
|
|
5485
5509
|
|
|
5510
|
+
const getGlobalRolesObservable = associate((db) => {
|
|
5511
|
+
return createSharedValueObservable(Dexie.liveQuery(() => db.roles
|
|
5512
|
+
.where({ realmId: 'rlm-public' })
|
|
5513
|
+
.toArray()
|
|
5514
|
+
.then((roles) => {
|
|
5515
|
+
const rv = {};
|
|
5516
|
+
for (const role of roles
|
|
5517
|
+
.slice()
|
|
5518
|
+
.sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0))) {
|
|
5519
|
+
rv[role.name] = role;
|
|
5520
|
+
}
|
|
5521
|
+
return rv;
|
|
5522
|
+
})), {});
|
|
5523
|
+
});
|
|
5524
|
+
|
|
5486
5525
|
const getCurrentUserEmitter = associate((db) => new rxjs.BehaviorSubject(UNAUTHORIZED_USER));
|
|
5487
5526
|
|
|
5488
5527
|
const getInternalAccessControlObservable = associate((db) => {
|
|
@@ -5584,18 +5623,38 @@
|
|
|
5584
5623
|
}
|
|
5585
5624
|
|
|
5586
5625
|
const getPermissionsLookupObservable = associate((db) => {
|
|
5587
|
-
const o =
|
|
5588
|
-
|
|
5626
|
+
const o = createSharedValueObservable(rxjs.combineLatest([
|
|
5627
|
+
getInternalAccessControlObservable(db._novip),
|
|
5628
|
+
getGlobalRolesObservable(db._novip),
|
|
5629
|
+
]).pipe(map(([{ selfMembers, realms, userId }, globalRoles]) => ({
|
|
5630
|
+
selfMembers,
|
|
5631
|
+
realms,
|
|
5632
|
+
userId,
|
|
5633
|
+
globalRoles,
|
|
5634
|
+
}))), {
|
|
5635
|
+
selfMembers: [],
|
|
5636
|
+
realms: [],
|
|
5637
|
+
userId: UNAUTHORIZED_USER.userId,
|
|
5638
|
+
globalRoles: {},
|
|
5639
|
+
});
|
|
5640
|
+
return mapValueObservable(o, ({ selfMembers, realms, userId, globalRoles }) => {
|
|
5589
5641
|
const rv = realms
|
|
5590
|
-
.map((realm) =>
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5642
|
+
.map((realm) => {
|
|
5643
|
+
const selfRealmMembers = selfMembers.filter((m) => m.realmId === realm.realmId);
|
|
5644
|
+
const directPermissionSets = selfRealmMembers
|
|
5645
|
+
.map((m) => m.permissions)
|
|
5646
|
+
.filter((p) => p);
|
|
5647
|
+
const rolePermissionSets = flatten(selfRealmMembers.map((m) => m.roles).filter((roleName) => roleName))
|
|
5648
|
+
.map((role) => globalRoles[role])
|
|
5649
|
+
.filter((role) => role)
|
|
5650
|
+
.map((role) => role.permissions);
|
|
5651
|
+
return {
|
|
5652
|
+
...realm,
|
|
5653
|
+
permissions: realm.owner === userId
|
|
5654
|
+
? { manage: '*' }
|
|
5655
|
+
: mergePermissions(...directPermissionSets, ...rolePermissionSets),
|
|
5656
|
+
};
|
|
5657
|
+
})
|
|
5599
5658
|
.reduce((p, c) => ({ ...p, [c.realmId]: c }), {
|
|
5600
5659
|
[userId]: {
|
|
5601
5660
|
realmId: userId,
|
|
@@ -5679,7 +5738,7 @@
|
|
|
5679
5738
|
const realm = permissionsLookup[realmId || dexie.cloud.currentUserId];
|
|
5680
5739
|
if (!realm)
|
|
5681
5740
|
return new PermissionChecker({}, tableName, !owner || owner === dexie.cloud.currentUserId);
|
|
5682
|
-
return new PermissionChecker(realm.permissions, tableName,
|
|
5741
|
+
return new PermissionChecker(realm.permissions, tableName, realmId === dexie.cloud.currentUserId || owner === dexie.cloud.currentUserId);
|
|
5683
5742
|
};
|
|
5684
5743
|
const o = source.pipe(map(mapper));
|
|
5685
5744
|
o.getValue = () => mapper(source.getValue());
|
|
@@ -5735,7 +5794,7 @@
|
|
|
5735
5794
|
currentUserEmitter.next(UNAUTHORIZED_USER);
|
|
5736
5795
|
});
|
|
5737
5796
|
dexie.cloud = {
|
|
5738
|
-
version: '4.0.0-beta.
|
|
5797
|
+
version: '4.0.0-beta.16',
|
|
5739
5798
|
options: { ...DEFAULT_OPTIONS },
|
|
5740
5799
|
schema: null,
|
|
5741
5800
|
serverState: null,
|
|
@@ -5756,6 +5815,7 @@
|
|
|
5756
5815
|
await login(db, hint);
|
|
5757
5816
|
},
|
|
5758
5817
|
invites: getInvitesObservable(dexie),
|
|
5818
|
+
roles: getGlobalRolesObservable(dexie),
|
|
5759
5819
|
configure(options) {
|
|
5760
5820
|
options = dexie.cloud.options = { ...dexie.cloud.options, ...options };
|
|
5761
5821
|
configuredProgramatically = true;
|
|
@@ -5976,7 +6036,7 @@
|
|
|
5976
6036
|
}
|
|
5977
6037
|
}
|
|
5978
6038
|
}
|
|
5979
|
-
dexieCloud.version = '4.0.0-beta.
|
|
6039
|
+
dexieCloud.version = '4.0.0-beta.16';
|
|
5980
6040
|
Dexie__default["default"].Cloud = dexieCloud;
|
|
5981
6041
|
|
|
5982
6042
|
// In case the SW lives for a while, let it reuse already opened connections:
|