@webex/webex-core 3.8.1 → 3.9.0-multi-llms.2

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.
Files changed (89) hide show
  1. package/README.md +87 -27
  2. package/dist/index.js +16 -33
  3. package/dist/index.js.map +1 -1
  4. package/dist/{lib/services/interceptors/hostmap.js → interceptors/proxy.js} +58 -25
  5. package/dist/interceptors/proxy.js.map +1 -0
  6. package/dist/lib/batcher.js +1 -1
  7. package/dist/lib/constants.js +10 -1
  8. package/dist/lib/constants.js.map +1 -1
  9. package/dist/lib/credentials/credentials.js +1 -1
  10. package/dist/lib/credentials/token.js +1 -1
  11. package/dist/lib/{services-v2/interceptors → interceptors}/server-error.js +1 -1
  12. package/dist/lib/interceptors/server-error.js.map +1 -0
  13. package/dist/lib/services/index.js +2 -29
  14. package/dist/lib/services/index.js.map +1 -1
  15. package/dist/lib/services/service-host.js +1 -1
  16. package/dist/lib/services/service-host.js.map +1 -1
  17. package/dist/lib/services/service-registry.js +1 -1
  18. package/dist/lib/services/service-registry.js.map +1 -1
  19. package/dist/lib/services/service-state.js +1 -1
  20. package/dist/lib/services/service-state.js.map +1 -1
  21. package/dist/lib/services/services.js +3 -3
  22. package/dist/lib/services/services.js.map +1 -1
  23. package/dist/lib/services-v2/index.js +0 -29
  24. package/dist/lib/services-v2/index.js.map +1 -1
  25. package/dist/lib/services-v2/metrics.js.map +1 -1
  26. package/dist/lib/services-v2/service-catalog.js +15 -11
  27. package/dist/lib/services-v2/service-catalog.js.map +1 -1
  28. package/dist/lib/services-v2/services-v2.js +160 -111
  29. package/dist/lib/services-v2/services-v2.js.map +1 -1
  30. package/dist/lib/services-v2/types.js.map +1 -1
  31. package/dist/plugins/logger.js +1 -1
  32. package/dist/webex-core.js +53 -60
  33. package/dist/webex-core.js.map +1 -1
  34. package/package.json +14 -14
  35. package/src/index.js +6 -14
  36. package/src/interceptors/proxy.js +70 -0
  37. package/src/lib/constants.js +29 -1
  38. package/src/lib/{services/interceptors → interceptors}/server-error.js +1 -1
  39. package/src/lib/services/index.js +2 -7
  40. package/src/lib/services/service-host.js +1 -1
  41. package/src/lib/services/service-registry.js +1 -1
  42. package/src/lib/services/service-state.js +1 -1
  43. package/src/lib/services/services.js +2 -2
  44. package/src/lib/services-v2/index.ts +0 -16
  45. package/src/lib/services-v2/service-catalog.ts +27 -19
  46. package/src/lib/services-v2/{services-v2.js → services-v2.ts} +188 -104
  47. package/src/lib/services-v2/types.ts +62 -2
  48. package/src/webex-core.js +12 -3
  49. package/test/fixtures/host-catalog-v2.ts +30 -122
  50. package/test/integration/spec/services/services.js +11 -0
  51. package/test/integration/spec/services-v2/service-catalog.js +664 -0
  52. package/test/integration/spec/services-v2/services-v2.js +1136 -0
  53. package/test/unit/spec/interceptors/proxy.js +73 -0
  54. package/test/unit/spec/services-v2/service-detail.ts +1 -1
  55. package/test/unit/spec/services-v2/services-v2.ts +579 -442
  56. package/test/unit/spec/webex-core.js +62 -2
  57. package/dist/lib/services/constants.js +0 -17
  58. package/dist/lib/services/constants.js.map +0 -1
  59. package/dist/lib/services/interceptors/hostmap.js.map +0 -1
  60. package/dist/lib/services/interceptors/server-error.js +0 -77
  61. package/dist/lib/services/interceptors/server-error.js.map +0 -1
  62. package/dist/lib/services/interceptors/service.js +0 -137
  63. package/dist/lib/services/interceptors/service.js.map +0 -1
  64. package/dist/lib/services-v2/constants.js +0 -17
  65. package/dist/lib/services-v2/constants.js.map +0 -1
  66. package/dist/lib/services-v2/interceptors/server-error.js.map +0 -1
  67. package/dist/lib/services-v2/service-host.js +0 -300
  68. package/dist/lib/services-v2/service-host.js.map +0 -1
  69. package/dist/lib/services-v2/service-registry.js +0 -534
  70. package/dist/lib/services-v2/service-registry.js.map +0 -1
  71. package/dist/lib/services-v2/service-state.js +0 -97
  72. package/dist/lib/services-v2/service-state.js.map +0 -1
  73. package/dist/lib/services-v2/service-url.js +0 -119
  74. package/dist/lib/services-v2/service-url.js.map +0 -1
  75. package/src/lib/services/constants.js +0 -21
  76. package/src/lib/services/interceptors/hostmap.js +0 -36
  77. package/src/lib/services/interceptors/service.js +0 -101
  78. package/src/lib/services-v2/constants.ts +0 -21
  79. package/src/lib/services-v2/interceptors/server-error.js +0 -48
  80. /package/dist/lib/{services-v2/interceptors → interceptors}/hostmap.js +0 -0
  81. /package/dist/lib/{services-v2/interceptors → interceptors}/hostmap.js.map +0 -0
  82. /package/dist/lib/{services-v2/interceptors → interceptors}/service.js +0 -0
  83. /package/dist/lib/{services-v2/interceptors → interceptors}/service.js.map +0 -0
  84. /package/dist/lib/{services/metrics.js → metrics.js} +0 -0
  85. /package/dist/lib/{services/metrics.js.map → metrics.js.map} +0 -0
  86. /package/src/lib/{services-v2/interceptors → interceptors}/hostmap.js +0 -0
  87. /package/src/lib/{services-v2/interceptors → interceptors}/service.js +0 -0
  88. /package/src/lib/{services-v2/metrics.js → metrics.js} +0 -0
  89. /package/src/lib/{services/metrics.js → services-v2/metrics.ts} +0 -0
