@webex/webex-core 3.12.0-next.32 → 3.12.0-next.34
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/config.js +9 -0
- package/dist/config.js.map +1 -1
- package/dist/lib/batcher.js +1 -1
- package/dist/lib/credentials/credentials.js +1 -1
- package/dist/lib/credentials/token.js +1 -1
- package/dist/lib/services/services.js +196 -28
- package/dist/lib/services/services.js.map +1 -1
- package/dist/lib/services-v2/services-v2.js +195 -26
- package/dist/lib/services-v2/services-v2.js.map +1 -1
- package/dist/plugins/logger.js +1 -1
- package/dist/webex-core.js +2 -2
- package/package.json +3 -3
- package/src/config.js +10 -0
- package/src/lib/services/services.js +170 -17
- package/src/lib/services-v2/services-v2.ts +169 -16
- package/test/fixtures/activation-email.ts +22 -0
- package/test/integration/spec/services/services.js +44 -8
- package/test/integration/spec/services-v2/services-v2.js +44 -8
- package/test/unit/spec/services/services.js +307 -2
- package/test/unit/spec/services-v2/services-v2.ts +295 -0
|
@@ -52,6 +52,21 @@ var Services = _webexPlugin.default.extend({
|
|
|
52
52
|
validateDomains: ['boolean', false, true],
|
|
53
53
|
initFailed: ['boolean', false, false]
|
|
54
54
|
},
|
|
55
|
+
session: {
|
|
56
|
+
/**
|
|
57
|
+
* Becomes `true` once the initial catalog collection has completed
|
|
58
|
+
* (successfully or otherwise) and any in-flight credentials refresh has
|
|
59
|
+
* settled. Blocks `webex.ready` so consumers can rely on `webex.ready`
|
|
60
|
+
* implying "catalogs populated AND credential state stable".
|
|
61
|
+
* @instance
|
|
62
|
+
* @memberof Services
|
|
63
|
+
* @type {boolean}
|
|
64
|
+
*/
|
|
65
|
+
ready: {
|
|
66
|
+
default: false,
|
|
67
|
+
type: 'boolean'
|
|
68
|
+
}
|
|
69
|
+
},
|
|
55
70
|
_catalogs: new _weakMap.default(),
|
|
56
71
|
_activeServices: {},
|
|
57
72
|
_services: [],
|
|
@@ -1285,6 +1300,7 @@ var Services = _webexPlugin.default.extend({
|
|
|
1285
1300
|
|
|
1286
1301
|
// Destructure the credentials plugin.
|
|
1287
1302
|
var credentials = this.webex.credentials;
|
|
1303
|
+
var catalog = this._getCatalog();
|
|
1288
1304
|
|
|
1289
1305
|
// Init a promise chain. Must be done as a Promise.resolve() to allow
|
|
1290
1306
|
// credentials#getOrgId() to properly throw.
|
|
@@ -1301,9 +1317,14 @@ var Services = _webexPlugin.default.extend({
|
|
|
1301
1317
|
}).then(function () {
|
|
1302
1318
|
// Validate if the token is authorized.
|
|
1303
1319
|
if (credentials.canAuthorize) {
|
|
1304
|
-
// Attempt to collect the postauth catalog
|
|
1320
|
+
// Attempt to collect the postauth catalog, then mark the catalog
|
|
1321
|
+
// ready. Setting `isReady` here - rather than only in the init
|
|
1322
|
+
// callers - means a slow postauth fetch that loses the gated-init
|
|
1323
|
+
// timeout race still marks the catalog ready once it completes.
|
|
1305
1324
|
return _this11.updateServices({
|
|
1306
1325
|
forceRefresh: refresh
|
|
1326
|
+
}).then(function () {
|
|
1327
|
+
catalog.isReady = true;
|
|
1307
1328
|
}).catch(function () {
|
|
1308
1329
|
_this11.initFailed = true;
|
|
1309
1330
|
_this11.logger.warn('services: cannot retrieve postauth catalog');
|
|
@@ -1314,6 +1335,42 @@ var Services = _webexPlugin.default.extend({
|
|
|
1314
1335
|
return _promise.default.resolve();
|
|
1315
1336
|
});
|
|
1316
1337
|
},
|
|
1338
|
+
/**
|
|
1339
|
+
* Await any in-flight credentials refresh, then flip `services.ready` so
|
|
1340
|
+
* `webex.ready` can fire. Closes the parallel-refresh window: if a credential
|
|
1341
|
+
* refresh is in flight when initial catalog collection settles, we must not
|
|
1342
|
+
* signal ready until the refresh has resolved - otherwise downstream
|
|
1343
|
+
* consumers may observe `canAuthorize`/token state that is about to change
|
|
1344
|
+
* under them.
|
|
1345
|
+
*
|
|
1346
|
+
* @private
|
|
1347
|
+
* @returns {Promise<void>}
|
|
1348
|
+
*/
|
|
1349
|
+
_finalizeReady: function _finalizeReady() {
|
|
1350
|
+
var _this12 = this;
|
|
1351
|
+
return (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee3() {
|
|
1352
|
+
var credentials;
|
|
1353
|
+
return _regenerator.default.wrap(function (_context3) {
|
|
1354
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
1355
|
+
case 0:
|
|
1356
|
+
credentials = _this12.webex.credentials;
|
|
1357
|
+
if (!(credentials && credentials.isRefreshing)) {
|
|
1358
|
+
_context3.next = 1;
|
|
1359
|
+
break;
|
|
1360
|
+
}
|
|
1361
|
+
_context3.next = 1;
|
|
1362
|
+
return new _promise.default(function (resolve) {
|
|
1363
|
+
credentials.once('change:isRefreshing', resolve);
|
|
1364
|
+
});
|
|
1365
|
+
case 1:
|
|
1366
|
+
_this12.ready = true;
|
|
1367
|
+
case 2:
|
|
1368
|
+
case "end":
|
|
1369
|
+
return _context3.stop();
|
|
1370
|
+
}
|
|
1371
|
+
}, _callee3);
|
|
1372
|
+
}))();
|
|
1373
|
+
},
|
|
1317
1374
|
/**
|
|
1318
1375
|
* Initializer
|
|
1319
1376
|
*
|
|
@@ -1322,58 +1379,170 @@ var Services = _webexPlugin.default.extend({
|
|
|
1322
1379
|
* @returns {Services}
|
|
1323
1380
|
*/
|
|
1324
1381
|
initialize: function initialize() {
|
|
1325
|
-
var
|
|
1382
|
+
var _this13 = this;
|
|
1326
1383
|
var catalog = new _serviceCatalog.default();
|
|
1327
1384
|
this._catalogs.set(this.webex, catalog);
|
|
1328
1385
|
|
|
1329
|
-
// Listen for configuration changes once.
|
|
1386
|
+
// Listen for configuration changes once. The config is not populated on the
|
|
1387
|
+
// webex instance until the `change:config` event fires, so any decision that
|
|
1388
|
+
// depends on config values (such as the gated-vs-ungated init below) must be
|
|
1389
|
+
// made from within this handler rather than synchronously in `initialize()`.
|
|
1330
1390
|
this.listenToOnce(this.webex, 'change:config', function () {
|
|
1331
|
-
|
|
1332
|
-
|
|
1391
|
+
var _this13$webex$config, _this13$webex$config$;
|
|
1392
|
+
_this13.initConfig();
|
|
1333
1393
|
|
|
1394
|
+
// Feature flag: when enabled, `webex.ready` is blocked until the initial
|
|
1395
|
+
// catalog collection has settled AND any in-flight credentials refresh has
|
|
1396
|
+
// completed. When disabled (the default), preserves the pre-existing
|
|
1397
|
+
// behavior where `webex.ready` fires as soon as `webex.loaded` does and
|
|
1398
|
+
// the catalog is collected out-of-band.
|
|
1399
|
+
var waitForCatalogInit = ((_this13$webex$config = _this13.webex.config) === null || _this13$webex$config === void 0 ? void 0 : (_this13$webex$config$ = _this13$webex$config.services) === null || _this13$webex$config$ === void 0 ? void 0 : _this13$webex$config$.waitForCatalogInit) === true;
|
|
1400
|
+
if (waitForCatalogInit) {
|
|
1401
|
+
_this13._initializeCatalogsGated(catalog);
|
|
1402
|
+
} else {
|
|
1403
|
+
// Not gating - immediately mark ready so we do not block webex.ready.
|
|
1404
|
+
_this13.ready = true;
|
|
1405
|
+
_this13._initializeCatalogsUngated(catalog);
|
|
1406
|
+
}
|
|
1407
|
+
});
|
|
1408
|
+
},
|
|
1409
|
+
/**
|
|
1410
|
+
* Original (pre-verified-ready) initialization path. Runs on `webex.ready`
|
|
1411
|
+
* and collects catalogs opportunistically without blocking anything.
|
|
1412
|
+
*
|
|
1413
|
+
* @private
|
|
1414
|
+
* @param {ServiceCatalog} catalog
|
|
1415
|
+
* @returns {void}
|
|
1416
|
+
*/
|
|
1417
|
+
_initializeCatalogsUngated: function _initializeCatalogsUngated(catalog) {
|
|
1418
|
+
var _this14 = this;
|
|
1334
1419
|
// wait for webex instance to be ready before attempting
|
|
1335
1420
|
// to update the service catalogs
|
|
1336
|
-
this.listenToOnce(this.webex, 'ready', /*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function
|
|
1421
|
+
this.listenToOnce(this.webex, 'ready', /*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee4() {
|
|
1337
1422
|
var warmed, supertoken, email;
|
|
1338
|
-
return _regenerator.default.wrap(function (
|
|
1339
|
-
while (1) switch (
|
|
1423
|
+
return _regenerator.default.wrap(function (_context4) {
|
|
1424
|
+
while (1) switch (_context4.prev = _context4.next) {
|
|
1340
1425
|
case 0:
|
|
1341
|
-
|
|
1342
|
-
return
|
|
1426
|
+
_context4.next = 1;
|
|
1427
|
+
return _this14._loadCatalogFromCache();
|
|
1343
1428
|
case 1:
|
|
1344
|
-
warmed =
|
|
1429
|
+
warmed = _context4.sent;
|
|
1345
1430
|
if (!warmed) {
|
|
1346
|
-
|
|
1431
|
+
_context4.next = 2;
|
|
1347
1432
|
break;
|
|
1348
1433
|
}
|
|
1349
1434
|
catalog.isReady = true;
|
|
1350
|
-
return
|
|
1435
|
+
return _context4.abrupt("return");
|
|
1351
1436
|
case 2:
|
|
1352
|
-
supertoken =
|
|
1437
|
+
supertoken = _this14.webex.credentials.supertoken; // Validate if the supertoken exists.
|
|
1353
1438
|
if (supertoken && supertoken.access_token) {
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1439
|
+
// `initServiceCatalogs` marks the catalog ready internally once the
|
|
1440
|
+
// postauth catalog is collected.
|
|
1441
|
+
_this14.initServiceCatalogs().catch(function (error) {
|
|
1442
|
+
_this14.initFailed = true;
|
|
1443
|
+
_this14.logger.error("services: failed to init initial services when credentials available, ".concat(error === null || error === void 0 ? void 0 : error.message));
|
|
1359
1444
|
});
|
|
1360
1445
|
} else {
|
|
1361
|
-
email =
|
|
1362
|
-
|
|
1446
|
+
email = _this14.webex.config.email;
|
|
1447
|
+
_this14.collectPreauthCatalog(email ? {
|
|
1363
1448
|
email: email
|
|
1364
1449
|
} : undefined).catch(function (error) {
|
|
1365
|
-
|
|
1366
|
-
|
|
1450
|
+
_this14.initFailed = true;
|
|
1451
|
+
_this14.logger.error("services: failed to init initial services when no credentials available, ".concat(error === null || error === void 0 ? void 0 : error.message));
|
|
1367
1452
|
});
|
|
1368
1453
|
}
|
|
1369
1454
|
case 3:
|
|
1370
1455
|
case "end":
|
|
1371
|
-
return
|
|
1456
|
+
return _context4.stop();
|
|
1372
1457
|
}
|
|
1373
|
-
},
|
|
1458
|
+
}, _callee4);
|
|
1459
|
+
})));
|
|
1460
|
+
},
|
|
1461
|
+
/**
|
|
1462
|
+
* Verified-ready initialization path. Blocks `webex.ready` until the initial
|
|
1463
|
+
* catalog fetch has settled (or timed out) AND any in-flight credentials
|
|
1464
|
+
* refresh has completed. Also handles the fresh-login case where OAuth
|
|
1465
|
+
* completes after `loaded` fires.
|
|
1466
|
+
*
|
|
1467
|
+
* @private
|
|
1468
|
+
* @param {ServiceCatalog} catalog
|
|
1469
|
+
* @returns {void}
|
|
1470
|
+
*/
|
|
1471
|
+
_initializeCatalogsGated: function _initializeCatalogsGated(catalog) {
|
|
1472
|
+
var _this15 = this;
|
|
1473
|
+
// Wait for storage to be loaded before attempting to update the service
|
|
1474
|
+
// catalogs. We listen for 'loaded' instead of 'ready' because `services.ready`
|
|
1475
|
+
// now blocks `webex.ready` - listening to 'ready' would deadlock.
|
|
1476
|
+
this.listenToOnce(this.webex, 'loaded', /*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee5() {
|
|
1477
|
+
var _this15$webex$config, _this15$webex$config$;
|
|
1478
|
+
var warmed, supertoken, initTimeoutMs, initServiceCatalogsTimeout, email;
|
|
1479
|
+
return _regenerator.default.wrap(function (_context5) {
|
|
1480
|
+
while (1) switch (_context5.prev = _context5.next) {
|
|
1481
|
+
case 0:
|
|
1482
|
+
_context5.next = 1;
|
|
1483
|
+
return _this15._loadCatalogFromCache();
|
|
1484
|
+
case 1:
|
|
1485
|
+
warmed = _context5.sent;
|
|
1486
|
+
if (!warmed) {
|
|
1487
|
+
_context5.next = 3;
|
|
1488
|
+
break;
|
|
1489
|
+
}
|
|
1490
|
+
catalog.isReady = true;
|
|
1491
|
+
_context5.next = 2;
|
|
1492
|
+
return _this15._finalizeReady();
|
|
1493
|
+
case 2:
|
|
1494
|
+
return _context5.abrupt("return");
|
|
1495
|
+
case 3:
|
|
1496
|
+
supertoken = _this15.webex.credentials.supertoken; // Race init against a hard timeout so a hung request never leaves
|
|
1497
|
+
// `services.ready` false forever - that would stall `webex.ready` and
|
|
1498
|
+
// leave consumers waiting on it indefinitely. Timeout is configurable via
|
|
1499
|
+
// `config.services.catalogInitTimeout` (defaults to 15s in config).
|
|
1500
|
+
initTimeoutMs = (_this15$webex$config = _this15.webex.config) === null || _this15$webex$config === void 0 ? void 0 : (_this15$webex$config$ = _this15$webex$config.services) === null || _this15$webex$config$ === void 0 ? void 0 : _this15$webex$config$.catalogInitTimeout;
|
|
1501
|
+
initServiceCatalogsTimeout = new _promise.default(function (_, reject) {
|
|
1502
|
+
setTimeout(function () {
|
|
1503
|
+
return reject(new Error("services: init timed out after ".concat(initTimeoutMs, "ms")));
|
|
1504
|
+
}, initTimeoutMs);
|
|
1505
|
+
}); // Validate if the supertoken exists.
|
|
1506
|
+
if (supertoken && supertoken.access_token) {
|
|
1507
|
+
// `initServiceCatalogs` marks the catalog ready internally once the
|
|
1508
|
+
// postauth catalog is collected - even if it loses the timeout race
|
|
1509
|
+
// above, so a slow fetch still eventually flips `catalog.isReady`.
|
|
1510
|
+
_promise.default.race([_this15.initServiceCatalogs(), initServiceCatalogsTimeout]).catch(function (error) {
|
|
1511
|
+
_this15.initFailed = true;
|
|
1512
|
+
_this15.logger.error("services: failed to init initial services when credentials available, ".concat(error === null || error === void 0 ? void 0 : error.message));
|
|
1513
|
+
}).finally(function () {
|
|
1514
|
+
return _this15._finalizeReady();
|
|
1515
|
+
});
|
|
1516
|
+
} else {
|
|
1517
|
+
email = _this15.webex.config.email;
|
|
1518
|
+
_promise.default.race([_this15.collectPreauthCatalog(email ? {
|
|
1519
|
+
email: email
|
|
1520
|
+
} : undefined), initServiceCatalogsTimeout]).catch(function (error) {
|
|
1521
|
+
_this15.initFailed = true;
|
|
1522
|
+
_this15.logger.error("services: failed to init initial services when no credentials available, ".concat(error === null || error === void 0 ? void 0 : error.message));
|
|
1523
|
+
}).finally(function () {
|
|
1524
|
+
return _this15._finalizeReady();
|
|
1525
|
+
});
|
|
1526
|
+
|
|
1527
|
+
// Handle fresh login: 'loaded' fires before OAuth completes, so listen
|
|
1528
|
+
// for `canAuthorize` flipping true and then collect the postauth catalog.
|
|
1529
|
+
_this15.listenToOnce(_this15.webex, 'change:canAuthorize', function () {
|
|
1530
|
+
if (_this15.webex.canAuthorize && !catalog.status.postauth.ready) {
|
|
1531
|
+
// `initServiceCatalogs` marks the catalog ready internally.
|
|
1532
|
+
_this15.initServiceCatalogs().catch(function (error) {
|
|
1533
|
+
_this15.logger.error("services: failed to init service catalogs after auth, ".concat(error === null || error === void 0 ? void 0 : error.message));
|
|
1534
|
+
});
|
|
1535
|
+
}
|
|
1536
|
+
});
|
|
1537
|
+
}
|
|
1538
|
+
case 4:
|
|
1539
|
+
case "end":
|
|
1540
|
+
return _context5.stop();
|
|
1541
|
+
}
|
|
1542
|
+
}, _callee5);
|
|
1374
1543
|
})));
|
|
1375
1544
|
},
|
|
1376
|
-
version: "3.12.0-next.
|
|
1545
|
+
version: "3.12.0-next.34"
|
|
1377
1546
|
});
|
|
1378
1547
|
/* eslint-enable no-underscore-dangle */
|
|
1379
1548
|
var _default = exports.default = Services;
|