@webex/webex-core 2.59.3-next.1 → 2.59.4

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 (189) hide show
  1. package/.eslintrc.js +6 -6
  2. package/README.md +79 -79
  3. package/babel.config.js +3 -3
  4. package/dist/config.js +24 -24
  5. package/dist/config.js.map +1 -1
  6. package/dist/credentials-config.js +56 -56
  7. package/dist/credentials-config.js.map +1 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/interceptors/auth.js +28 -28
  10. package/dist/interceptors/auth.js.map +1 -1
  11. package/dist/interceptors/default-options.js +24 -24
  12. package/dist/interceptors/default-options.js.map +1 -1
  13. package/dist/interceptors/embargo.js +9 -9
  14. package/dist/interceptors/embargo.js.map +1 -1
  15. package/dist/interceptors/network-timing.js +19 -19
  16. package/dist/interceptors/network-timing.js.map +1 -1
  17. package/dist/interceptors/payload-transformer.js +19 -19
  18. package/dist/interceptors/payload-transformer.js.map +1 -1
  19. package/dist/interceptors/rate-limit.js +40 -40
  20. package/dist/interceptors/rate-limit.js.map +1 -1
  21. package/dist/interceptors/redirect.js +13 -13
  22. package/dist/interceptors/redirect.js.map +1 -1
  23. package/dist/interceptors/request-event.js +23 -23
  24. package/dist/interceptors/request-event.js.map +1 -1
  25. package/dist/interceptors/request-logger.js +13 -13
  26. package/dist/interceptors/request-logger.js.map +1 -1
  27. package/dist/interceptors/request-timing.js +23 -23
  28. package/dist/interceptors/request-timing.js.map +1 -1
  29. package/dist/interceptors/response-logger.js +19 -19
  30. package/dist/interceptors/response-logger.js.map +1 -1
  31. package/dist/interceptors/user-agent.js +29 -29
  32. package/dist/interceptors/user-agent.js.map +1 -1
  33. package/dist/interceptors/webex-tracking-id.js +15 -15
  34. package/dist/interceptors/webex-tracking-id.js.map +1 -1
  35. package/dist/interceptors/webex-user-agent.js +13 -13
  36. package/dist/interceptors/webex-user-agent.js.map +1 -1
  37. package/dist/lib/batcher.js +83 -83
  38. package/dist/lib/batcher.js.map +1 -1
  39. package/dist/lib/credentials/credentials.js +103 -103
  40. package/dist/lib/credentials/credentials.js.map +1 -1
  41. package/dist/lib/credentials/grant-errors.js +17 -17
  42. package/dist/lib/credentials/grant-errors.js.map +1 -1
  43. package/dist/lib/credentials/index.js +2 -2
  44. package/dist/lib/credentials/index.js.map +1 -1
  45. package/dist/lib/credentials/scope.js +11 -11
  46. package/dist/lib/credentials/scope.js.map +1 -1
  47. package/dist/lib/credentials/token-collection.js +2 -2
  48. package/dist/lib/credentials/token-collection.js.map +1 -1
  49. package/dist/lib/credentials/token.js +145 -145
  50. package/dist/lib/credentials/token.js.map +1 -1
  51. package/dist/lib/page.js +49 -49
  52. package/dist/lib/page.js.map +1 -1
  53. package/dist/lib/services/constants.js.map +1 -1
  54. package/dist/lib/services/index.js +2 -2
  55. package/dist/lib/services/index.js.map +1 -1
  56. package/dist/lib/services/interceptors/server-error.js +9 -9
  57. package/dist/lib/services/interceptors/server-error.js.map +1 -1
  58. package/dist/lib/services/interceptors/service.js +24 -24
  59. package/dist/lib/services/interceptors/service.js.map +1 -1
  60. package/dist/lib/services/metrics.js.map +1 -1
  61. package/dist/lib/services/service-catalog.js +104 -104
  62. package/dist/lib/services/service-catalog.js.map +1 -1
  63. package/dist/lib/services/service-fed-ramp.js.map +1 -1
  64. package/dist/lib/services/service-host.js +134 -134
  65. package/dist/lib/services/service-host.js.map +1 -1
  66. package/dist/lib/services/service-registry.js +175 -175
  67. package/dist/lib/services/service-registry.js.map +1 -1
  68. package/dist/lib/services/service-state.js +38 -38
  69. package/dist/lib/services/service-state.js.map +1 -1
  70. package/dist/lib/services/service-url.js +31 -31
  71. package/dist/lib/services/service-url.js.map +1 -1
  72. package/dist/lib/services/services.js +245 -245
  73. package/dist/lib/services/services.js.map +1 -1
  74. package/dist/lib/stateless-webex-plugin.js +28 -28
  75. package/dist/lib/stateless-webex-plugin.js.map +1 -1
  76. package/dist/lib/storage/decorators.js +27 -27
  77. package/dist/lib/storage/decorators.js.map +1 -1
  78. package/dist/lib/storage/errors.js +4 -4
  79. package/dist/lib/storage/errors.js.map +1 -1
  80. package/dist/lib/storage/index.js.map +1 -1
  81. package/dist/lib/storage/make-webex-plugin-store.js +44 -44
  82. package/dist/lib/storage/make-webex-plugin-store.js.map +1 -1
  83. package/dist/lib/storage/make-webex-store.js +40 -40
  84. package/dist/lib/storage/make-webex-store.js.map +1 -1
  85. package/dist/lib/storage/memory-store-adapter.js +9 -9
  86. package/dist/lib/storage/memory-store-adapter.js.map +1 -1
  87. package/dist/lib/webex-core-plugin-mixin.js +13 -13
  88. package/dist/lib/webex-core-plugin-mixin.js.map +1 -1
  89. package/dist/lib/webex-http-error.js +9 -9
  90. package/dist/lib/webex-http-error.js.map +1 -1
  91. package/dist/lib/webex-internal-core-plugin-mixin.js +13 -13
  92. package/dist/lib/webex-internal-core-plugin-mixin.js.map +1 -1
  93. package/dist/lib/webex-plugin.js +36 -36
  94. package/dist/lib/webex-plugin.js.map +1 -1
  95. package/dist/plugins/logger.js +9 -9
  96. package/dist/plugins/logger.js.map +1 -1
  97. package/dist/webex-core.js +104 -104
  98. package/dist/webex-core.js.map +1 -1
  99. package/dist/webex-internal-core.js +12 -12
  100. package/dist/webex-internal-core.js.map +1 -1
  101. package/jest.config.js +3 -3
  102. package/package.json +19 -20
  103. package/process +1 -1
  104. package/src/config.js +90 -90
  105. package/src/credentials-config.js +212 -212
  106. package/src/index.js +62 -62
  107. package/src/interceptors/auth.js +186 -186
  108. package/src/interceptors/default-options.js +55 -55
  109. package/src/interceptors/embargo.js +43 -43
  110. package/src/interceptors/network-timing.js +54 -54
  111. package/src/interceptors/payload-transformer.js +55 -55
  112. package/src/interceptors/rate-limit.js +169 -169
  113. package/src/interceptors/redirect.js +106 -106
  114. package/src/interceptors/request-event.js +93 -93
  115. package/src/interceptors/request-logger.js +78 -78
  116. package/src/interceptors/request-timing.js +65 -65
  117. package/src/interceptors/response-logger.js +98 -98
  118. package/src/interceptors/user-agent.js +77 -77
  119. package/src/interceptors/webex-tracking-id.js +73 -73
  120. package/src/interceptors/webex-user-agent.js +79 -79
  121. package/src/lib/batcher.js +307 -307
  122. package/src/lib/credentials/credentials.js +552 -552
  123. package/src/lib/credentials/grant-errors.js +92 -92
  124. package/src/lib/credentials/index.js +16 -16
  125. package/src/lib/credentials/scope.js +34 -34
  126. package/src/lib/credentials/token-collection.js +17 -17
  127. package/src/lib/credentials/token.js +559 -559
  128. package/src/lib/page.js +159 -159
  129. package/src/lib/services/constants.js +9 -9
  130. package/src/lib/services/index.js +26 -26
  131. package/src/lib/services/interceptors/server-error.js +48 -48
  132. package/src/lib/services/interceptors/service.js +101 -101
  133. package/src/lib/services/metrics.js +4 -4
  134. package/src/lib/services/service-catalog.js +435 -435
  135. package/src/lib/services/service-fed-ramp.js +4 -4
  136. package/src/lib/services/service-host.js +267 -267
  137. package/src/lib/services/service-registry.js +465 -465
  138. package/src/lib/services/service-state.js +78 -78
  139. package/src/lib/services/service-url.js +124 -124
  140. package/src/lib/services/services.js +1018 -1018
  141. package/src/lib/stateless-webex-plugin.js +98 -98
  142. package/src/lib/storage/decorators.js +220 -220
  143. package/src/lib/storage/errors.js +15 -15
  144. package/src/lib/storage/index.js +10 -10
  145. package/src/lib/storage/make-webex-plugin-store.js +211 -211
  146. package/src/lib/storage/make-webex-store.js +140 -140
  147. package/src/lib/storage/memory-store-adapter.js +79 -79
  148. package/src/lib/webex-core-plugin-mixin.js +114 -114
  149. package/src/lib/webex-http-error.js +61 -61
  150. package/src/lib/webex-internal-core-plugin-mixin.js +107 -107
  151. package/src/lib/webex-plugin.js +222 -222
  152. package/src/plugins/logger.js +60 -60
  153. package/src/webex-core.js +745 -745
  154. package/src/webex-internal-core.js +46 -46
  155. package/test/integration/spec/credentials/credentials.js +139 -139
  156. package/test/integration/spec/credentials/token.js +102 -102
  157. package/test/integration/spec/services/service-catalog.js +838 -838
  158. package/test/integration/spec/services/services.js +1221 -1221
  159. package/test/integration/spec/webex-core.js +178 -178
  160. package/test/unit/spec/_setup.js +44 -44
  161. package/test/unit/spec/credentials/credentials.js +1017 -1017
  162. package/test/unit/spec/credentials/token.js +441 -441
  163. package/test/unit/spec/interceptors/auth.js +521 -521
  164. package/test/unit/spec/interceptors/default-options.js +84 -84
  165. package/test/unit/spec/interceptors/embargo.js +144 -144
  166. package/test/unit/spec/interceptors/network-timing.js +49 -49
  167. package/test/unit/spec/interceptors/payload-transformer.js +155 -155
  168. package/test/unit/spec/interceptors/rate-limit.js +302 -302
  169. package/test/unit/spec/interceptors/redirect.js +102 -102
  170. package/test/unit/spec/interceptors/request-timing.js +92 -92
  171. package/test/unit/spec/interceptors/user-agent.js +76 -76
  172. package/test/unit/spec/interceptors/webex-tracking-id.js +76 -76
  173. package/test/unit/spec/interceptors/webex-user-agent.js +159 -159
  174. package/test/unit/spec/lib/batcher.js +330 -330
  175. package/test/unit/spec/lib/page.js +148 -148
  176. package/test/unit/spec/lib/webex-plugin.js +48 -48
  177. package/test/unit/spec/services/interceptors/server-error.js +204 -204
  178. package/test/unit/spec/services/interceptors/service.js +188 -188
  179. package/test/unit/spec/services/service-catalog.js +194 -194
  180. package/test/unit/spec/services/service-host.js +260 -260
  181. package/test/unit/spec/services/service-registry.js +747 -747
  182. package/test/unit/spec/services/service-state.js +60 -60
  183. package/test/unit/spec/services/service-url.js +258 -258
  184. package/test/unit/spec/services/services.js +348 -348
  185. package/test/unit/spec/storage/persist.js +50 -50
  186. package/test/unit/spec/storage/storage-adapter.js +12 -12
  187. package/test/unit/spec/storage/wait-for-value.js +81 -81
  188. package/test/unit/spec/webex-core.js +253 -253
  189. package/test/unit/spec/webex-internal-core.js +91 -91
