@webex/webex-core 3.12.0-llmrefactor.1 → 3.12.0-llmrefactor.10
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 +23 -0
- package/dist/config.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/interceptors/catalog-url.js +87 -0
- package/dist/interceptors/catalog-url.js.map +1 -0
- package/dist/interceptors/payload-transformer.js +25 -4
- package/dist/interceptors/payload-transformer.js.map +1 -1
- package/dist/lib/batcher.js +1 -1
- package/dist/lib/credentials/credentials.js +56 -1
- package/dist/lib/credentials/credentials.js.map +1 -1
- package/dist/lib/credentials/token.js +1 -1
- package/dist/lib/services/service-catalog.js +102 -8
- package/dist/lib/services/service-catalog.js.map +1 -1
- package/dist/lib/services/services.js +74 -44
- package/dist/lib/services/services.js.map +1 -1
- package/dist/lib/services-v2/service-catalog.js +8 -1
- package/dist/lib/services-v2/service-catalog.js.map +1 -1
- package/dist/lib/services-v2/services-v2.js +76 -45
- package/dist/lib/services-v2/services-v2.js.map +1 -1
- package/dist/plugins/logger.js +1 -1
- package/dist/webex-core.js +11 -3
- package/dist/webex-core.js.map +1 -1
- package/package.json +12 -12
- package/src/config.js +25 -0
- package/src/index.js +1 -0
- package/src/interceptors/catalog-url.js +66 -0
- package/src/interceptors/payload-transformer.js +23 -1
- package/src/lib/credentials/credentials.js +43 -0
- package/src/lib/services/service-catalog.js +106 -6
- package/src/lib/services/services.js +65 -30
- package/src/lib/services-v2/service-catalog.ts +10 -1
- package/src/lib/services-v2/services-v2.ts +70 -30
- package/src/webex-core.js +8 -0
- package/test/integration/spec/services/services.js +148 -113
- package/test/integration/spec/services-v2/services-v2.js +134 -99
- package/test/unit/spec/credentials/credentials.js +114 -1
- package/test/unit/spec/interceptors/catalog-url.js +224 -0
- package/test/unit/spec/interceptors/payload-transformer.js +119 -1
- package/test/unit/spec/services/service-catalog.js +275 -0
- package/test/unit/spec/services/services.js +135 -2
- package/test/unit/spec/services-v2/service-catalog.ts +41 -0
- package/test/unit/spec/services-v2/services-v2.ts +158 -2
- package/test/unit/spec/webex-core.js +77 -1
|
@@ -1103,9 +1103,16 @@ const Services = WebexPlugin.extend({
|
|
|
1103
1103
|
requestObject.headers = {authorization: token};
|
|
1104
1104
|
}
|
|
1105
1105
|
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1106
|
+
const sendRequest = () => this.request(requestObject);
|
|
1107
|
+
|
|
1108
|
+
const responsePromise = this.webex.internal.newMetrics
|
|
1109
|
+
? this.webex.internal.newMetrics.callDiagnosticLatencies.measureLatency(
|
|
1110
|
+
sendRequest,
|
|
1111
|
+
'internal.get.u2c.time'
|
|
1112
|
+
)
|
|
1113
|
+
: sendRequest();
|
|
1114
|
+
|
|
1115
|
+
return responsePromise.then(({body}) => body);
|
|
1109
1116
|
},
|
|
1110
1117
|
|
|
1111
1118
|
/**
|
|
@@ -1418,6 +1425,28 @@ const Services = WebexPlugin.extend({
|
|
|
1418
1425
|
this.ready = true;
|
|
1419
1426
|
},
|
|
1420
1427
|
|
|
1428
|
+
/**
|
|
1429
|
+
* Build a promise that rejects once the catalog init timeout elapses. Race
|
|
1430
|
+
* this against catalog collection so a hung request never leaves
|
|
1431
|
+
* `services.ready` false forever - that would stall `webex.ready` and leave
|
|
1432
|
+
* consumers waiting on it indefinitely. Timeout is configurable via
|
|
1433
|
+
* `config.services.catalogInitTimeout` (defaults to 15s in config). Created
|
|
1434
|
+
* lazily so paths that skip catalog collection never schedule a stray timer.
|
|
1435
|
+
*
|
|
1436
|
+
* @private
|
|
1437
|
+
* @returns {Promise<never>}
|
|
1438
|
+
*/
|
|
1439
|
+
_makeInitTimeout() {
|
|
1440
|
+
const initTimeoutMs = this.webex.config?.services?.catalogInitTimeout;
|
|
1441
|
+
|
|
1442
|
+
return new Promise((_, reject) => {
|
|
1443
|
+
setTimeout(
|
|
1444
|
+
() => reject(new Error(`services: init timed out after ${initTimeoutMs}ms`)),
|
|
1445
|
+
initTimeoutMs
|
|
1446
|
+
);
|
|
1447
|
+
});
|
|
1448
|
+
},
|
|
1449
|
+
|
|
1421
1450
|
/**
|
|
1422
1451
|
* Initializer
|
|
1423
1452
|
*
|
|
@@ -1492,6 +1521,14 @@ const Services = WebexPlugin.extend({
|
|
|
1492
1521
|
} else {
|
|
1493
1522
|
const {email} = this.webex.config;
|
|
1494
1523
|
|
|
1524
|
+
if (this.webex.config?.services?.skipPreauthCatalogOnUnauthenticated === true) {
|
|
1525
|
+
this.logger.info(
|
|
1526
|
+
'services: skipping preauth catalog collection while unauthenticated as per the config'
|
|
1527
|
+
);
|
|
1528
|
+
|
|
1529
|
+
return;
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1495
1532
|
this.collectPreauthCatalog(email ? {email} : undefined).catch((error) => {
|
|
1496
1533
|
this.initFailed = true;
|
|
1497
1534
|
this.logger.error(
|
|
@@ -1526,25 +1563,12 @@ const Services = WebexPlugin.extend({
|
|
|
1526
1563
|
}
|
|
1527
1564
|
const {supertoken} = this.webex.credentials;
|
|
1528
1565
|
|
|
1529
|
-
// Race init against a hard timeout so a hung request never leaves
|
|
1530
|
-
// `services.ready` false forever - that would stall `webex.ready` and
|
|
1531
|
-
// leave consumers waiting on it indefinitely. Timeout is configurable via
|
|
1532
|
-
// `config.services.catalogInitTimeout` (defaults to 15s in config).
|
|
1533
|
-
const initTimeoutMs = this.webex.config?.services?.catalogInitTimeout;
|
|
1534
|
-
|
|
1535
|
-
const initServiceCatalogsTimeout = new Promise((_, reject) => {
|
|
1536
|
-
setTimeout(
|
|
1537
|
-
() => reject(new Error(`services: init timed out after ${initTimeoutMs}ms`)),
|
|
1538
|
-
initTimeoutMs
|
|
1539
|
-
);
|
|
1540
|
-
});
|
|
1541
|
-
|
|
1542
1566
|
// Validate if the supertoken exists.
|
|
1543
1567
|
if (supertoken && supertoken.access_token) {
|
|
1544
1568
|
// `initServiceCatalogs` marks the catalog ready internally once the
|
|
1545
1569
|
// postauth catalog is collected - even if it loses the timeout race
|
|
1546
|
-
//
|
|
1547
|
-
Promise.race([this.initServiceCatalogs(),
|
|
1570
|
+
// below, so a slow fetch still eventually flips `catalog.isReady`.
|
|
1571
|
+
Promise.race([this.initServiceCatalogs(), this._makeInitTimeout()])
|
|
1548
1572
|
.catch((error) => {
|
|
1549
1573
|
this.initFailed = true;
|
|
1550
1574
|
this.logger.error(
|
|
@@ -1555,18 +1579,6 @@ const Services = WebexPlugin.extend({
|
|
|
1555
1579
|
} else {
|
|
1556
1580
|
const {email} = this.webex.config;
|
|
1557
1581
|
|
|
1558
|
-
Promise.race([
|
|
1559
|
-
this.collectPreauthCatalog(email ? {email} : undefined),
|
|
1560
|
-
initServiceCatalogsTimeout,
|
|
1561
|
-
])
|
|
1562
|
-
.catch((error) => {
|
|
1563
|
-
this.initFailed = true;
|
|
1564
|
-
this.logger.error(
|
|
1565
|
-
`services: failed to init initial services when no credentials available, ${error?.message}`
|
|
1566
|
-
);
|
|
1567
|
-
})
|
|
1568
|
-
.finally(() => this._finalizeReady());
|
|
1569
|
-
|
|
1570
1582
|
// Handle fresh login: 'loaded' fires before OAuth completes, so listen
|
|
1571
1583
|
// for `canAuthorize` flipping true and then collect the postauth catalog.
|
|
1572
1584
|
this.listenToOnce(this.webex, 'change:canAuthorize', () => {
|
|
@@ -1579,6 +1591,29 @@ const Services = WebexPlugin.extend({
|
|
|
1579
1591
|
});
|
|
1580
1592
|
}
|
|
1581
1593
|
});
|
|
1594
|
+
|
|
1595
|
+
if (this.webex.config?.services?.skipPreauthCatalogOnUnauthenticated === true) {
|
|
1596
|
+
// Skip the preauth catalog fetch (it will be collected manually
|
|
1597
|
+
// later), but still finalize `services.ready` so `webex.ready` is not
|
|
1598
|
+
// stalled while unauthenticated. No timeout is created here so there
|
|
1599
|
+
// is no stray timer or unhandled rejection.
|
|
1600
|
+
this.logger.info(
|
|
1601
|
+
'services: skipping preauth catalog collection while unauthenticated as per the config'
|
|
1602
|
+
);
|
|
1603
|
+
this._finalizeReady();
|
|
1604
|
+
} else {
|
|
1605
|
+
Promise.race([
|
|
1606
|
+
this.collectPreauthCatalog(email ? {email} : undefined),
|
|
1607
|
+
this._makeInitTimeout(),
|
|
1608
|
+
])
|
|
1609
|
+
.catch((error) => {
|
|
1610
|
+
this.initFailed = true;
|
|
1611
|
+
this.logger.error(
|
|
1612
|
+
`services: failed to init initial services when no credentials available, ${error?.message}`
|
|
1613
|
+
);
|
|
1614
|
+
})
|
|
1615
|
+
.finally(() => this._finalizeReady());
|
|
1616
|
+
}
|
|
1582
1617
|
}
|
|
1583
1618
|
});
|
|
1584
1619
|
},
|
|
@@ -4,6 +4,7 @@ import {union} from 'lodash';
|
|
|
4
4
|
import ServiceDetail from './service-detail';
|
|
5
5
|
import {IServiceDetail, ServiceGroup} from './types';
|
|
6
6
|
import {matchAllowedDomain, normalizeAllowedDomains} from '../domains';
|
|
7
|
+
import {matchesParsedCatalogUrl, parseCatalogUrl} from '../services/service-catalog';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* @class
|
|
@@ -199,9 +200,17 @@ const ServiceCatalog = AmpState.extend({
|
|
|
199
200
|
findServiceDetailFromUrl(url: string): IServiceDetail | undefined {
|
|
200
201
|
const serviceDetails = this._getAllServiceDetails();
|
|
201
202
|
|
|
203
|
+
let candidateUrl: URL;
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
candidateUrl = new URL(url);
|
|
207
|
+
} catch {
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
|
|
202
211
|
return serviceDetails.find(({serviceUrls}) => {
|
|
203
212
|
for (const serviceUrl of serviceUrls) {
|
|
204
|
-
if (
|
|
213
|
+
if (matchesParsedCatalogUrl(candidateUrl, parseCatalogUrl(serviceUrl.baseUrl))) {
|
|
205
214
|
return true;
|
|
206
215
|
}
|
|
207
216
|
}
|
|
@@ -7,6 +7,7 @@ import METRICS from '../metrics';
|
|
|
7
7
|
import ServiceCatalog from './service-catalog';
|
|
8
8
|
import fedRampServices from './service-fed-ramp';
|
|
9
9
|
import {COMMERCIAL_ALLOWED_DOMAINS} from '../constants';
|
|
10
|
+
import {matchesCatalogUrl} from '../services/service-catalog';
|
|
10
11
|
import {
|
|
11
12
|
ActiveServices,
|
|
12
13
|
IServiceCatalog,
|
|
@@ -15,6 +16,7 @@ import {
|
|
|
15
16
|
ServiceHostmap,
|
|
16
17
|
ServiceGroup,
|
|
17
18
|
ServiceHost,
|
|
19
|
+
ServiceUrl,
|
|
18
20
|
SelectionMeta,
|
|
19
21
|
} from './types';
|
|
20
22
|
|
|
@@ -988,7 +990,9 @@ const Services = WebexPlugin.extend({
|
|
|
988
990
|
|
|
989
991
|
const priorityUrl = service.get();
|
|
990
992
|
const defaultUrl = new URL(
|
|
991
|
-
service.serviceUrls.find((serviceUrl) =>
|
|
993
|
+
service.serviceUrls.find((serviceUrl: ServiceUrl) =>
|
|
994
|
+
matchesCatalogUrl(url, serviceUrl.baseUrl)
|
|
995
|
+
).baseUrl
|
|
992
996
|
).href;
|
|
993
997
|
|
|
994
998
|
return {
|
|
@@ -1257,9 +1261,16 @@ const Services = WebexPlugin.extend({
|
|
|
1257
1261
|
requestObject.headers = {authorization: token};
|
|
1258
1262
|
}
|
|
1259
1263
|
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1264
|
+
const sendRequest = () => this.request(requestObject);
|
|
1265
|
+
|
|
1266
|
+
const responsePromise = this.webex.internal.newMetrics
|
|
1267
|
+
? this.webex.internal.newMetrics.callDiagnosticLatencies.measureLatency(
|
|
1268
|
+
sendRequest,
|
|
1269
|
+
'internal.get.u2c.time'
|
|
1270
|
+
)
|
|
1271
|
+
: sendRequest();
|
|
1272
|
+
|
|
1273
|
+
return responsePromise.then(({body}) => this._formatReceivedHostmap(body || {}));
|
|
1263
1274
|
},
|
|
1264
1275
|
|
|
1265
1276
|
/**
|
|
@@ -1388,6 +1399,28 @@ const Services = WebexPlugin.extend({
|
|
|
1388
1399
|
this.ready = true;
|
|
1389
1400
|
},
|
|
1390
1401
|
|
|
1402
|
+
/**
|
|
1403
|
+
* Build a promise that rejects once the catalog init timeout elapses. Race
|
|
1404
|
+
* this against catalog collection so a hung request never leaves
|
|
1405
|
+
* `services.ready` false forever - that would stall `webex.ready` and leave
|
|
1406
|
+
* consumers waiting on it indefinitely. Timeout is configurable via
|
|
1407
|
+
* `config.services.catalogInitTimeout` (defaults to 15s in config). Created
|
|
1408
|
+
* lazily so paths that skip catalog collection never schedule a stray timer.
|
|
1409
|
+
*
|
|
1410
|
+
* @private
|
|
1411
|
+
* @returns {Promise<never>}
|
|
1412
|
+
*/
|
|
1413
|
+
_makeInitTimeout(): Promise<never> {
|
|
1414
|
+
const initTimeoutMs = this.webex.config?.services?.catalogInitTimeout;
|
|
1415
|
+
|
|
1416
|
+
return new Promise<never>((_, reject) => {
|
|
1417
|
+
setTimeout(
|
|
1418
|
+
() => reject(new Error(`services: init timed out after ${initTimeoutMs}ms`)),
|
|
1419
|
+
initTimeoutMs
|
|
1420
|
+
);
|
|
1421
|
+
});
|
|
1422
|
+
},
|
|
1423
|
+
|
|
1391
1424
|
/**
|
|
1392
1425
|
* Initializer
|
|
1393
1426
|
*
|
|
@@ -1455,6 +1488,14 @@ const Services = WebexPlugin.extend({
|
|
|
1455
1488
|
} else {
|
|
1456
1489
|
const {email} = this.webex.config;
|
|
1457
1490
|
|
|
1491
|
+
if (this.webex.config?.services?.skipPreauthCatalogOnUnauthenticated === true) {
|
|
1492
|
+
this.logger.info(
|
|
1493
|
+
'services: skipping preauth catalog collection while unauthenticated as per the config'
|
|
1494
|
+
);
|
|
1495
|
+
|
|
1496
|
+
return;
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1458
1499
|
this.collectPreauthCatalog(email ? {email} : undefined).catch((error) => {
|
|
1459
1500
|
this.initFailed = true;
|
|
1460
1501
|
this.logger.error(
|
|
@@ -1489,24 +1530,12 @@ const Services = WebexPlugin.extend({
|
|
|
1489
1530
|
}
|
|
1490
1531
|
const {supertoken} = this.webex.credentials;
|
|
1491
1532
|
|
|
1492
|
-
// Race init against a hard timeout so a hung request never leaves
|
|
1493
|
-
// `services.ready` false forever - that would stall `webex.ready` and
|
|
1494
|
-
// leave consumers waiting on it indefinitely. Timeout is configurable via
|
|
1495
|
-
// `config.services.catalogInitTimeout` (defaults to 15s in config).
|
|
1496
|
-
const initTimeoutMs = this.webex.config?.services?.catalogInitTimeout;
|
|
1497
|
-
const initServiceCatalogsTimeout = new Promise<never>((_, reject) => {
|
|
1498
|
-
setTimeout(
|
|
1499
|
-
() => reject(new Error(`services: init timed out after ${initTimeoutMs}ms`)),
|
|
1500
|
-
initTimeoutMs
|
|
1501
|
-
);
|
|
1502
|
-
});
|
|
1503
|
-
|
|
1504
1533
|
// Validate if the supertoken exists.
|
|
1505
1534
|
if (supertoken && supertoken.access_token) {
|
|
1506
1535
|
// `initServiceCatalogs` marks the catalog ready internally once the
|
|
1507
1536
|
// postauth catalog is collected - even if it loses the timeout race
|
|
1508
|
-
//
|
|
1509
|
-
Promise.race([this.initServiceCatalogs(),
|
|
1537
|
+
// below, so a slow fetch still eventually flips `catalog.isReady`.
|
|
1538
|
+
Promise.race([this.initServiceCatalogs(), this._makeInitTimeout()])
|
|
1510
1539
|
.catch((error) => {
|
|
1511
1540
|
this.initFailed = true;
|
|
1512
1541
|
this.logger.error(
|
|
@@ -1517,18 +1546,6 @@ const Services = WebexPlugin.extend({
|
|
|
1517
1546
|
} else {
|
|
1518
1547
|
const {email} = this.webex.config;
|
|
1519
1548
|
|
|
1520
|
-
Promise.race([
|
|
1521
|
-
this.collectPreauthCatalog(email ? {email} : undefined),
|
|
1522
|
-
initServiceCatalogsTimeout,
|
|
1523
|
-
])
|
|
1524
|
-
.catch((error) => {
|
|
1525
|
-
this.initFailed = true;
|
|
1526
|
-
this.logger.error(
|
|
1527
|
-
`services: failed to init initial services when no credentials available, ${error?.message}`
|
|
1528
|
-
);
|
|
1529
|
-
})
|
|
1530
|
-
.finally(() => this._finalizeReady());
|
|
1531
|
-
|
|
1532
1549
|
// Handle fresh login: 'loaded' fires before OAuth completes, so listen
|
|
1533
1550
|
// for `canAuthorize` flipping true and then collect the postauth catalog.
|
|
1534
1551
|
this.listenToOnce(this.webex, 'change:canAuthorize', () => {
|
|
@@ -1541,6 +1558,29 @@ const Services = WebexPlugin.extend({
|
|
|
1541
1558
|
});
|
|
1542
1559
|
}
|
|
1543
1560
|
});
|
|
1561
|
+
|
|
1562
|
+
if (this.webex.config?.services?.skipPreauthCatalogOnUnauthenticated === true) {
|
|
1563
|
+
// Skip the preauth catalog fetch (it will be collected manually
|
|
1564
|
+
// later), but still finalize `services.ready` so `webex.ready` is not
|
|
1565
|
+
// stalled while unauthenticated. No timeout is created here so there
|
|
1566
|
+
// is no stray timer or unhandled rejection.
|
|
1567
|
+
this.logger.info(
|
|
1568
|
+
'services: skipping preauth catalog collection while unauthenticated as per the config'
|
|
1569
|
+
);
|
|
1570
|
+
this._finalizeReady();
|
|
1571
|
+
} else {
|
|
1572
|
+
Promise.race([
|
|
1573
|
+
this.collectPreauthCatalog(email ? {email} : undefined),
|
|
1574
|
+
this._makeInitTimeout(),
|
|
1575
|
+
])
|
|
1576
|
+
.catch((error) => {
|
|
1577
|
+
this.initFailed = true;
|
|
1578
|
+
this.logger.error(
|
|
1579
|
+
`services: failed to init initial services when no credentials available, ${error?.message}`
|
|
1580
|
+
);
|
|
1581
|
+
})
|
|
1582
|
+
.finally(() => this._finalizeReady());
|
|
1583
|
+
}
|
|
1544
1584
|
}
|
|
1545
1585
|
});
|
|
1546
1586
|
},
|
package/src/webex-core.js
CHANGED
|
@@ -17,6 +17,7 @@ import AmpState from 'ampersand-state';
|
|
|
17
17
|
import uuid from 'uuid';
|
|
18
18
|
|
|
19
19
|
import AuthInterceptor from './interceptors/auth';
|
|
20
|
+
import CatalogUrlInterceptor from './interceptors/catalog-url';
|
|
20
21
|
import NetworkTimingInterceptor from './interceptors/network-timing';
|
|
21
22
|
import PayloadTransformerInterceptor from './interceptors/payload-transformer';
|
|
22
23
|
import RedirectInterceptor from './interceptors/redirect';
|
|
@@ -58,6 +59,7 @@ const interceptors = {
|
|
|
58
59
|
/* eslint-enable no-extra-parens */
|
|
59
60
|
RequestTimingInterceptor: RequestTimingInterceptor.create,
|
|
60
61
|
ServiceInterceptor: undefined,
|
|
62
|
+
CatalogUrlInterceptor: CatalogUrlInterceptor.create,
|
|
61
63
|
UserAgentInterceptor: UserAgentInterceptor.create,
|
|
62
64
|
ProxyInterceptor: ProxyInterceptor.create,
|
|
63
65
|
WebexUserAgentInterceptor: WebexUserAgentInterceptor.create,
|
|
@@ -83,6 +85,7 @@ const preInterceptors = [
|
|
|
83
85
|
'RequestEventInterceptor',
|
|
84
86
|
'WebexTrackingIdInterceptor',
|
|
85
87
|
'RateLimitInterceptor',
|
|
88
|
+
'CatalogUrlInterceptor',
|
|
86
89
|
];
|
|
87
90
|
|
|
88
91
|
const postInterceptors = [
|
|
@@ -393,6 +396,11 @@ const WebexCore = AmpState.extend({
|
|
|
393
396
|
return ints;
|
|
394
397
|
}
|
|
395
398
|
|
|
399
|
+
// CatalogUrlInterceptor is opt-in via config.services.validateCatalogUrls
|
|
400
|
+
if (key === 'CatalogUrlInterceptor' && this.config.services?.validateCatalogUrls !== true) {
|
|
401
|
+
return ints;
|
|
402
|
+
}
|
|
403
|
+
|
|
396
404
|
ints.push(Reflect.apply(interceptor, this, []));
|
|
397
405
|
|
|
398
406
|
return ints;
|