@@ -1,12 +1,20 @@
1
1
  import sha256 from 'crypto-js/sha256';
2
2
 
3
- import {union, unionBy} from 'lodash';
3
+ import {toNumber, union, unionBy} from 'lodash';
4
4
  import WebexPlugin from '../webex-plugin';
5
5
 
6
- import METRICS from './metrics';
6
+ import METRICS from '../metrics';
7
7
  import ServiceCatalog from './service-catalog';
8
8
  import fedRampServices from './service-fed-ramp';
9
- import {COMMERCIAL_ALLOWED_DOMAINS} from './constants';
9
+ import {COMMERCIAL_ALLOWED_DOMAINS} from '../constants';
10
+ import {
11
+ ActiveServices,
12
+ IServiceCatalog,
13
+ QueryOptions,
14
+ Service,
15
+ ServiceHostmap,
16
+ ServiceGroup,
17
+ } from './types';
10
18
 
11
19
  const trailingSlashes = /(?:^\/)|(?:\/$)/;
12
20
 
@@ -41,9 +49,9 @@ const Services = WebexPlugin.extend({
41
49
  * @private
42
50
  * Get the current catalog based on the assocaited
43
51
  * webex instance.
44
- * @returns {ServiceCatalog}
52
+ * @returns {IServiceCatalog}
45
53
  */
46
- _getCatalog() {
54
+ _getCatalog(): IServiceCatalog {
47
55
  return this._catalogs.get(this.webex);
48
56
  },
49
57
 
@@ -51,14 +59,23 @@ const Services = WebexPlugin.extend({
51
59
  * Get a service url from the current services list by name
52
60
  * from the associated instance catalog.
53
61
  * @param {string} name
54
- * @param {boolean} [priorityHost]
55
- * @param {string} [serviceGroup]
62
+ * @param {ServiceGroup} [serviceGroup]
56
63
  * @returns {string|undefined}
57
64
  */
58
- get(name, priorityHost, serviceGroup) {
65
+ get(name: string, serviceGroup?: ServiceGroup): string | undefined {
59
66
  const catalog = this._getCatalog();
60
67
 
61
- return catalog.get(name, priorityHost, serviceGroup);
68
+ const clusterId = this._activeServices[name];
69
+
70
+ const urlById = catalog.get(clusterId, serviceGroup);
71
+ const urlByName = catalog.get(name, serviceGroup);
72
+
73
+ // if both are undefined, then we cannot find the service
74
+ if (!urlById && !urlByName) {
75
+ return undefined;
76
+ }
77
+
78
+ return urlById || urlByName;
62
79
  },
63
80
 
64
81
  /**
@@ -66,59 +83,42 @@ const Services = WebexPlugin.extend({
66
83
  *
67
84
  * @returns {boolean} - True if a allowed domains list exists.
68
85
  */
69
- hasAllowedDomains() {
86
+ hasAllowedDomains(): boolean {
70
87
  const catalog = this._getCatalog();
71
88
 
72
89
  return catalog.getAllowedDomains().length > 0;
73
90
  },
74
91
 
75
- /**
76
- * Generate a service catalog as an object from
77
- * the associated instance catalog.
78
- * @param {boolean} [priorityHost] - use highest priority host if set to `true`
79
- * @param {string} [serviceGroup]
80
- * @returns {Record<string, string>}
81
- */
82
- list(priorityHost, serviceGroup) {
83
- const catalog = this._getCatalog();
84
-
85
- return catalog.list(priorityHost, serviceGroup);
86
- },
87
-
88
92
  /**
89
93
  * Mark a priority host service url as failed.
90
- * This will mark the host associated with the
91
- * `ServiceUrl` to be removed from the its
92
- * respective host array, and then return the next
93
- * viable host from the `ServiceUrls` host array,
94
- * or the `ServiceUrls` default url if no other priority
95
- * hosts are available, or if `noPriorityHosts` is set to
96
- * `true`.
94
+ * This will mark the service url associated with the
95
+ * `ServiceDetail` to be removed from the its
96
+ * respective service url array, and then return the next
97
+ * viable service url from the `ServiceDetail` service url array.
97
98
  * @param {string} url
98
- * @param {boolean} noPriorityHosts
99
99
  * @returns {string}
100
100
  */
101
- markFailedUrl(url, noPriorityHosts) {
101
+ markFailedUrl(url: string): string | undefined {
102
102
  const catalog = this._getCatalog();
103
103
 
104
- return catalog.markFailedUrl(url, noPriorityHosts);
104
+ return catalog.markFailedServiceUrl(url);
105
105
  },
106
106
 
107
107
  /**
108
108
  * saves all the services from the pre and post catalog service
109
- * @param {Object} activeServices
109
+ * @param {ActiveServices} activeServices
110
110
  * @returns {void}
111
111
  */
112
- _updateActiveServices(activeServices) {
112
+ _updateActiveServices(activeServices: ActiveServices): void {
113
113
  this._activeServices = {...this._activeServices, ...activeServices};
114
114
  },
115
115
 
116
116
  /**
117
117
  * saves the hostCatalog object
118
- * @param {Object} services
118
+ * @param {Array<Service>} services
119
119
  * @returns {void}
120
120
  */
121
- _updateServices(services) {
121
+ _updateServices(services: Array<Service>): void {
122
122
  this._services = unionBy(services, this._services, 'id');
123
123
  },
124
124
 
@@ -135,7 +135,14 @@ const Services = WebexPlugin.extend({
135
135
  * @param {string} [param.token] - used for signin catalog
136
136
  * @returns {Promise<object>}
137
137
  */
138
- updateServices({from, query, token, forceRefresh} = {}) {
138
+ updateServices(
139
+ {from, query, token, forceRefresh} = {} as {
140
+ from: string;
141
+ query: QueryOptions;
142
+ token: string;
143
+ forceRefresh: boolean;
144
+ }
145
+ ): Promise<object> {
139
146
  const catalog = this._getCatalog();
140
147
  let formattedQuery;
141
148
  let serviceGroup;
@@ -152,9 +159,8 @@ const Services = WebexPlugin.extend({
152
159
  serviceGroup = 'postauth';
153
160
  break;
154
161
  }
155
-
156
162
  // confirm catalog update for group is not in progress.
157
- if (catalog.status[serviceGroup].collecting) {
163
+ if (catalog.status?.[serviceGroup]?.collecting) {
158
164
  return this.waitForCatalog(serviceGroup);
159
165
  }
160
166
 
@@ -188,8 +194,12 @@ const Services = WebexPlugin.extend({
188
194
  query: formattedQuery,
189
195
  forceRefresh,
190
196
  })
191
- .then((serviceHostMap) => {
192
- catalog.updateServiceGroups(serviceGroup, serviceHostMap);
197
+ .then((serviceHostMap: ServiceHostmap) => {
198
+ catalog.updateServiceGroups(
199
+ serviceGroup,
200
+ serviceHostMap?.services,
201
+ serviceHostMap?.timestamp
202
+ );
193
203
  this.updateCredentialsConfig();
194
204
  catalog.status[serviceGroup].collecting = false;
195
205
  })
@@ -283,7 +293,7 @@ const Services = WebexPlugin.extend({
283
293
  // Retrieve the service url from the updated catalog. This is required
284
294
  // since `WebexCore` is usually not fully initialized at the time this
285
295
  // request completes.
286
- const idbrokerService = this.get('idbroker', true);
296
+ const idbrokerService = this.get('idbroker');
287
297
 
288
298
  // Collect the client auth token.
289
299
  return this.webex.credentials.getClientToken({
@@ -338,7 +348,56 @@ const Services = WebexPlugin.extend({
338
348
  })
339
349
  );
340
350
  },
351
+ /**
352
+ * Update cluster id via mercury service update. If the cluster id does not exist,
353
+ * fetch new catalog.
354
+ *
355
+ * @param {ActiveServices} newActiveClusters - The new active clusters to switch to.
356
+ * @returns {Promsie<void>}
357
+ * */
358
+ switchActiveClusterIds(newActiveClusters: ActiveServices): Promise<void> {
359
+ this.logger.info('services: switching active cluster ids');
360
+
361
+ const newActiveClusterIds = Object.values(newActiveClusters);
362
+
363
+ const missingClusterIds = newActiveClusterIds.some((clusterId) => {
364
+ // if the clusterId does not exist in the catalog, fetch the catalog
365
+ return !this._services.find((service) => service.id === clusterId);
366
+ });
367
+
368
+ if (missingClusterIds) {
369
+ this.logger.warn(
370
+ 'services: some cluster ids do not exist in the catalog, fetching the catalog'
371
+ );
372
+
373
+ // fetch the catalog
374
+ return this.initServiceCatalogs(true);
375
+ }
376
+ // update the active services
377
+ this._updateActiveServices(newActiveClusters);
378
+ this.logger.info('services: active cluster ids updated successfully');
379
+
380
+ return Promise.resolve();
381
+ },
341
382
 
383
+ /**
384
+ * Invalidate cache via mercury notification. If the timestamp is newer than current,
385
+ * refetch catalog services.
386
+ *
387
+ * @param {string} timestamp - The timestamp of invalidation notification.
388
+ * @returns {Promsie<void>}
389
+ * */
390
+ invalidateCache(timestamp: string): Promise<void> {
391
+ this.logger.info('services: invalidate cache, timestamp:', timestamp);
392
+ const lastTime = toNumber(this._getCatalog()?.timestamp) || 0;
393
+ const invalidateTime = toNumber(timestamp) || 0;
394
+ if (invalidateTime > lastTime) {
395
+ this.logger.info('services: invalidateCache, refresh services');
396
+ this.initServiceCatalogs(true);
397
+ }
398
+
399
+ return Promise.resolve();
400
+ },
342
401
  /**
343
402
  * Get user meeting preferences (preferred webex site).
344
403
  *
@@ -446,16 +505,20 @@ const Services = WebexPlugin.extend({
446
505
 
447
506
  /**
448
507
  * Updates a given service group i.e. preauth, signin, postauth with a new hostmap.
449
- * @param {string} serviceGroup - preauth, signin, postauth
450
- * @param {object} hostMap - The new hostmap to update the service group with.
508
+ * @param {ServiceGroup} serviceGroup - preauth, signin, postauth
509
+ * @param {ServiceHostmap} hostMap - The new hostmap to update the service group with.
451
510
  * @returns {Promise<void>}
452
511
  */
453
- updateCatalog(serviceGroup, hostMap) {
512
+ updateCatalog(serviceGroup: ServiceGroup, hostMap: ServiceHostmap): Promise<void> {
454
513
  const catalog = this._getCatalog();
455
514
 
456
515
  const serviceHostMap = this._formatReceivedHostmap(hostMap);
457
516
 
458
- return catalog.updateServiceGroups(serviceGroup, serviceHostMap);
517
+ return catalog.updateServiceGroups(
518
+ serviceGroup,
519
+ serviceHostMap?.services,
520
+ serviceHostMap?.timestamp
521
+ );
459
522
  },
460
523
 
461
524
  /**
@@ -467,7 +530,7 @@ const Services = WebexPlugin.extend({
467
530
  * @param {boolean} forceRefresh - Boolean to bypass u2c cache control header
468
531
  * @returns {Promise<void>}
469
532
  */
470
- collectPreauthCatalog(query, forceRefresh = false) {
533
+ collectPreauthCatalog(query: QueryOptions, forceRefresh = false) {
471
534
  if (!query) {
472
535
  return this.updateServices({
473
536
  from: 'limited',
@@ -486,7 +549,9 @@ const Services = WebexPlugin.extend({
486
549
  * @param {string} param.token - must be a client token
487
550
  * @returns {Promise<void>}
488
551
  */
489
- collectSigninCatalog({email, token, forceRefresh} = {}) {
552
+ collectSigninCatalog(
553
+ {email, token, forceRefresh} = {} as {email: string; token: string; forceRefresh: boolean}
554
+ ): Promise<void> {
490
555
  if (!email) {
491
556
  return Promise.reject(new Error('`email` is required'));
492
557
  }
@@ -507,25 +572,26 @@ const Services = WebexPlugin.extend({
507
572
  * urls.
508
573
  * @returns {void}
509
574
  */
510
- updateCredentialsConfig() {
511
- const {idbroker, identity} = this.list(true);
575
+ updateCredentialsConfig(): void {
576
+ const idbrokerUrl = this.get('idbroker');
577
+ const identityUrl = this.get('identity');
512
578
 
513
- if (idbroker && identity) {
579
+ if (idbrokerUrl && identityUrl) {
514
580
  const {authorizationString, authorizeUrl} = this.webex.config.credentials;
515
581
 
516
582
  // This must be set outside of the setConfig method used to assign the
517
583
  // idbroker and identity url values.
518
584
  this.webex.config.credentials.authorizeUrl = authorizationString
519
585
  ? authorizeUrl
520
- : `${idbroker.replace(trailingSlashes, '')}/idb/oauth2/v1/authorize`;
586
+ : `${idbrokerUrl.replace(trailingSlashes, '')}/idb/oauth2/v1/authorize`;
521
587
 
522
588
  this.webex.setConfig({
523
589
  credentials: {
524
590
  idbroker: {
525
- url: idbroker.replace(trailingSlashes, ''), // remove trailing slash
591
+ url: idbrokerUrl.replace(trailingSlashes, ''), // remove trailing slash
526
592
  },
527
593
  identity: {
528
- url: identity.replace(trailingSlashes, ''), // remove trailing slash
594
+ url: identityUrl.replace(trailingSlashes, ''), // remove trailing slash
529
595
  },
530
596
  },
531
597
  });
@@ -535,11 +601,11 @@ const Services = WebexPlugin.extend({
535
601
  /**
536
602
  * Wait until the service catalog is available,
537
603
  * or reject afte ra timeout of 60 seconds.
538
- * @param {string} serviceGroup
604
+ * @param {ServiceGroup} serviceGroup
539
605
  * @param {number} [timeout] - in seconds
540
606
  * @returns {Promise<void>}
541
607
  */
542
- waitForCatalog(serviceGroup, timeout) {
608
+ waitForCatalog(serviceGroup: ServiceGroup, timeout: number): Promise<void> {
543
609
  const catalog = this._getCatalog();
544
610
  const {supertoken} = this.webex.credentials;
545
611
 
@@ -576,7 +642,15 @@ const Services = WebexPlugin.extend({
576
642
  * @param {WaitForServicePTO} - The parameter transfer object.
577
643
  * @returns {Promise<string>} - Resolves to the priority host of a service.
578
644
  */
579
- waitForService({name, timeout = 5, url}) {
645
+ waitForService({
646
+ name,
647
+ timeout = 5,
648
+ url,
649
+ }: {
650
+ name: string;
651
+ timeout: number;
652
+ url: string;
653
+ }): Promise<string> {
580
654
  const {services} = this.webex.config;
581
655
 
582
656
  // Save memory by grabbing the catalog after there isn't a priortyURL
@@ -587,10 +661,12 @@ const Services = WebexPlugin.extend({
587
661
  );
588
662
 
589
663
  if (fetchFromServiceUrl) {
590
- return Promise.resolve(this._activeServices[name]);
664
+ const clusterId = this._activeServices[name];
665
+
666
+ return Promise.resolve(this.get(clusterId));
591
667
  }
592
668
 
593
- const priorityUrl = this.get(name, true);
669
+ const priorityUrl = this.get(name);
594
670
  const priorityUrlObj = this.getServiceFromUrl(url);
595
671
 
596
672
  if (priorityUrl || priorityUrlObj) {
@@ -617,7 +693,7 @@ const Services = WebexPlugin.extend({
617
693
  catalog
618
694
  .waitForCatalog(catalogGroup, timeout)
619
695
  .then(() => {
620
- const scopedPriorityUrl = this.get(name, true);
696
+ const scopedPriorityUrl = this.get(name);
621
697
  const scopedPrioriryUrlObj = this.getServiceFromUrl(url);
622
698
 
623
699
  if (scopedPriorityUrl || scopedPrioriryUrlObj) {
@@ -641,25 +717,12 @@ const Services = WebexPlugin.extend({
641
717
  * @param {string} uri
642
718
  * @returns {string} uri with the host replaced
643
719
  */
644
- replaceHostFromHostmap(uri) {
645
- const url = new URL(uri);
646
- const hostCatalog = this._services;
647
-
648
- if (!hostCatalog) {
720
+ replaceHostFromHostmap(uri: string): string {
721
+ try {
722
+ return this.convertUrlToPriorityHostUrl(uri);
723
+ } catch {
649
724
  return uri;
650
725
  }
651
-
652
- const host = hostCatalog[url.host];
653
-
654
- if (host && host[0]) {
655
- const newHost = host[0].host;
656
-
657
- url.host = newHost;
658
-
659
- return url.toString();
660
- }
661
-
662
- return uri;
663
726
  },
664
727
 
665
728
  /**
@@ -687,12 +750,18 @@ const Services = WebexPlugin.extend({
687
750
  /**
688
751
  * @private
689
752
  * Organize a received hostmap from a service
690
- * @param {object} serviceHostmap
753
+ * @param {ServiceHostmap} serviceHostmap
691
754
  * catalog endpoint.
692
- * @returns {object}
755
+ * @returns {Array<Service>}
693
756
  */
694
- _formatReceivedHostmap({services, activeServices}) {
695
- const formattedHostmap = services.map((service) => this._formatHostMapEntry(service));
757
+ _formatReceivedHostmap({services, activeServices, timestamp, orgId, format}) {
758
+ const formattedHostmap: ServiceHostmap = {
759
+ activeServices,
760
+ services: services.map((service) => this._formatHostMapEntry(service)),
761
+ timestamp,
762
+ orgId,
763
+ format,
764
+ };
696
765
  this._updateActiveServices(activeServices);
697
766
  this._updateServices(services);
698
767
 
@@ -702,9 +771,9 @@ const Services = WebexPlugin.extend({
702
771
  /**
703
772
  * Get the clusterId associated with a URL string.
704
773
  * @param {string} url
705
- * @returns {string} - Cluster ID of url provided
774
+ * @returns {string | undefined} - Cluster ID of url provided
706
775
  */
707
- getClusterId(url) {
776
+ getClusterId(url: string): string | undefined {
708
777
  const catalog = this._getCatalog();
709
778
 
710
779
  return catalog.findClusterId(url);
@@ -715,13 +784,15 @@ const Services = WebexPlugin.extend({
715
784
  * return an object containing both the name and url of a found service.
716
785
  * @param {object} params
717
786
  * @param {string} params.clusterId - clusterId of found service
718
- * @param {boolean} [params.priorityHost] - returns priority host url if true
719
- * @param {string} [params.serviceGroup] - specify service group
787
+ * @param {ServiceGroup} [params.serviceGroup] - specify service group
720
788
  * @returns {object} service
721
789
  * @returns {string} service.name
722
790
  * @returns {string} service.url
723
791
  */
724
- getServiceFromClusterId(params) {
792
+ getServiceFromClusterId(params: {
793
+ clusterId: string;
794
+ serviceGroup?: ServiceGroup;
795
+ }): {name: string; url: string} | undefined {
725
796
  const catalog = this._getCatalog();
726
797
 
727
798
  return catalog.findServiceFromClusterId(params);
@@ -733,7 +804,7 @@ const Services = WebexPlugin.extend({
733
804
  * If empty, just return the base URL.
734
805
  * @returns {String} url of the service
735
806
  */
736
- getServiceUrlFromClusterId({cluster = 'us'} = {}) {
807
+ getServiceUrlFromClusterId({cluster = 'us'}: {cluster?: string} = {}): string {
737
808
  let clusterId = cluster === 'us' ? DEFAULT_CLUSTER_IDENTIFIER : cluster;
738
809
 
739
810
  // Determine if cluster has service name (non-US clusters from hydra do not)
@@ -758,20 +829,25 @@ const Services = WebexPlugin.extend({
758
829
  * @param {string} url - The url to be validated.
759
830
  * @returns {object} - Service object.
760
831
  * @returns {object.name} - The name of the service found.
761
- * @returns {object.priorityUrl} - The priority url of the found service.
832
+ * @returns {object.priorityUrl} - The default url of the found service.
762
833
  * @returns {object.defaultUrl} - The default url of the found service.
763
834
  */
764
- getServiceFromUrl(url = '') {
765
- const service = this._getCatalog().findServiceUrlFromUrl(url);
835
+ getServiceFromUrl(url = ''): {name: string; priorityUrl: string; defaultUrl: string} | undefined {
836
+ const service = this._getCatalog().findServiceDetailFromUrl(url);
766
837
 
767
838
  if (!service) {
768
839
  return undefined;
769
840
  }
770
841
 
842
+ const priorityUrl = service.get();
843
+ const defaultUrl = new URL(
844
+ service.serviceUrls.find((serviceUrl) => url.startsWith(serviceUrl.baseUrl)).baseUrl
845
+ ).href;
846
+
771
847
  return {
772
- name: service.name,
773
- priorityUrl: service.get(true),
774
- defaultUrl: service.get(),
848
+ name: service.serviceName,
849
+ priorityUrl,
850
+ defaultUrl,
775
851
  };
776
852
  },
777
853
 
@@ -781,7 +857,7 @@ const Services = WebexPlugin.extend({
781
857
  * @param {string} url - The url to match allowed domains against.
782
858
  * @returns {boolean} - True if the url provided is allowed.
783
859
  */
784
- isAllowedDomainUrl(url) {
860
+ isAllowedDomainUrl(url: string): boolean {
785
861
  const catalog = this._getCatalog();
786
862
 
787
863
  return !!catalog.findAllowedDomain(url);
@@ -795,7 +871,7 @@ const Services = WebexPlugin.extend({
795
871
  * @returns {string} a service url that contains the top priority host.
796
872
  * @throws if url isn't a service url
797
873
  */
798
- convertUrlToPriorityHostUrl(url = '') {
874
+ convertUrlToPriorityHostUrl(url = '' as string): string {
799
875
  const data = this.getServiceFromUrl(url);
800
876
 
801
877
  if (!data) {
@@ -818,10 +894,17 @@ const Services = WebexPlugin.extend({
818
894
  * @param {string} [param.token] - used for signin catalog
819
895
  * @returns {Promise<object>}
820
896
  */
821
- _fetchNewServiceHostmap({from, query, token, forceRefresh} = {}) {
897
+ _fetchNewServiceHostmap(
898
+ {from, query, token, forceRefresh} = {} as {
899
+ from: string;
900
+ query: QueryOptions;
901
+ token: string;
902
+ forceRefresh: boolean;
903
+ }
904
+ ): Promise<object> {
822
905
  const service = 'u2c';
823
906
  const resource = from ? `/${from}/catalog` : '/catalog';
824
- const qs = {...(query || {}), format: 'hostmap'};
907
+ const qs = {...(query || {}), format: 'U2CV2'};
825
908
 
826
909
  if (forceRefresh) {
827
910
  qs.timestamp = new Date().getTime();
@@ -832,6 +915,7 @@ const Services = WebexPlugin.extend({
832
915
  service,
833
916
  resource,
834
917
  qs,
918
+ headers: {},
835
919
  };
836
920
 
837
921
  if (token) {
@@ -848,7 +932,7 @@ const Services = WebexPlugin.extend({
848
932
  *
849
933
  * @returns {void}
850
934
  */
851
- initConfig() {
935
+ initConfig(): void {
852
936
  // Get the catalog and destructure the services config.
853
937
  const catalog = this._getCatalog();
854
938
  const {services, fedramp} = this.webex.config;
@@ -905,10 +989,10 @@ const Services = WebexPlugin.extend({
905
989
 
906
990
  /**
907
991
  * Make the initial requests to collect the root catalogs.
908
- *
992
+ * @param {boolean} refresh - Is need force update
909
993
  * @returns {Promise<void, Error>} - Errors if the token is unavailable.
910
994
  */
911
- initServiceCatalogs() {
995
+ initServiceCatalogs(refresh = false): Promise<void> {
912
996
  this.logger.info('services: initializing initial service catalogs');
913
997
 
914
998
  // Destructure the credentials plugin.
@@ -921,12 +1005,12 @@ const Services = WebexPlugin.extend({
921
1005
  // Get the user's OrgId.
922
1006
  .then(() => credentials.getOrgId())
923
1007
  // Begin collecting the preauth/limited catalog.
924
- .then((orgId) => this.collectPreauthCatalog({orgId}))
1008
+ .then((orgId) => this.collectPreauthCatalog({orgId}, refresh))
925
1009
  .then(() => {
926
1010
  // Validate if the token is authorized.
927
1011
  if (credentials.canAuthorize) {
928
1012
  // Attempt to collect the postauth catalog.
929
- return this.updateServices().catch(() => {
1013
+ return this.updateServices({forceRefresh: refresh}).catch(() => {
930
1014
  this.initFailed = true;
931
1015
  this.logger.warn('services: cannot retrieve postauth catalog');
932
1016
  });
@@ -945,7 +1029,7 @@ const Services = WebexPlugin.extend({
945
1029
  * @memberof Services
946
1030
  * @returns {Services}
947
1031
  */
948
- initialize() {
1032
+ initialize(): typeof Services {
949
1033
  const catalog = new ServiceCatalog();
950
1034
  this._catalogs.set(this.webex, catalog);
951
1035
 
@@ -1,3 +1,7 @@
1
+ type ServiceName = string;
2
+ type ClusterId = string;
3
+ export type ServiceGroup = 'discovery' | 'override' | 'preauth' | 'postauth' | 'signin';
4
+
1
5
  export type ServiceUrl = {
2
6
  baseUrl: string;
3
7
  host: string;
@@ -5,9 +9,65 @@ export type ServiceUrl = {
5
9
  failed?: boolean;
6
10
  };
7
11
 
12
+ export type ActiveServices = Record<ServiceName, ClusterId>;
13
+ export type Service = {
14
+ id: ClusterId;
15
+ serviceName: ServiceName;
16
+ serviceUrls: Array<ServiceUrl>;
17
+ };
18
+ export type QueryOptions = {
19
+ email?: string;
20
+ orgId?: string;
21
+ userId?: string;
22
+ timestamp?: number;
23
+ };
24
+
25
+ export interface ServiceHostmap {
26
+ activeServices: ActiveServices;
27
+ services: Array<Service>;
28
+ timestamp: string;
29
+ orgId: string;
30
+ format: string;
31
+ }
32
+
8
33
  export interface IServiceDetail {
9
- id: string;
10
- serviceName: string;
34
+ id: ClusterId;
35
+ serviceName: ServiceName;
11
36
  serviceUrls: Array<ServiceUrl>;
12
37
  failHost(url: string): boolean;
38
+ get(): string;
39
+ }
40
+
41
+ export interface IServiceCatalog {
42
+ serviceGroups: {
43
+ discovery: Array<IServiceDetail>;
44
+ override: Array<IServiceDetail>;
45
+ preauth: Array<IServiceDetail>;
46
+ postauth: Array<IServiceDetail>;
47
+ signin: Array<IServiceDetail>;
48
+ };
49
+ status: {
50
+ discovery: {ready: boolean; collecting: boolean};
51
+ override: {ready: boolean; collecting: boolean};
52
+ preauth: {ready: boolean; collecting: boolean};
53
+ postauth: {ready: boolean; collecting: boolean};
54
+ signin: {ready: boolean; collecting: boolean};
55
+ };
56
+ isReady: boolean;
57
+ allowedDomains: string[];
58
+ clean(): void;
59
+ findClusterId(url: string): string | undefined;
60
+ findServiceFromClusterId(params: {
61
+ clusterId: ClusterId;
62
+ serviceGroup?: ServiceGroup;
63
+ }): {name: string; url: string} | undefined;
64
+ findServiceDetailFromUrl(url: string): IServiceDetail | undefined;
65
+ findAllowedDomain(url: string): string | undefined;
66
+ get(clusterId: ClusterId, serviceGroup?: ServiceGroup): string | undefined;
67
+ getAllowedDomains(): string[];
68
+ markFailedServiceUrl(url: string): string | undefined;
69
+ setAllowedDomains(allowedDomains: string[]): void;
70
+ addAllowedDomains(newAllowedDomains: string[]): void;
71
+ updateServiceGroups(serviceGroup: ServiceGroup, serviceDetails: Array<IServiceDetail>): void;
72
+ waitForCatalog(serviceGroup: ServiceGroup, timeout?: number): Promise<void>;
13
73
  }