dexie-cloud-addon 4.0.0-beta.14 → 4.0.0-beta.17
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 +194 -138
- 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 +193 -137
- 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 +231 -180
- 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/WSObservable.d.ts +1 -0
- package/dist/types/getGlobalRolesObservable.d.ts +5 -0
- package/dist/types/getInvitesObservable.d.ts +1 -1
- package/dist/umd/dexie-cloud-addon.js +231 -180
- 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 +192 -136
- 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 +190 -134
- package/dist/umd-modern/dexie-cloud-addon.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DexieCloudOptions } from './DexieCloudOptions';
|
|
2
|
-
import { DexieCloudSchema } from 'dexie-cloud-common';
|
|
2
|
+
import { DBRealmRole, DexieCloudSchema } from 'dexie-cloud-common';
|
|
3
3
|
import { UserLogin } from './db/entities/UserLogin';
|
|
4
4
|
import * as Rx from 'rxjs';
|
|
5
5
|
import { PersistedSyncState } from './db/entities/PersistedSyncState';
|
|
@@ -22,6 +22,9 @@ export interface DexieCloudAPI {
|
|
|
22
22
|
persistedSyncState: Rx.BehaviorSubject<PersistedSyncState | undefined>;
|
|
23
23
|
userInteraction: Rx.BehaviorSubject<DXCUserInteraction | undefined>;
|
|
24
24
|
invites: Rx.Observable<Invite[]>;
|
|
25
|
+
roles: Rx.Observable<{
|
|
26
|
+
[roleName: string]: DBRealmRole;
|
|
27
|
+
}>;
|
|
25
28
|
usingServiceWorker?: boolean;
|
|
26
29
|
/** Login using Dexie Cloud OTP or Demo user.
|
|
27
30
|
*
|
|
@@ -61,6 +61,7 @@ export declare class WSConnection extends Subscription {
|
|
|
61
61
|
constructor(databaseUrl: string, rev: string, realmSetHash: string, clientIdentity: string, token: string | undefined, tokenExpiration: Date | undefined, subscriber: Subscriber<WSConnectionMsg>, messageProducer: Observable<WSClientToServerMsg>, webSocketStatus: BehaviorSubject<DXCWebSocketStatus>);
|
|
62
62
|
private teardown;
|
|
63
63
|
private disconnect;
|
|
64
|
+
reconnecting: boolean;
|
|
64
65
|
reconnect(): void;
|
|
65
66
|
connect(): Promise<void>;
|
|
66
67
|
}
|
|
@@ -4,7 +4,7 @@ export declare const getInvitesObservable: (x: Dexie) => import("./mapValueObser
|
|
|
4
4
|
realm: import("dexie-cloud-common").DBRealm & {
|
|
5
5
|
permissions: import("dexie-cloud-common").DBPermissionSet;
|
|
6
6
|
};
|
|
7
|
-
id
|
|
7
|
+
id: string;
|
|
8
8
|
userId?: string | undefined;
|
|
9
9
|
email?: string | undefined;
|
|
10
10
|
name?: string | undefined;
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
*
|
|
109
109
|
* ==========================================================================
|
|
110
110
|
*
|
|
111
|
-
* Version 4.0.0-beta.
|
|
111
|
+
* Version 4.0.0-beta.17, Fri Apr 08 2022
|
|
112
112
|
*
|
|
113
113
|
* https://dexie.org
|
|
114
114
|
*
|
|
@@ -5303,166 +5303,22 @@
|
|
|
5303
5303
|
return rv;
|
|
5304
5304
|
};
|
|
5305
5305
|
}
|
|
5306
|
-
var SECONDS = 1000;
|
|
5307
|
-
var MINUTES = 60 * SECONDS;
|
|
5308
|
-
var myId = randomString(16);
|
|
5309
|
-
var GUARDED_JOB_HEARTBEAT = 1 * SECONDS;
|
|
5310
|
-
var GUARDED_JOB_TIMEOUT = 1 * MINUTES;
|
|
5311
|
-
function performGuardedJob(db, jobName, jobsTableName, job, _e) {
|
|
5312
|
-
var _f = _e === void 0 ? {} : _e, awaitRemoteJob = _f.awaitRemoteJob;
|
|
5313
|
-
return __awaiter$1(this, void 0, void 0, function () {
|
|
5314
|
-
function aquireLock() {
|
|
5315
|
-
return __awaiter$1(this, void 0, void 0, function () {
|
|
5316
|
-
var gotTheLock, jobDoneObservable, err_1;
|
|
5317
|
-
var _this_1 = this;
|
|
5318
|
-
return __generator$1(this, function (_e) {
|
|
5319
|
-
switch (_e.label) {
|
|
5320
|
-
case 0: return [4 /*yield*/, db.transaction('rw!', jobsTableName, function () { return __awaiter$1(_this_1, void 0, void 0, function () {
|
|
5321
|
-
var currentWork;
|
|
5322
|
-
return __generator$1(this, function (_e) {
|
|
5323
|
-
switch (_e.label) {
|
|
5324
|
-
case 0: return [4 /*yield*/, jobsTable.get(jobName)];
|
|
5325
|
-
case 1:
|
|
5326
|
-
currentWork = _e.sent();
|
|
5327
|
-
if (!!currentWork) return [3 /*break*/, 3];
|
|
5328
|
-
// No one else is working. Let's record that we are.
|
|
5329
|
-
return [4 /*yield*/, jobsTable.add({
|
|
5330
|
-
nodeId: myId,
|
|
5331
|
-
started: new Date(),
|
|
5332
|
-
heartbeat: new Date()
|
|
5333
|
-
}, jobName)];
|
|
5334
|
-
case 2:
|
|
5335
|
-
// No one else is working. Let's record that we are.
|
|
5336
|
-
_e.sent();
|
|
5337
|
-
return [2 /*return*/, true];
|
|
5338
|
-
case 3:
|
|
5339
|
-
if (!(currentWork.heartbeat.getTime() <
|
|
5340
|
-
Date.now() - GUARDED_JOB_TIMEOUT)) return [3 /*break*/, 5];
|
|
5341
|
-
console.warn("Latest ".concat(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!");
|
|
5342
|
-
// Now, take over!
|
|
5343
|
-
return [4 /*yield*/, jobsTable.put({
|
|
5344
|
-
nodeId: myId,
|
|
5345
|
-
started: new Date(),
|
|
5346
|
-
heartbeat: new Date()
|
|
5347
|
-
}, jobName)];
|
|
5348
|
-
case 4:
|
|
5349
|
-
// Now, take over!
|
|
5350
|
-
_e.sent();
|
|
5351
|
-
return [2 /*return*/, true];
|
|
5352
|
-
case 5: return [2 /*return*/, false];
|
|
5353
|
-
}
|
|
5354
|
-
});
|
|
5355
|
-
}); })];
|
|
5356
|
-
case 1:
|
|
5357
|
-
gotTheLock = _e.sent();
|
|
5358
|
-
if (gotTheLock)
|
|
5359
|
-
return [2 /*return*/, true];
|
|
5360
|
-
if (!awaitRemoteJob) return [3 /*break*/, 6];
|
|
5361
|
-
_e.label = 2;
|
|
5362
|
-
case 2:
|
|
5363
|
-
_e.trys.push([2, 4, , 6]);
|
|
5364
|
-
jobDoneObservable = rxjs.from(Dexie.liveQuery(function () { return jobsTable.get(jobName); })).pipe(timeout(GUARDED_JOB_TIMEOUT), filter(function (job) { return !job; }));
|
|
5365
|
-
return [4 /*yield*/, jobDoneObservable.toPromise()];
|
|
5366
|
-
case 3:
|
|
5367
|
-
_e.sent();
|
|
5368
|
-
return [2 /*return*/, false];
|
|
5369
|
-
case 4:
|
|
5370
|
-
err_1 = _e.sent();
|
|
5371
|
-
if (err_1.name !== 'TimeoutError') {
|
|
5372
|
-
throw err_1;
|
|
5373
|
-
}
|
|
5374
|
-
return [4 /*yield*/, aquireLock()];
|
|
5375
|
-
case 5:
|
|
5376
|
-
// Timeout stopped us! Try aquire the lock now.
|
|
5377
|
-
// It will likely succeed this time unless
|
|
5378
|
-
// another client took it.
|
|
5379
|
-
return [2 /*return*/, _e.sent()];
|
|
5380
|
-
case 6: return [2 /*return*/, false];
|
|
5381
|
-
}
|
|
5382
|
-
});
|
|
5383
|
-
});
|
|
5384
|
-
}
|
|
5385
|
-
var jobsTable, heartbeat;
|
|
5386
|
-
var _this_1 = this;
|
|
5387
|
-
return __generator$1(this, function (_g) {
|
|
5388
|
-
switch (_g.label) {
|
|
5389
|
-
case 0:
|
|
5390
|
-
jobsTable = db.table(jobsTableName);
|
|
5391
|
-
return [4 /*yield*/, aquireLock()];
|
|
5392
|
-
case 1:
|
|
5393
|
-
if (!_g.sent()) return [3 /*break*/, 6];
|
|
5394
|
-
heartbeat = setInterval(function () {
|
|
5395
|
-
jobsTable.update(jobName, function (job) {
|
|
5396
|
-
if (job.nodeId === myId) {
|
|
5397
|
-
job.heartbeat = new Date();
|
|
5398
|
-
}
|
|
5399
|
-
});
|
|
5400
|
-
}, GUARDED_JOB_HEARTBEAT);
|
|
5401
|
-
_g.label = 2;
|
|
5402
|
-
case 2:
|
|
5403
|
-
_g.trys.push([2, , 4, 6]);
|
|
5404
|
-
return [4 /*yield*/, job()];
|
|
5405
|
-
case 3: return [2 /*return*/, _g.sent()];
|
|
5406
|
-
case 4:
|
|
5407
|
-
// Stop heartbeat
|
|
5408
|
-
clearInterval(heartbeat);
|
|
5409
|
-
// Remove the persisted job state:
|
|
5410
|
-
return [4 /*yield*/, db.transaction('rw!', jobsTableName, function () { return __awaiter$1(_this_1, void 0, void 0, function () {
|
|
5411
|
-
var currentWork;
|
|
5412
|
-
return __generator$1(this, function (_e) {
|
|
5413
|
-
switch (_e.label) {
|
|
5414
|
-
case 0: return [4 /*yield*/, jobsTable.get(jobName)];
|
|
5415
|
-
case 1:
|
|
5416
|
-
currentWork = _e.sent();
|
|
5417
|
-
if (currentWork && currentWork.nodeId === myId) {
|
|
5418
|
-
jobsTable.delete(jobName);
|
|
5419
|
-
}
|
|
5420
|
-
return [2 /*return*/];
|
|
5421
|
-
}
|
|
5422
|
-
});
|
|
5423
|
-
}); })];
|
|
5424
|
-
case 5:
|
|
5425
|
-
// Remove the persisted job state:
|
|
5426
|
-
_g.sent();
|
|
5427
|
-
return [7 /*endfinally*/];
|
|
5428
|
-
case 6: return [2 /*return*/];
|
|
5429
|
-
}
|
|
5430
|
-
});
|
|
5431
|
-
});
|
|
5432
|
-
}
|
|
5433
5306
|
function performInitialSync(db, cloudOptions, cloudSchema) {
|
|
5434
5307
|
return __awaiter$1(this, void 0, void 0, function () {
|
|
5435
|
-
var _this_1 = this;
|
|
5436
5308
|
return __generator$1(this, function (_e) {
|
|
5437
5309
|
switch (_e.label) {
|
|
5438
5310
|
case 0:
|
|
5439
|
-
console.debug(
|
|
5440
|
-
return [4 /*yield*/,
|
|
5441
|
-
var syncState;
|
|
5442
|
-
return __generator$1(this, function (_e) {
|
|
5443
|
-
switch (_e.label) {
|
|
5444
|
-
case 0: return [4 /*yield*/, db.getPersistedSyncState()];
|
|
5445
|
-
case 1:
|
|
5446
|
-
syncState = _e.sent();
|
|
5447
|
-
if (!!(syncState === null || syncState === void 0 ? void 0 : syncState.initiallySynced)) return [3 /*break*/, 3];
|
|
5448
|
-
return [4 /*yield*/, sync(db, cloudOptions, cloudSchema, { isInitialSync: true })];
|
|
5449
|
-
case 2:
|
|
5450
|
-
_e.sent();
|
|
5451
|
-
_e.label = 3;
|
|
5452
|
-
case 3: return [2 /*return*/];
|
|
5453
|
-
}
|
|
5454
|
-
});
|
|
5455
|
-
}); }, { awaitRemoteJob: true } // Don't return until the job is done!
|
|
5456
|
-
)];
|
|
5311
|
+
console.debug('Performing initial sync');
|
|
5312
|
+
return [4 /*yield*/, sync(db, cloudOptions, cloudSchema, { isInitialSync: true })];
|
|
5457
5313
|
case 1:
|
|
5458
5314
|
_e.sent();
|
|
5459
|
-
console.debug(
|
|
5315
|
+
console.debug('Done initial sync');
|
|
5460
5316
|
return [2 /*return*/];
|
|
5461
5317
|
}
|
|
5462
5318
|
});
|
|
5463
5319
|
});
|
|
5464
5320
|
}
|
|
5465
|
-
var USER_INACTIVITY_TIMEOUT =
|
|
5321
|
+
var USER_INACTIVITY_TIMEOUT = 180000; // 3 minutes
|
|
5466
5322
|
var INACTIVE_WAIT_TIME = 20000;
|
|
5467
5323
|
// This observable will be emitted to later down....
|
|
5468
5324
|
var userIsActive = new rxjs.BehaviorSubject(true);
|
|
@@ -5476,9 +5332,12 @@
|
|
|
5476
5332
|
// for just a short time.
|
|
5477
5333
|
var userIsReallyActive = new rxjs.BehaviorSubject(true);
|
|
5478
5334
|
userIsActive
|
|
5479
|
-
.pipe(switchMap(function (isActive) {
|
|
5480
|
-
|
|
5481
|
-
|
|
5335
|
+
.pipe(switchMap(function (isActive) {
|
|
5336
|
+
//console.debug('SyncStatus: DUBB: isActive changed to', isActive);
|
|
5337
|
+
return isActive
|
|
5338
|
+
? rxjs.of(true)
|
|
5339
|
+
: rxjs.of(false).pipe(delay(INACTIVE_WAIT_TIME));
|
|
5340
|
+
}), distinctUntilChanged())
|
|
5482
5341
|
.subscribe(userIsReallyActive);
|
|
5483
5342
|
//
|
|
5484
5343
|
// First create some corner-stone observables to build the flow on
|
|
@@ -5493,7 +5352,7 @@
|
|
|
5493
5352
|
var documentBecomesVisible = visibilityStateIsChanged.pipe(filter(function () { return document.visibilityState === 'visible'; }));
|
|
5494
5353
|
// Any of various user-activity-related events happen:
|
|
5495
5354
|
var userDoesSomething = typeof window !== 'undefined'
|
|
5496
|
-
? rxjs.merge(documentBecomesVisible, rxjs.fromEvent(window, 'mousemove'), rxjs.fromEvent(window, 'keydown'), rxjs.fromEvent(window, 'wheel'), rxjs.fromEvent(window, 'touchmove'))
|
|
5355
|
+
? rxjs.merge(documentBecomesVisible, rxjs.fromEvent(window, 'mousedown'), rxjs.fromEvent(window, 'mousemove'), rxjs.fromEvent(window, 'keydown'), rxjs.fromEvent(window, 'wheel'), rxjs.fromEvent(window, 'touchmove'))
|
|
5497
5356
|
: rxjs.of({});
|
|
5498
5357
|
if (typeof document !== 'undefined') {
|
|
5499
5358
|
//
|
|
@@ -5548,6 +5407,7 @@
|
|
|
5548
5407
|
function WSConnection(databaseUrl, rev, realmSetHash, clientIdentity, token, tokenExpiration, subscriber, messageProducer, webSocketStatus) {
|
|
5549
5408
|
var _this_1 = _super_1.call(this, function () { return _this_1.teardown(); }) || this;
|
|
5550
5409
|
_this_1.id = ++counter;
|
|
5410
|
+
_this_1.reconnecting = false;
|
|
5551
5411
|
console.debug('New WebSocket Connection', _this_1.id, token ? 'authorized' : 'unauthorized');
|
|
5552
5412
|
_this_1.databaseUrl = databaseUrl;
|
|
5553
5413
|
_this_1.rev = rev;
|
|
@@ -5568,7 +5428,7 @@
|
|
|
5568
5428
|
this.disconnect();
|
|
5569
5429
|
};
|
|
5570
5430
|
WSConnection.prototype.disconnect = function () {
|
|
5571
|
-
this.webSocketStatus.next(
|
|
5431
|
+
this.webSocketStatus.next('disconnected');
|
|
5572
5432
|
if (this.pinger) {
|
|
5573
5433
|
clearInterval(this.pinger);
|
|
5574
5434
|
this.pinger = null;
|
|
@@ -5586,17 +5446,25 @@
|
|
|
5586
5446
|
}
|
|
5587
5447
|
};
|
|
5588
5448
|
WSConnection.prototype.reconnect = function () {
|
|
5589
|
-
this
|
|
5590
|
-
this.
|
|
5449
|
+
var _this_1 = this;
|
|
5450
|
+
if (this.reconnecting)
|
|
5451
|
+
return;
|
|
5452
|
+
this.reconnecting = true;
|
|
5453
|
+
try {
|
|
5454
|
+
this.disconnect();
|
|
5455
|
+
}
|
|
5456
|
+
catch (_e) { }
|
|
5457
|
+
this.connect()
|
|
5458
|
+
.catch(function () { })
|
|
5459
|
+
.then(function () { return (_this_1.reconnecting = false); }); // finally()
|
|
5591
5460
|
};
|
|
5592
5461
|
WSConnection.prototype.connect = function () {
|
|
5593
5462
|
return __awaiter$1(this, void 0, void 0, function () {
|
|
5594
|
-
var wsUrl, searchParams, ws;
|
|
5463
|
+
var wsUrl, searchParams, ws, everConnected_1;
|
|
5595
5464
|
var _this_1 = this;
|
|
5596
5465
|
return __generator$1(this, function (_e) {
|
|
5597
5466
|
switch (_e.label) {
|
|
5598
5467
|
case 0:
|
|
5599
|
-
this.webSocketStatus.next("connecting");
|
|
5600
5468
|
this.lastServerActivity = new Date();
|
|
5601
5469
|
if (this.pauseUntil && this.pauseUntil > new Date()) {
|
|
5602
5470
|
console.debug('WS not reconnecting just yet', {
|
|
@@ -5611,12 +5479,14 @@
|
|
|
5611
5479
|
if (!this.databaseUrl)
|
|
5612
5480
|
throw new Error("Cannot connect without a database URL");
|
|
5613
5481
|
if (this.closed) {
|
|
5482
|
+
//console.debug('SyncStatus: DUBB: Ooops it was closed!');
|
|
5614
5483
|
return [2 /*return*/];
|
|
5615
5484
|
}
|
|
5616
5485
|
if (this.tokenExpiration && this.tokenExpiration < new Date()) {
|
|
5617
5486
|
this.subscriber.error(new TokenExpiredError()); // Will be handled in connectWebSocket.ts.
|
|
5618
5487
|
return [2 /*return*/];
|
|
5619
5488
|
}
|
|
5489
|
+
this.webSocketStatus.next('connecting');
|
|
5620
5490
|
this.pinger = setInterval(function () { return __awaiter$1(_this_1, void 0, void 0, function () {
|
|
5621
5491
|
var _this_1 = this;
|
|
5622
5492
|
return __generator$1(this, function (_e) {
|
|
@@ -5666,7 +5536,7 @@
|
|
|
5666
5536
|
searchParams = new URLSearchParams();
|
|
5667
5537
|
if (this.subscriber.closed)
|
|
5668
5538
|
return [2 /*return*/];
|
|
5669
|
-
searchParams.set('v',
|
|
5539
|
+
searchParams.set('v', '2');
|
|
5670
5540
|
searchParams.set('rev', this.rev);
|
|
5671
5541
|
searchParams.set('realmsHash', this.realmSetHash);
|
|
5672
5542
|
searchParams.set('clientId', this.clientIdentity);
|
|
@@ -5707,17 +5577,23 @@
|
|
|
5707
5577
|
_e.label = 1;
|
|
5708
5578
|
case 1:
|
|
5709
5579
|
_e.trys.push([1, 3, , 4]);
|
|
5580
|
+
everConnected_1 = false;
|
|
5710
5581
|
return [4 /*yield*/, new Promise(function (resolve, reject) {
|
|
5711
5582
|
ws.onopen = function (event) {
|
|
5712
5583
|
console.debug('dexie-cloud WebSocket onopen');
|
|
5584
|
+
everConnected_1 = true;
|
|
5713
5585
|
resolve(null);
|
|
5714
5586
|
};
|
|
5715
5587
|
ws.onerror = function (event) {
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5588
|
+
if (!everConnected_1) {
|
|
5589
|
+
var error = event.error || new Error('WebSocket Error');
|
|
5590
|
+
_this_1.subscriber.error(error);
|
|
5591
|
+
_this_1.webSocketStatus.next('error');
|
|
5592
|
+
reject(error);
|
|
5593
|
+
}
|
|
5594
|
+
else {
|
|
5595
|
+
_this_1.reconnect();
|
|
5596
|
+
}
|
|
5721
5597
|
};
|
|
5722
5598
|
})];
|
|
5723
5599
|
case 2:
|
|
@@ -5725,8 +5601,9 @@
|
|
|
5725
5601
|
this.messageProducerSubscription = this.messageProducer.subscribe(function (msg) {
|
|
5726
5602
|
var _e;
|
|
5727
5603
|
if (!_this_1.closed) {
|
|
5728
|
-
if (msg.type === 'ready' &&
|
|
5729
|
-
_this_1.webSocketStatus.
|
|
5604
|
+
if (msg.type === 'ready' &&
|
|
5605
|
+
_this_1.webSocketStatus.value !== 'connected') {
|
|
5606
|
+
_this_1.webSocketStatus.next('connected');
|
|
5730
5607
|
}
|
|
5731
5608
|
(_e = _this_1.ws) === null || _e === void 0 ? void 0 : _e.send(TSON.stringify(msg));
|
|
5732
5609
|
}
|
|
@@ -5835,7 +5712,10 @@
|
|
|
5835
5712
|
else {
|
|
5836
5713
|
return rxjs.throwError(error);
|
|
5837
5714
|
}
|
|
5838
|
-
}), catchError(function (error) {
|
|
5715
|
+
}), catchError(function (error) {
|
|
5716
|
+
db.cloud.webSocketStatus.next("error");
|
|
5717
|
+
return rxjs.from(waitAndReconnectWhenUserDoesSomething(error)).pipe(switchMap(function () { return createObservable(); }));
|
|
5718
|
+
}));
|
|
5839
5719
|
}
|
|
5840
5720
|
return createObservable().subscribe(function (msg) {
|
|
5841
5721
|
if (msg) {
|
|
@@ -5868,6 +5748,135 @@
|
|
|
5868
5748
|
});
|
|
5869
5749
|
});
|
|
5870
5750
|
}
|
|
5751
|
+
var SECONDS = 1000;
|
|
5752
|
+
var MINUTES = 60 * SECONDS;
|
|
5753
|
+
var myId = randomString(16);
|
|
5754
|
+
var GUARDED_JOB_HEARTBEAT = 1 * SECONDS;
|
|
5755
|
+
var GUARDED_JOB_TIMEOUT = 1 * MINUTES;
|
|
5756
|
+
function performGuardedJob(db, jobName, jobsTableName, job, _e) {
|
|
5757
|
+
var _f = _e === void 0 ? {} : _e, awaitRemoteJob = _f.awaitRemoteJob;
|
|
5758
|
+
return __awaiter$1(this, void 0, void 0, function () {
|
|
5759
|
+
function aquireLock() {
|
|
5760
|
+
return __awaiter$1(this, void 0, void 0, function () {
|
|
5761
|
+
var gotTheLock, jobDoneObservable, err_1;
|
|
5762
|
+
var _this_1 = this;
|
|
5763
|
+
return __generator$1(this, function (_e) {
|
|
5764
|
+
switch (_e.label) {
|
|
5765
|
+
case 0: return [4 /*yield*/, db.transaction('rw!', jobsTableName, function () { return __awaiter$1(_this_1, void 0, void 0, function () {
|
|
5766
|
+
var currentWork;
|
|
5767
|
+
return __generator$1(this, function (_e) {
|
|
5768
|
+
switch (_e.label) {
|
|
5769
|
+
case 0: return [4 /*yield*/, jobsTable.get(jobName)];
|
|
5770
|
+
case 1:
|
|
5771
|
+
currentWork = _e.sent();
|
|
5772
|
+
if (!!currentWork) return [3 /*break*/, 3];
|
|
5773
|
+
// No one else is working. Let's record that we are.
|
|
5774
|
+
return [4 /*yield*/, jobsTable.add({
|
|
5775
|
+
nodeId: myId,
|
|
5776
|
+
started: new Date(),
|
|
5777
|
+
heartbeat: new Date()
|
|
5778
|
+
}, jobName)];
|
|
5779
|
+
case 2:
|
|
5780
|
+
// No one else is working. Let's record that we are.
|
|
5781
|
+
_e.sent();
|
|
5782
|
+
return [2 /*return*/, true];
|
|
5783
|
+
case 3:
|
|
5784
|
+
if (!(currentWork.heartbeat.getTime() <
|
|
5785
|
+
Date.now() - GUARDED_JOB_TIMEOUT)) return [3 /*break*/, 5];
|
|
5786
|
+
console.warn("Latest ".concat(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!");
|
|
5787
|
+
// Now, take over!
|
|
5788
|
+
return [4 /*yield*/, jobsTable.put({
|
|
5789
|
+
nodeId: myId,
|
|
5790
|
+
started: new Date(),
|
|
5791
|
+
heartbeat: new Date()
|
|
5792
|
+
}, jobName)];
|
|
5793
|
+
case 4:
|
|
5794
|
+
// Now, take over!
|
|
5795
|
+
_e.sent();
|
|
5796
|
+
return [2 /*return*/, true];
|
|
5797
|
+
case 5: return [2 /*return*/, false];
|
|
5798
|
+
}
|
|
5799
|
+
});
|
|
5800
|
+
}); })];
|
|
5801
|
+
case 1:
|
|
5802
|
+
gotTheLock = _e.sent();
|
|
5803
|
+
if (gotTheLock)
|
|
5804
|
+
return [2 /*return*/, true];
|
|
5805
|
+
if (!awaitRemoteJob) return [3 /*break*/, 6];
|
|
5806
|
+
_e.label = 2;
|
|
5807
|
+
case 2:
|
|
5808
|
+
_e.trys.push([2, 4, , 6]);
|
|
5809
|
+
jobDoneObservable = rxjs.from(Dexie.liveQuery(function () { return jobsTable.get(jobName); })).pipe(timeout(GUARDED_JOB_TIMEOUT), filter(function (job) { return !job; }));
|
|
5810
|
+
return [4 /*yield*/, jobDoneObservable.toPromise()];
|
|
5811
|
+
case 3:
|
|
5812
|
+
_e.sent();
|
|
5813
|
+
return [2 /*return*/, false];
|
|
5814
|
+
case 4:
|
|
5815
|
+
err_1 = _e.sent();
|
|
5816
|
+
if (err_1.name !== 'TimeoutError') {
|
|
5817
|
+
throw err_1;
|
|
5818
|
+
}
|
|
5819
|
+
return [4 /*yield*/, aquireLock()];
|
|
5820
|
+
case 5:
|
|
5821
|
+
// Timeout stopped us! Try aquire the lock now.
|
|
5822
|
+
// It will likely succeed this time unless
|
|
5823
|
+
// another client took it.
|
|
5824
|
+
return [2 /*return*/, _e.sent()];
|
|
5825
|
+
case 6: return [2 /*return*/, false];
|
|
5826
|
+
}
|
|
5827
|
+
});
|
|
5828
|
+
});
|
|
5829
|
+
}
|
|
5830
|
+
var jobsTable, heartbeat;
|
|
5831
|
+
var _this_1 = this;
|
|
5832
|
+
return __generator$1(this, function (_g) {
|
|
5833
|
+
switch (_g.label) {
|
|
5834
|
+
case 0:
|
|
5835
|
+
jobsTable = db.table(jobsTableName);
|
|
5836
|
+
return [4 /*yield*/, aquireLock()];
|
|
5837
|
+
case 1:
|
|
5838
|
+
if (!_g.sent()) return [3 /*break*/, 6];
|
|
5839
|
+
heartbeat = setInterval(function () {
|
|
5840
|
+
jobsTable.update(jobName, function (job) {
|
|
5841
|
+
if (job.nodeId === myId) {
|
|
5842
|
+
job.heartbeat = new Date();
|
|
5843
|
+
}
|
|
5844
|
+
});
|
|
5845
|
+
}, GUARDED_JOB_HEARTBEAT);
|
|
5846
|
+
_g.label = 2;
|
|
5847
|
+
case 2:
|
|
5848
|
+
_g.trys.push([2, , 4, 6]);
|
|
5849
|
+
return [4 /*yield*/, job()];
|
|
5850
|
+
case 3: return [2 /*return*/, _g.sent()];
|
|
5851
|
+
case 4:
|
|
5852
|
+
// Stop heartbeat
|
|
5853
|
+
clearInterval(heartbeat);
|
|
5854
|
+
// Remove the persisted job state:
|
|
5855
|
+
return [4 /*yield*/, db.transaction('rw!', jobsTableName, function () { return __awaiter$1(_this_1, void 0, void 0, function () {
|
|
5856
|
+
var currentWork;
|
|
5857
|
+
return __generator$1(this, function (_e) {
|
|
5858
|
+
switch (_e.label) {
|
|
5859
|
+
case 0: return [4 /*yield*/, jobsTable.get(jobName)];
|
|
5860
|
+
case 1:
|
|
5861
|
+
currentWork = _e.sent();
|
|
5862
|
+
if (!(currentWork && currentWork.nodeId === myId)) return [3 /*break*/, 3];
|
|
5863
|
+
return [4 /*yield*/, jobsTable.delete(jobName)];
|
|
5864
|
+
case 2:
|
|
5865
|
+
_e.sent();
|
|
5866
|
+
_e.label = 3;
|
|
5867
|
+
case 3: return [2 /*return*/];
|
|
5868
|
+
}
|
|
5869
|
+
});
|
|
5870
|
+
}); })];
|
|
5871
|
+
case 5:
|
|
5872
|
+
// Remove the persisted job state:
|
|
5873
|
+
_g.sent();
|
|
5874
|
+
return [7 /*endfinally*/];
|
|
5875
|
+
case 6: return [2 /*return*/];
|
|
5876
|
+
}
|
|
5877
|
+
});
|
|
5878
|
+
});
|
|
5879
|
+
}
|
|
5871
5880
|
var ongoingSyncs = new WeakMap();
|
|
5872
5881
|
function syncIfPossible(db, cloudOptions, cloudSchema, options) {
|
|
5873
5882
|
var ongoing = ongoingSyncs.get(db);
|
|
@@ -6476,6 +6485,21 @@
|
|
|
6476
6485
|
rv.getValue = function () { return currentValue; };
|
|
6477
6486
|
return rv;
|
|
6478
6487
|
}
|
|
6488
|
+
var getGlobalRolesObservable = associate(function (db) {
|
|
6489
|
+
return createSharedValueObservable(Dexie.liveQuery(function () { return db.roles
|
|
6490
|
+
.where({ realmId: 'rlm-public' })
|
|
6491
|
+
.toArray()
|
|
6492
|
+
.then(function (roles) {
|
|
6493
|
+
var rv = {};
|
|
6494
|
+
for (var _e = 0, _f = roles
|
|
6495
|
+
.slice()
|
|
6496
|
+
.sort(function (a, b) { return (a.sortOrder || 0) - (b.sortOrder || 0); }); _e < _f.length; _e++) {
|
|
6497
|
+
var role = _f[_e];
|
|
6498
|
+
rv[role.name] = role;
|
|
6499
|
+
}
|
|
6500
|
+
return rv;
|
|
6501
|
+
}); }), {});
|
|
6502
|
+
});
|
|
6479
6503
|
var getCurrentUserEmitter = associate(function (db) { return new rxjs.BehaviorSubject(UNAUTHORIZED_USER); });
|
|
6480
6504
|
var getInternalAccessControlObservable = associate(function (db) {
|
|
6481
6505
|
return createSharedValueObservable(getCurrentUserEmitter(db._novip).pipe(switchMap(function (currentUser) { return Dexie.liveQuery(function () { return db.transaction('r', 'realms', 'members', function () { return Promise.all([
|
|
@@ -6578,17 +6602,40 @@
|
|
|
6578
6602
|
return reduced;
|
|
6579
6603
|
}
|
|
6580
6604
|
var getPermissionsLookupObservable = associate(function (db) {
|
|
6581
|
-
var o =
|
|
6605
|
+
var o = createSharedValueObservable(rxjs.combineLatest([
|
|
6606
|
+
getInternalAccessControlObservable(db._novip),
|
|
6607
|
+
getGlobalRolesObservable(db._novip),
|
|
6608
|
+
]).pipe(map(function (_e) {
|
|
6609
|
+
var _f = _e[0], selfMembers = _f.selfMembers, realms = _f.realms, userId = _f.userId, globalRoles = _e[1];
|
|
6610
|
+
return ({
|
|
6611
|
+
selfMembers: selfMembers,
|
|
6612
|
+
realms: realms,
|
|
6613
|
+
userId: userId,
|
|
6614
|
+
globalRoles: globalRoles,
|
|
6615
|
+
});
|
|
6616
|
+
})), {
|
|
6617
|
+
selfMembers: [],
|
|
6618
|
+
realms: [],
|
|
6619
|
+
userId: UNAUTHORIZED_USER.userId,
|
|
6620
|
+
globalRoles: {},
|
|
6621
|
+
});
|
|
6582
6622
|
return mapValueObservable(o, function (_e) {
|
|
6583
6623
|
var _f;
|
|
6584
|
-
var selfMembers = _e.selfMembers, realms = _e.realms, userId = _e.userId;
|
|
6624
|
+
var selfMembers = _e.selfMembers, realms = _e.realms, userId = _e.userId, globalRoles = _e.globalRoles;
|
|
6585
6625
|
var rv = realms
|
|
6586
|
-
.map(function (realm) {
|
|
6587
|
-
|
|
6588
|
-
|
|
6589
|
-
|
|
6590
|
-
|
|
6591
|
-
|
|
6626
|
+
.map(function (realm) {
|
|
6627
|
+
var selfRealmMembers = selfMembers.filter(function (m) { return m.realmId === realm.realmId; });
|
|
6628
|
+
var directPermissionSets = selfRealmMembers
|
|
6629
|
+
.map(function (m) { return m.permissions; })
|
|
6630
|
+
.filter(function (p) { return p; });
|
|
6631
|
+
var rolePermissionSets = flatten(selfRealmMembers.map(function (m) { return m.roles; }).filter(function (roleName) { return roleName; }))
|
|
6632
|
+
.map(function (role) { return globalRoles[role]; })
|
|
6633
|
+
.filter(function (role) { return role; })
|
|
6634
|
+
.map(function (role) { return role.permissions; });
|
|
6635
|
+
return __assign(__assign({}, realm), { permissions: realm.owner === userId
|
|
6636
|
+
? { manage: '*' }
|
|
6637
|
+
: mergePermissions.apply(void 0, __spreadArray$1(__spreadArray$1([], directPermissionSets, false), rolePermissionSets, false)) });
|
|
6638
|
+
})
|
|
6592
6639
|
.reduce(function (p, c) {
|
|
6593
6640
|
var _e;
|
|
6594
6641
|
return (__assign(__assign({}, p), (_e = {}, _e[c.realmId] = c, _e)));
|
|
@@ -6686,7 +6733,7 @@
|
|
|
6686
6733
|
var realm = permissionsLookup[realmId || dexie.cloud.currentUserId];
|
|
6687
6734
|
if (!realm)
|
|
6688
6735
|
return new PermissionChecker({}, tableName, !owner || owner === dexie.cloud.currentUserId);
|
|
6689
|
-
return new PermissionChecker(realm.permissions, tableName,
|
|
6736
|
+
return new PermissionChecker(realm.permissions, tableName, realmId === dexie.cloud.currentUserId || owner === dexie.cloud.currentUserId);
|
|
6690
6737
|
};
|
|
6691
6738
|
var o = source.pipe(map(mapper));
|
|
6692
6739
|
o.getValue = function () { return mapper(source.getValue()); };
|
|
@@ -6724,6 +6771,7 @@
|
|
|
6724
6771
|
//
|
|
6725
6772
|
var currentUserEmitter = getCurrentUserEmitter(dexie);
|
|
6726
6773
|
var subscriptions = [];
|
|
6774
|
+
var configuredProgramatically = false;
|
|
6727
6775
|
// local sync worker - used when there's no service worker.
|
|
6728
6776
|
var localSyncWorker = null;
|
|
6729
6777
|
dexie.on('ready', function (dexie) { return __awaiter$1(_this_1, void 0, void 0, function () {
|
|
@@ -6759,7 +6807,7 @@
|
|
|
6759
6807
|
currentUserEmitter.next(UNAUTHORIZED_USER);
|
|
6760
6808
|
});
|
|
6761
6809
|
dexie.cloud = {
|
|
6762
|
-
version: '4.0.0-beta.
|
|
6810
|
+
version: '4.0.0-beta.17',
|
|
6763
6811
|
options: __assign({}, DEFAULT_OPTIONS),
|
|
6764
6812
|
schema: null,
|
|
6765
6813
|
serverState: null,
|
|
@@ -6793,8 +6841,10 @@
|
|
|
6793
6841
|
});
|
|
6794
6842
|
},
|
|
6795
6843
|
invites: getInvitesObservable(dexie),
|
|
6844
|
+
roles: getGlobalRolesObservable(dexie),
|
|
6796
6845
|
configure: function (options) {
|
|
6797
6846
|
options = dexie.cloud.options = __assign(__assign({}, dexie.cloud.options), options);
|
|
6847
|
+
configuredProgramatically = true;
|
|
6798
6848
|
if (options.databaseUrl && options.nameSuffix) {
|
|
6799
6849
|
// @ts-ignore
|
|
6800
6850
|
dexie.name = "".concat(origIdbName, "-").concat(getDbNameFromDbUrl(options.databaseUrl));
|
|
@@ -6929,7 +6979,7 @@
|
|
|
6929
6979
|
])];
|
|
6930
6980
|
case 1:
|
|
6931
6981
|
_f = _m.sent(), persistedOptions = _f[0], persistedSchema = _f[1], persistedSyncState = _f[2];
|
|
6932
|
-
if (!!
|
|
6982
|
+
if (!!configuredProgramatically) return [3 /*break*/, 2];
|
|
6933
6983
|
// Options not specified programatically (use case for SW!)
|
|
6934
6984
|
// Take persisted options:
|
|
6935
6985
|
db.cloud.options = persistedOptions || null;
|
|
@@ -6938,9 +6988,10 @@
|
|
|
6938
6988
|
if (!(!persistedOptions ||
|
|
6939
6989
|
JSON.stringify(persistedOptions) !== JSON.stringify(options))) return [3 /*break*/, 4];
|
|
6940
6990
|
// Update persisted options:
|
|
6991
|
+
if (!options)
|
|
6992
|
+
throw new Error("Internal error"); // options cannot be null if configuredProgramatically is set.
|
|
6941
6993
|
return [4 /*yield*/, db.$syncState.put(options, 'options')];
|
|
6942
6994
|
case 3:
|
|
6943
|
-
// Update persisted options:
|
|
6944
6995
|
_m.sent();
|
|
6945
6996
|
_m.label = 4;
|
|
6946
6997
|
case 4:
|
|
@@ -7086,7 +7137,7 @@
|
|
|
7086
7137
|
});
|
|
7087
7138
|
}
|
|
7088
7139
|
}
|
|
7089
|
-
dexieCloud.version = '4.0.0-beta.
|
|
7140
|
+
dexieCloud.version = '4.0.0-beta.17';
|
|
7090
7141
|
Dexie__default["default"].Cloud = dexieCloud;
|
|
7091
7142
|
|
|
7092
7143
|
exports["default"] = dexieCloud;
|