@@ -1,465 +1,465 @@
1
- import {SERVICE_CATALOGS, SERVICE_CATALOGS_ENUM_TYPES} from './constants';
2
- import ServiceHost from './service-host';
3
-
4
- /**
5
- * The parameter transfer object for {@link ServiceRegistry#mapRemoteCatalog}.
6
- * This object is shaped to match the object returned from the **U2C** service.
7
- *
8
- * @typedef {Record<string, string>} RSL
9
- * @typedef {Record<string, Array<Record<string, number | string>>>} RHC
10
- *
11
- * @typedef {Object} MapRemoteCatalogPTO
12
- * @property {string} MapRemoteCatalogPTO.catalog - Service catalog name.
13
- * @property {RSL} MapRemoteCatalogPTO.serviceLinks - Service links.
14
- * @property {RHC} MapRemoteCatalogPTO.hostCatalog - Service host catalog.
15
- */
16
-
17
- /**
18
- * Service manipulation filter object for retrieving services within the
19
- * {@link ServiceRegistry} class.
20
- *
21
- * @typedef {Object} HostFilter
22
- * @property {boolean} [HostFilter.active] - Active state to filter.
23
- * @property {Array<string> | string} [HostFilter.catalog] - Catalogs to filter.
24
- * @property {Array<string> | string} [HostFilter.cluster] - Clusters to filter.
25
- * @property {boolean} [HostFilter.local] - Filter to the user's home cluster.
26
- * @property {boolean} [HostFilter.priority] - Filter for the highest priority.
27
- * @property {Array<string> | string} [HostFilter.service] - Services to filter.
28
- * @property {Array<string> | string} [HostFilter.url] - URL to filter.
29
- */
30
-
31
- /**
32
- * @class
33
- * @classdesc - Manages a collection of {@link ServiceHost} class objects.
34
- */
35
- export default class ServiceRegistry {
36
- /**
37
- * Generate a new {@link ServiceHost}.
38
- *
39
- * @public
40
- * @constructor
41
- * @memberof ServiceHost
42
- */
43
- constructor() {
44
- /**
45
- * The collection of managed {@link ServiceHost}s.
46
- *
47
- * @instance
48
- * @type {Array<ServiceHost>}
49
- * @private
50
- * @memberof ServiceRegistry
51
- */
52
- this.hosts = [];
53
- }
54
-
55
- /**
56
- * An active, local, and priority mapped record of the current
57
- * {@link ServiceCatalog#hosts}.
58
- *
59
- * @public
60
- * @memberof ServiceCatalog
61
- * @type {Record<string, string>}
62
- */
63
- get map() {
64
- // Get a list of active, local, and priority-mapped hosts.
65
- return this.find({
66
- active: true,
67
- local: true,
68
- priority: true,
69
- }).reduce((map, host) => {
70
- // Generate a new object to assign the existing map.
71
- const hostReference = {};
72
-
73
- // Assign the key:value pair for the service and url.
74
- hostReference[host.service] = host.url;
75
-
76
- // Assign the reference to the map and return.
77
- return {...map, ...hostReference};
78
- }, {});
79
- }
80
-
81
- /**
82
- * Removes a collection of {@link ServiceHost} class objects from the
83
- * {@link ServiceRegistry#hosts} array based on the provided
84
- * {@link HostFilter}.
85
- *
86
- * @public
87
- * @memberof ServiceRegistry
88
- * @param {HostFilter} filter - The inclusive filter for hosts to remove.
89
- * @returns {Array<ServiceHost>} - The removed {@link ServiceHost}s.
90
- */
91
- clear(filter) {
92
- // Collect a list of hosts to remove based on the provided filter.
93
- const removing = this.find(filter);
94
-
95
- // Remove the hosts from the array.
96
- this.hosts = this.hosts.filter((host) => !removing.includes(host));
97
-
98
- // Return the removed hosts.
99
- return removing;
100
- }
101
-
102
- /**
103
- * Mark a collection of {@link ServiceHost} class objects from the
104
- * {@link ServiceRegistry#hosts} array as failed based on the provided
105
- * {@link HostFilter}.
106
- *
107
- * @public
108
- * @memberof ServiceRegistry
109
- * @param {HostFilter} filter - The inclusive filter for hosts to mark failed.
110
- * @returns {Array<ServiceHost>} - The {@link ServiceHost}s marked failed.
111
- */
112
- failed(filter) {
113
- // Collect a list of hosts to mark as failed based on the provided filter.
114
- const failing = this.find(filter);
115
-
116
- // Mark the hosts from the array as failed.
117
- failing.forEach((host) => {
118
- host.setStatus({failed: true});
119
- });
120
-
121
- // Return the marked hosts.
122
- return failing;
123
- }
124
-
125
- /**
126
- * Filter the {@link ServiceRegistry#hosts} array against their active states.
127
- *
128
- * @private
129
- * @memberof ServiceRegistry
130
- * @param {boolean} [active] - Filter for the host state.
131
- * @returns {Array<ServiceHost>} - The filtered host array.
132
- */
133
- filterActive(active) {
134
- // Filter the host array if the active requirement is true.
135
- return typeof active === 'boolean'
136
- ? this.hosts.filter((host) => host.active === active)
137
- : [...this.hosts];
138
- }
139
-
140
- /**
141
- * Filter the {@link ServiceRegistry#hosts} array against their assigned
142
- * catalog values.
143
- *
144
- * @private
145
- * @memberof ServiceRegistry
146
- * @param {Array<string> | string} [catalog] - Catalogs to filter.
147
- * @returns {Array<ServiceHost>} - The filtered host array.
148
- */
149
- filterCatalog(catalog = []) {
150
- // Generate a catalog names array based on the provided catalog param.
151
- const catalogs = (Array.isArray(catalog) ? catalog : [catalog]).map(
152
- (catalogId) =>
153
- ServiceRegistry.mapCatalogName({
154
- id: catalogId,
155
- type: SERVICE_CATALOGS_ENUM_TYPES.STRING,
156
- }) || catalogId
157
- );
158
-
159
- // Filter the host array against the catalog names array.
160
- return catalogs.length > 0
161
- ? this.hosts.filter((host) => catalogs.includes(host.catalog))
162
- : [...this.hosts];
163
- }
164
-
165
- /**
166
- * Filter the {@link ServiceRegistry#hosts} array against their assigned
167
- * cluster values.
168
- *
169
- * @private
170
- * @memberof ServiceRegistry
171
- * @param {Array<string> | string} [cluster] - Clusters to filter for.
172
- * @returns {Array<ServiceHost>} - The filtered host array.
173
- */
174
- filterCluster(cluster = []) {
175
- // Generate an array of clusters regardless of parameter type.
176
- const clusters = Array.isArray(cluster) ? cluster : [cluster];
177
-
178
- // Filter the host array against the provided clusters.
179
- return clusters.length > 0
180
- ? this.hosts.filter((host) => clusters.includes(host.id))
181
- : [...this.hosts];
182
- }
183
-
184
- /**
185
- * Filter the {@link ServiceRegistry#hosts} array against their location in
186
- * reference to the authenticated user.
187
- *
188
- * @private
189
- * @memberof ServiceRegistry
190
- * @param {boolean} [local] - Filter for the host location.
191
- * @returns {Array<ServiceHost>} - The filtered host array.
192
- */
193
- filterLocal(local) {
194
- return typeof local === 'boolean'
195
- ? this.hosts.filter((host) => host.local === local)
196
- : [...this.hosts];
197
- }
198
-
199
- /**
200
- * Filter the {@link ServiceRegistry#hosts} array for the highest priority
201
- * hosts for each specific service.
202
- *
203
- * @private
204
- * @memberof ServiceRegistry
205
- * @param {boolean} [priority] - Filter for the highest priority
206
- * @returns {Array<ServiceHost>} - The filtered host array.
207
- */
208
- filterPriority(priority) {
209
- return priority
210
- ? this.hosts.reduce((filteredHosts, currentHost) => {
211
- // Validate that the current host is not active.
212
- if (!currentHost.active) {
213
- return filteredHosts;
214
- }
215
-
216
- // Determine if the filtered hosts array contains a host from the same
217
- // host group.
218
- const foundHost = filteredHosts.find((host) => host.hostGroup === currentHost.hostGroup);
219
-
220
- // Validate if a host was found.
221
- if (!foundHost) {
222
- filteredHosts.push(currentHost);
223
-
224
- return filteredHosts;
225
- }
226
-
227
- // Map the found host's catalog to its priority value.
228
- const foundHostCatalogPriority = ServiceRegistry.mapCatalogName({
229
- id: foundHost.catalog,
230
- type: SERVICE_CATALOGS_ENUM_TYPES.NUMBER,
231
- });
232
-
233
- // Map the current host's catalog to its priority value.
234
- const currentHostCatalogPriority = ServiceRegistry.mapCatalogName({
235
- id: currentHost.catalog,
236
- type: SERVICE_CATALOGS_ENUM_TYPES.NUMBER,
237
- });
238
-
239
- // Validate if the found host has a lower priority than the current
240
- // host.
241
- if (
242
- foundHostCatalogPriority < currentHostCatalogPriority ||
243
- foundHost.priority < currentHost.priority
244
- ) {
245
- filteredHosts.splice(filteredHosts.indexOf(foundHost, 1));
246
- filteredHosts.push(currentHost);
247
- }
248
-
249
- return filteredHosts;
250
- }, [])
251
- : [...this.hosts];
252
- }
253
-
254
- /**
255
- * Filter the {@link ServiceRegistry#hosts} array for hosts with a specified
256
- * set of service names.
257
- *
258
- * @private
259
- * @memberof ServiceRegistry
260
- * @param {Array<string> | string} [service] - Services to filter.
261
- * @returns {Array<ServiceHost>} - The filtered host array.
262
- */
263
- filterService(service = []) {
264
- // Generate an array of services regardless of parameter type.
265
- const services = Array.isArray(service) ? service : [service];
266
-
267
- // Filter the host array against the provided services.
268
- return services.length > 0
269
- ? this.hosts.filter((host) => services.includes(host.service))
270
- : [...this.hosts];
271
- }
272
-
273
- /**
274
- * Filter the {@link ServiceRegistry#hosts} array for hosts with a specified
275
- * set of URLs.
276
- *
277
- * @private
278
- * @memberof ServiceRegistry
279
- * @param {Array<string> | string} [url] - URL to filter.
280
- * @returns {Array<ServiceHost>} - The filter host array.
281
- */
282
- filterUrl(url = []) {
283
- // Generate an array of URLs regardless of the parameter type.
284
- const urls = Array.isArray(url) ? url : [url];
285
-
286
- // Filter the host array against the provided URLs.
287
- return urls.length > 0 ? this.hosts.filter((host) => urls.includes(host.url)) : [...this.hosts];
288
- }
289
-
290
- /**
291
- * Get an array of {@link ServiceHost}s based on a provided
292
- * {@link HostFilter} from the {@link ServiceRegistry#hosts} array.
293
- *
294
- * @public
295
- * @memberof ServiceRegistry
296
- * @param {HostFilter} [filter] - The inclusive filter for hosts to find.
297
- * @returns {Array<ServiceHost>} - The filtered hosts.
298
- */
299
- find({active, catalog, cluster, local, priority, service, url} = {}) {
300
- return this.hosts.filter(
301
- (host) =>
302
- this.filterActive(active).includes(host) &&
303
- this.filterCatalog(catalog).includes(host) &&
304
- this.filterCluster(cluster).includes(host) &&
305
- this.filterLocal(local).includes(host) &&
306
- this.filterPriority(priority).includes(host) &&
307
- this.filterService(service).includes(host) &&
308
- this.filterUrl(url).includes(host)
309
- );
310
- }
311
-
312
- /**
313
- * Load a formatted array of {@link ServiceHost} constructor parameter
314
- * transfer objects as instances of {@link ServiceHost} class objects to the
315
- * {@link ServiceRegistry#hosts} array.
316
- *
317
- * @public
318
- * @memberof ServiceRegistry
319
- * @param {Array<ServiceHost.ConstructorPTO>} hosts
320
- * @returns {this}
321
- */
322
- load(hosts = []) {
323
- // Validate that the provided hosts are eligible to be loaded.
324
- const validHosts = hosts.filter(
325
- (host) =>
326
- !!ServiceRegistry.mapCatalogName({
327
- id: host.catalog,
328
- type: SERVICE_CATALOGS_ENUM_TYPES.STRING,
329
- })
330
- );
331
-
332
- // Load the eligible hosts.
333
- this.hosts.push(...validHosts.map((loadableHost) => new ServiceHost(loadableHost)));
334
-
335
- return this;
336
- }
337
-
338
- /**
339
- * Mark a collection of {@link ServiceHost} class objects from the
340
- * {@link ServiceRegistry#hosts} array as replaced based on the provided
341
- * {@link HostFilter}.
342
- *
343
- * @public
344
- * @memberof ServiceRegistry
345
- * @param {HostFilter} filter - The inclusive filter to mark replaced.
346
- * @returns {Array<ServiceHost>} - The {@link ServiceHost}s marked replaced.
347
- */
348
- replaced(filter) {
349
- // Collect a list of hosts to mark as replaced based on the provided filter.
350
- const replacing = this.find(filter);
351
-
352
- // Mark the hosts from the array as replaced.
353
- replacing.forEach((host) => {
354
- host.setStatus({replaced: true});
355
- });
356
-
357
- // Return the marked hosts.
358
- return replacing;
359
- }
360
-
361
- /**
362
- * Reset the failed status of a collection of {@link ServiceHost} class
363
- * objects from the {@link ServiceRegistry#hosts} array based on the provided
364
- * {@link HostFilter}.
365
- *
366
- * @public
367
- * @memberof ServiceRegistry
368
- * @param {HostFilter} filter - The inclusive filter of hosts to reset.
369
- * @returns {Array<ServiceHost>} - The {@link ServiceHost}s that reset.
370
- */
371
- reset(filter) {
372
- // Collect a list of hosts to mark as replaced based on the provided filter.
373
- const resetting = this.find(filter);
374
-
375
- // Mark the hosts from the array as replaced.
376
- resetting.forEach((host) => {
377
- host.setStatus({failed: false});
378
- });
379
-
380
- // Return the marked hosts.
381
- return resetting;
382
- }
383
-
384
- /**
385
- * Convert a {@link SERVICE_CATALOGS} identifier or value to its associated
386
- * idenfier or value.
387
- *
388
- * @public
389
- * @static
390
- * @memberof ServiceRegistry
391
- * @param {Object} pto - The parameter transfer object.
392
- * @property {string | number} pto.id - The identifier to convert in the enum.
393
- * @property {SERVICE_CATALOGS_ENUM_TYPES} pto.type - The desired output.
394
- * @returns {string|number} - The matching enum value or index.
395
- */
396
- static mapCatalogName({id, type}) {
397
- // Validate that the id is a number.
398
- if (typeof id === 'number') {
399
- // Validate that the desired type is a number.
400
- if (type === SERVICE_CATALOGS_ENUM_TYPES.NUMBER) {
401
- return SERVICE_CATALOGS[id] !== undefined ? id : undefined;
402
- }
403
-
404
- // Validate that the desired type is a string.
405
- if (type === SERVICE_CATALOGS_ENUM_TYPES.STRING) {
406
- return SERVICE_CATALOGS[id];
407
- }
408
- }
409
-
410
- // Validate that the id is a string.
411
- if (typeof id === 'string') {
412
- // Validate that the desired type is a string.
413
- if (type === SERVICE_CATALOGS_ENUM_TYPES.STRING) {
414
- return SERVICE_CATALOGS.includes(id) ? id : undefined;
415
- }
416
-
417
- // Validate that the desired type is a number.
418
- if (type === SERVICE_CATALOGS_ENUM_TYPES.NUMBER) {
419
- return SERVICE_CATALOGS.includes(id) ? SERVICE_CATALOGS.indexOf(id) : undefined;
420
- }
421
- }
422
-
423
- return undefined;
424
- }
425
-
426
- /**
427
- * Generate a formatted array based on the object received from the **U2C**
428
- * service for usage in the {@link ServiceRegistry#load} method.
429
- *
430
- * @public
431
- * @static
432
- * @memberof ServiceRegistry
433
- * @param {MapRemoteCatalogPTO} pto - The parameter transfer object.
434
- * @throws - If the target catalog does not exist.
435
- * @returns {Array<ServiceHost#ServiceHostConstructorPTO>}
436
- */
437
- static mapRemoteCatalog({catalog, hostCatalog, serviceLinks}) {
438
- // Collect the service catalog name if needed.
439
- const catalogIndex = ServiceRegistry.mapCatalogName({
440
- id: catalog,
441
- type: SERVICE_CATALOGS_ENUM_TYPES.STRING,
442
- });
443
-
444
- // Validate that the target catalog exists.
445
- if (!SERVICE_CATALOGS.includes(catalogIndex)) {
446
- throw new Error(`service-catalogs: '${catalog}' is not a valid catalog`);
447
- }
448
-
449
- // Map the remote catalog to a mountable host array.
450
- return Object.keys(hostCatalog).reduce((output, key) => {
451
- output.push(
452
- ...hostCatalog[key].map((host) => ({
453
- catalog: catalogIndex,
454
- defaultUri: serviceLinks[host.id.split(':')[3]],
455
- hostGroup: key,
456
- id: host.id,
457
- priority: host.priority,
458
- uri: host.host,
459
- }))
460
- );
461
-
462
- return output;
463
- }, []);
464
- }
465
- }
1
+ import {SERVICE_CATALOGS, SERVICE_CATALOGS_ENUM_TYPES} from './constants';
2
+ import ServiceHost from './service-host';
3
+
4
+ /**
5
+ * The parameter transfer object for {@link ServiceRegistry#mapRemoteCatalog}.
6
+ * This object is shaped to match the object returned from the **U2C** service.
7
+ *
8
+ * @typedef {Record<string, string>} RSL
9
+ * @typedef {Record<string, Array<Record<string, number | string>>>} RHC
10
+ *
11
+ * @typedef {Object} MapRemoteCatalogPTO
12
+ * @property {string} MapRemoteCatalogPTO.catalog - Service catalog name.
13
+ * @property {RSL} MapRemoteCatalogPTO.serviceLinks - Service links.
14
+ * @property {RHC} MapRemoteCatalogPTO.hostCatalog - Service host catalog.
15
+ */
16
+
17
+ /**
18
+ * Service manipulation filter object for retrieving services within the
19
+ * {@link ServiceRegistry} class.
20
+ *
21
+ * @typedef {Object} HostFilter
22
+ * @property {boolean} [HostFilter.active] - Active state to filter.
23
+ * @property {Array<string> | string} [HostFilter.catalog] - Catalogs to filter.
24
+ * @property {Array<string> | string} [HostFilter.cluster] - Clusters to filter.
25
+ * @property {boolean} [HostFilter.local] - Filter to the user's home cluster.
26
+ * @property {boolean} [HostFilter.priority] - Filter for the highest priority.
27
+ * @property {Array<string> | string} [HostFilter.service] - Services to filter.
28
+ * @property {Array<string> | string} [HostFilter.url] - URL to filter.
29
+ */
30
+
31
+ /**
32
+ * @class
33
+ * @classdesc - Manages a collection of {@link ServiceHost} class objects.
34
+ */
35
+ export default class ServiceRegistry {
36
+ /**
37
+ * Generate a new {@link ServiceHost}.
38
+ *
39
+ * @public
40
+ * @constructor
41
+ * @memberof ServiceHost
42
+ */
43
+ constructor() {
44
+ /**
45
+ * The collection of managed {@link ServiceHost}s.
46
+ *
47
+ * @instance
48
+ * @type {Array<ServiceHost>}
49
+ * @private
50
+ * @memberof ServiceRegistry
51
+ */
52
+ this.hosts = [];
53
+ }
54
+
55
+ /**
56
+ * An active, local, and priority mapped record of the current
57
+ * {@link ServiceCatalog#hosts}.
58
+ *
59
+ * @public
60
+ * @memberof ServiceCatalog
61
+ * @type {Record<string, string>}
62
+ */
63
+ get map() {
64
+ // Get a list of active, local, and priority-mapped hosts.
65
+ return this.find({
66
+ active: true,
67
+ local: true,
68
+ priority: true,
69
+ }).reduce((map, host) => {
70
+ // Generate a new object to assign the existing map.
71
+ const hostReference = {};
72
+
73
+ // Assign the key:value pair for the service and url.
74
+ hostReference[host.service] = host.url;
75
+
76
+ // Assign the reference to the map and return.
77
+ return {...map, ...hostReference};
78
+ }, {});
79
+ }
80
+
81
+ /**
82
+ * Removes a collection of {@link ServiceHost} class objects from the
83
+ * {@link ServiceRegistry#hosts} array based on the provided
84
+ * {@link HostFilter}.
85
+ *
86
+ * @public
87
+ * @memberof ServiceRegistry
88
+ * @param {HostFilter} filter - The inclusive filter for hosts to remove.
89
+ * @returns {Array<ServiceHost>} - The removed {@link ServiceHost}s.
90
+ */
91
+ clear(filter) {
92
+ // Collect a list of hosts to remove based on the provided filter.
93
+ const removing = this.find(filter);
94
+
95
+ // Remove the hosts from the array.
96
+ this.hosts = this.hosts.filter((host) => !removing.includes(host));
97
+
98
+ // Return the removed hosts.
99
+ return removing;
100
+ }
101
+
102
+ /**
103
+ * Mark a collection of {@link ServiceHost} class objects from the
104
+ * {@link ServiceRegistry#hosts} array as failed based on the provided
105
+ * {@link HostFilter}.
106
+ *
107
+ * @public
108
+ * @memberof ServiceRegistry
109
+ * @param {HostFilter} filter - The inclusive filter for hosts to mark failed.
110
+ * @returns {Array<ServiceHost>} - The {@link ServiceHost}s marked failed.
111
+ */
112
+ failed(filter) {
113
+ // Collect a list of hosts to mark as failed based on the provided filter.
114
+ const failing = this.find(filter);
115
+
116
+ // Mark the hosts from the array as failed.
117
+ failing.forEach((host) => {
118
+ host.setStatus({failed: true});
119
+ });
120
+
121
+ // Return the marked hosts.
122
+ return failing;
123
+ }
124
+
125
+ /**
126
+ * Filter the {@link ServiceRegistry#hosts} array against their active states.
127
+ *
128
+ * @private
129
+ * @memberof ServiceRegistry
130
+ * @param {boolean} [active] - Filter for the host state.
131
+ * @returns {Array<ServiceHost>} - The filtered host array.
132
+ */
133
+ filterActive(active) {
134
+ // Filter the host array if the active requirement is true.
135
+ return typeof active === 'boolean'
136
+ ? this.hosts.filter((host) => host.active === active)
137
+ : [...this.hosts];
138
+ }
139
+
140
+ /**
141
+ * Filter the {@link ServiceRegistry#hosts} array against their assigned
142
+ * catalog values.
143
+ *
144
+ * @private
145
+ * @memberof ServiceRegistry
146
+ * @param {Array<string> | string} [catalog] - Catalogs to filter.
147
+ * @returns {Array<ServiceHost>} - The filtered host array.
148
+ */
149
+ filterCatalog(catalog = []) {
150
+ // Generate a catalog names array based on the provided catalog param.
151
+ const catalogs = (Array.isArray(catalog) ? catalog : [catalog]).map(
152
+ (catalogId) =>
153
+ ServiceRegistry.mapCatalogName({
154
+ id: catalogId,
155
+ type: SERVICE_CATALOGS_ENUM_TYPES.STRING,
156
+ }) || catalogId
157
+ );
158
+
159
+ // Filter the host array against the catalog names array.
160
+ return catalogs.length > 0
161
+ ? this.hosts.filter((host) => catalogs.includes(host.catalog))
162
+ : [...this.hosts];
163
+ }
164
+
165
+ /**
166
+ * Filter the {@link ServiceRegistry#hosts} array against their assigned
167
+ * cluster values.
168
+ *
169
+ * @private
170
+ * @memberof ServiceRegistry
171
+ * @param {Array<string> | string} [cluster] - Clusters to filter for.
172
+ * @returns {Array<ServiceHost>} - The filtered host array.
173
+ */
174
+ filterCluster(cluster = []) {
175
+ // Generate an array of clusters regardless of parameter type.
176
+ const clusters = Array.isArray(cluster) ? cluster : [cluster];
177
+
178
+ // Filter the host array against the provided clusters.
179
+ return clusters.length > 0
180
+ ? this.hosts.filter((host) => clusters.includes(host.id))
181
+ : [...this.hosts];
182
+ }
183
+
184
+ /**
185
+ * Filter the {@link ServiceRegistry#hosts} array against their location in
186
+ * reference to the authenticated user.
187
+ *
188
+ * @private
189
+ * @memberof ServiceRegistry
190
+ * @param {boolean} [local] - Filter for the host location.
191
+ * @returns {Array<ServiceHost>} - The filtered host array.
192
+ */
193
+ filterLocal(local) {
194
+ return typeof local === 'boolean'
195
+ ? this.hosts.filter((host) => host.local === local)
196
+ : [...this.hosts];
197
+ }
198
+
199
+ /**
200
+ * Filter the {@link ServiceRegistry#hosts} array for the highest priority
201
+ * hosts for each specific service.
202
+ *
203
+ * @private
204
+ * @memberof ServiceRegistry
205
+ * @param {boolean} [priority] - Filter for the highest priority
206
+ * @returns {Array<ServiceHost>} - The filtered host array.
207
+ */
208
+ filterPriority(priority) {
209
+ return priority
210
+ ? this.hosts.reduce((filteredHosts, currentHost) => {
211
+ // Validate that the current host is not active.
212
+ if (!currentHost.active) {
213
+ return filteredHosts;
214
+ }
215
+
216
+ // Determine if the filtered hosts array contains a host from the same
217
+ // host group.
218
+ const foundHost = filteredHosts.find((host) => host.hostGroup === currentHost.hostGroup);
219
+
220
+ // Validate if a host was found.
221
+ if (!foundHost) {
222
+ filteredHosts.push(currentHost);
223
+
224
+ return filteredHosts;
225
+ }
226
+
227
+ // Map the found host's catalog to its priority value.
228
+ const foundHostCatalogPriority = ServiceRegistry.mapCatalogName({
229
+ id: foundHost.catalog,
230
+ type: SERVICE_CATALOGS_ENUM_TYPES.NUMBER,
231
+ });
232
+
233
+ // Map the current host's catalog to its priority value.
234
+ const currentHostCatalogPriority = ServiceRegistry.mapCatalogName({
235
+ id: currentHost.catalog,
236
+ type: SERVICE_CATALOGS_ENUM_TYPES.NUMBER,
237
+ });
238
+
239
+ // Validate if the found host has a lower priority than the current
240
+ // host.
241
+ if (
242
+ foundHostCatalogPriority < currentHostCatalogPriority ||
243
+ foundHost.priority < currentHost.priority
244
+ ) {
245
+ filteredHosts.splice(filteredHosts.indexOf(foundHost, 1));
246
+ filteredHosts.push(currentHost);
247
+ }
248
+
249
+ return filteredHosts;
250
+ }, [])
251
+ : [...this.hosts];
252
+ }
253
+
254
+ /**
255
+ * Filter the {@link ServiceRegistry#hosts} array for hosts with a specified
256
+ * set of service names.
257
+ *
258
+ * @private
259
+ * @memberof ServiceRegistry
260
+ * @param {Array<string> | string} [service] - Services to filter.
261
+ * @returns {Array<ServiceHost>} - The filtered host array.
262
+ */
263
+ filterService(service = []) {
264
+ // Generate an array of services regardless of parameter type.
265
+ const services = Array.isArray(service) ? service : [service];
266
+
267
+ // Filter the host array against the provided services.
268
+ return services.length > 0
269
+ ? this.hosts.filter((host) => services.includes(host.service))
270
+ : [...this.hosts];
271
+ }
272
+
273
+ /**
274
+ * Filter the {@link ServiceRegistry#hosts} array for hosts with a specified
275
+ * set of URLs.
276
+ *
277
+ * @private
278
+ * @memberof ServiceRegistry
279
+ * @param {Array<string> | string} [url] - URL to filter.
280
+ * @returns {Array<ServiceHost>} - The filter host array.
281
+ */
282
+ filterUrl(url = []) {
283
+ // Generate an array of URLs regardless of the parameter type.
284
+ const urls = Array.isArray(url) ? url : [url];
285
+
286
+ // Filter the host array against the provided URLs.
287
+ return urls.length > 0 ? this.hosts.filter((host) => urls.includes(host.url)) : [...this.hosts];
288
+ }
289
+
290
+ /**
291
+ * Get an array of {@link ServiceHost}s based on a provided
292
+ * {@link HostFilter} from the {@link ServiceRegistry#hosts} array.
293
+ *
294
+ * @public
295
+ * @memberof ServiceRegistry
296
+ * @param {HostFilter} [filter] - The inclusive filter for hosts to find.
297
+ * @returns {Array<ServiceHost>} - The filtered hosts.
298
+ */
299
+ find({active, catalog, cluster, local, priority, service, url} = {}) {
300
+ return this.hosts.filter(
301
+ (host) =>
302
+ this.filterActive(active).includes(host) &&
303
+ this.filterCatalog(catalog).includes(host) &&
304
+ this.filterCluster(cluster).includes(host) &&
305
+ this.filterLocal(local).includes(host) &&
306
+ this.filterPriority(priority).includes(host) &&
307
+ this.filterService(service).includes(host) &&
308
+ this.filterUrl(url).includes(host)
309
+ );
310
+ }
311
+
312
+ /**
313
+ * Load a formatted array of {@link ServiceHost} constructor parameter
314
+ * transfer objects as instances of {@link ServiceHost} class objects to the
315
+ * {@link ServiceRegistry#hosts} array.
316
+ *
317
+ * @public
318
+ * @memberof ServiceRegistry
319
+ * @param {Array<ServiceHost.ConstructorPTO>} hosts
320
+ * @returns {this}
321
+ */
322
+ load(hosts = []) {
323
+ // Validate that the provided hosts are eligible to be loaded.
324
+ const validHosts = hosts.filter(
325
+ (host) =>
326
+ !!ServiceRegistry.mapCatalogName({
327
+ id: host.catalog,
328
+ type: SERVICE_CATALOGS_ENUM_TYPES.STRING,
329
+ })
330
+ );
331
+
332
+ // Load the eligible hosts.
333
+ this.hosts.push(...validHosts.map((loadableHost) => new ServiceHost(loadableHost)));
334
+
335
+ return this;
336
+ }
337
+
338
+ /**
339
+ * Mark a collection of {@link ServiceHost} class objects from the
340
+ * {@link ServiceRegistry#hosts} array as replaced based on the provided
341
+ * {@link HostFilter}.
342
+ *
343
+ * @public
344
+ * @memberof ServiceRegistry
345
+ * @param {HostFilter} filter - The inclusive filter to mark replaced.
346
+ * @returns {Array<ServiceHost>} - The {@link ServiceHost}s marked replaced.
347
+ */
348
+ replaced(filter) {
349
+ // Collect a list of hosts to mark as replaced based on the provided filter.
350
+ const replacing = this.find(filter);
351
+
352
+ // Mark the hosts from the array as replaced.
353
+ replacing.forEach((host) => {
354
+ host.setStatus({replaced: true});
355
+ });
356
+
357
+ // Return the marked hosts.
358
+ return replacing;
359
+ }
360
+
361
+ /**
362
+ * Reset the failed status of a collection of {@link ServiceHost} class
363
+ * objects from the {@link ServiceRegistry#hosts} array based on the provided
364
+ * {@link HostFilter}.
365
+ *
366
+ * @public
367
+ * @memberof ServiceRegistry
368
+ * @param {HostFilter} filter - The inclusive filter of hosts to reset.
369
+ * @returns {Array<ServiceHost>} - The {@link ServiceHost}s that reset.
370
+ */
371
+ reset(filter) {
372
+ // Collect a list of hosts to mark as replaced based on the provided filter.
373
+ const resetting = this.find(filter);
374
+
375
+ // Mark the hosts from the array as replaced.
376
+ resetting.forEach((host) => {
377
+ host.setStatus({failed: false});
378
+ });
379
+
380
+ // Return the marked hosts.
381
+ return resetting;
382
+ }
383
+
384
+ /**
385
+ * Convert a {@link SERVICE_CATALOGS} identifier or value to its associated
386
+ * idenfier or value.
387
+ *
388
+ * @public
389
+ * @static
390
+ * @memberof ServiceRegistry
391
+ * @param {Object} pto - The parameter transfer object.
392
+ * @property {string | number} pto.id - The identifier to convert in the enum.
393
+ * @property {SERVICE_CATALOGS_ENUM_TYPES} pto.type - The desired output.
394
+ * @returns {string|number} - The matching enum value or index.
395
+ */
396
+ static mapCatalogName({id, type}) {
397
+ // Validate that the id is a number.
398
+ if (typeof id === 'number') {
399
+ // Validate that the desired type is a number.
400
+ if (type === SERVICE_CATALOGS_ENUM_TYPES.NUMBER) {
401
+ return SERVICE_CATALOGS[id] !== undefined ? id : undefined;
402
+ }
403
+
404
+ // Validate that the desired type is a string.
405
+ if (type === SERVICE_CATALOGS_ENUM_TYPES.STRING) {
406
+ return SERVICE_CATALOGS[id];
407
+ }
408
+ }
409
+
410
+ // Validate that the id is a string.
411
+ if (typeof id === 'string') {
412
+ // Validate that the desired type is a string.
413
+ if (type === SERVICE_CATALOGS_ENUM_TYPES.STRING) {
414
+ return SERVICE_CATALOGS.includes(id) ? id : undefined;
415
+ }
416
+
417
+ // Validate that the desired type is a number.
418
+ if (type === SERVICE_CATALOGS_ENUM_TYPES.NUMBER) {
419
+ return SERVICE_CATALOGS.includes(id) ? SERVICE_CATALOGS.indexOf(id) : undefined;
420
+ }
421
+ }
422
+
423
+ return undefined;
424
+ }
425
+
426
+ /**
427
+ * Generate a formatted array based on the object received from the **U2C**
428
+ * service for usage in the {@link ServiceRegistry#load} method.
429
+ *
430
+ * @public
431
+ * @static
432
+ * @memberof ServiceRegistry
433
+ * @param {MapRemoteCatalogPTO} pto - The parameter transfer object.
434
+ * @throws - If the target catalog does not exist.
435
+ * @returns {Array<ServiceHost#ServiceHostConstructorPTO>}
436
+ */
437
+ static mapRemoteCatalog({catalog, hostCatalog, serviceLinks}) {
438
+ // Collect the service catalog name if needed.
439
+ const catalogIndex = ServiceRegistry.mapCatalogName({
440
+ id: catalog,
441
+ type: SERVICE_CATALOGS_ENUM_TYPES.STRING,
442
+ });
443
+
444
+ // Validate that the target catalog exists.
445
+ if (!SERVICE_CATALOGS.includes(catalogIndex)) {
446
+ throw new Error(`service-catalogs: '${catalog}' is not a valid catalog`);
447
+ }
448
+
449
+ // Map the remote catalog to a mountable host array.
450
+ return Object.keys(hostCatalog).reduce((output, key) => {
451
+ output.push(
452
+ ...hostCatalog[key].map((host) => ({
453
+ catalog: catalogIndex,
454
+ defaultUri: serviceLinks[host.id.split(':')[3]],
455
+ hostGroup: key,
456
+ id: host.id,
457
+ priority: host.priority,
458
+ uri: host.host,
459
+ }))
460
+ );
461
+
462
+ return output;
463
+ }, []);
464
+ }
465
+ }