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

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 +20 -19
  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,307 +1,307 @@
1
- /*!
2
- * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
- */
4
-
5
- import {has} from 'lodash';
6
- import {cappedDebounce, Defer, tap} from '@webex/common';
7
-
8
- import WebexPlugin from './webex-plugin';
9
- import WebexHttpError from './webex-http-error';
10
-
11
- /**
12
- * Base class for coalescing requests to batched APIs
13
- * @class Batcher
14
- */
15
- const Batcher = WebexPlugin.extend({
16
- session: {
17
- deferreds: {
18
- type: 'object',
19
- default() {
20
- return new Map();
21
- },
22
- },
23
- queue: {
24
- type: 'array',
25
- default() {
26
- return [];
27
- },
28
- },
29
- },
30
-
31
- derived: {
32
- bounce: {
33
- fn() {
34
- return cappedDebounce((...args) => this.executeQueue(...args), this.config.batcherWait, {
35
- maxCalls: this.config.batcherMaxCalls,
36
- maxWait: this.config.batcherMaxWait,
37
- });
38
- },
39
- },
40
- },
41
-
42
- /**
43
- * Requests an item from a batched API
44
- * @param {Object} item
45
- * @returns {Promise<mixed>}
46
- */
47
- request(item) {
48
- // So far, I can't find a way to avoid three layers of nesting here.
49
- /* eslint max-nested-callbacks: [0] */
50
- const defer = new Defer();
51
-
52
- this.fingerprintRequest(item)
53
- .then((idx) => {
54
- if (this.deferreds.has(idx)) {
55
- defer.resolve(this.deferreds.get(idx).promise);
56
-
57
- return;
58
- }
59
- this.deferreds.set(idx, defer);
60
- this.prepareItem(item)
61
- .then((req) => {
62
- defer.promise = defer.promise
63
- .then(tap(() => this.deferreds.delete(idx)))
64
- .catch((reason) => {
65
- this.deferreds.delete(idx);
66
-
67
- return Promise.reject(reason);
68
- });
69
-
70
- this.enqueue(req)
71
- .then(() => this.bounce())
72
- .catch((reason) => defer.reject(reason));
73
- })
74
- .catch((reason) => defer.reject(reason));
75
- })
76
- .catch((reason) => defer.reject(reason));
77
-
78
- return defer.promise;
79
- },
80
-
81
- /**
82
- * Adds an item to the queue.
83
- * Intended to be overridden
84
- * @param {mixed} req
85
- * @returns {Promise<undefined>}
86
- */
87
- enqueue(req) {
88
- this.queue.push(req);
89
-
90
- return Promise.resolve();
91
- },
92
-
93
- /**
94
- * Transform the item before adding it to the queue
95
- * Intended to be overridden
96
- * @param {mixed} item
97
- * @returns {Promise<mixed>}
98
- */
99
- prepareItem(item) {
100
- return Promise.resolve(item);
101
- },
102
-
103
- /**
104
- * Detaches the current queue, does any appropriate transforms, and submits it
105
- * to the API.
106
- * @returns {Promise<undefined>}
107
- */
108
- executeQueue() {
109
- const queue = this.queue.splice(0, this.config.batcherMaxCalls);
110
-
111
- return new Promise((resolve) => {
112
- resolve(
113
- this.prepareRequest(queue)
114
- .then((payload) =>
115
- this.submitHttpRequest(payload).then((res) => this.handleHttpSuccess(res))
116
- )
117
- .catch((reason) => {
118
- if (reason instanceof WebexHttpError) {
119
- return this.handleHttpError(reason);
120
- }
121
-
122
- return Promise.all(
123
- queue.map((item) =>
124
- this.getDeferredForRequest(item).then((defer) => {
125
- defer.reject(reason);
126
- })
127
- )
128
- );
129
- })
130
- );
131
- }).catch((reason) => {
132
- this.logger.error(process.env.NODE_ENV === 'production' ? reason : reason.stack);
133
-
134
- return Promise.reject(reason);
135
- });
136
- },
137
-
138
- /**
139
- * Performs any final transforms on the queue before submitting it to the API
140
- * Intended to be overridden
141
- * @param {Object|Array} queue
142
- * @returns {Promise<Object>}
143
- */
144
- prepareRequest(queue) {
145
- return Promise.resolve(queue);
146
- },
147
-
148
- /**
149
- * Submits the prepared request body to the API.
150
- * This method *must* be overridden
151
- * @param {Object} payload
152
- * @returns {Promise<HttpResponseObject>}
153
- */
154
- // eslint-disable-next-line no-unused-vars
155
- submitHttpRequest(payload) {
156
- throw new Error('request() must be implemented');
157
- },
158
-
159
- /**
160
- * Actions taken when the http request returns a success
161
- * Intended to be overridden
162
- * @param {Promise<HttpResponseObject>} res
163
- * @returns {Promise<undefined>}
164
- */
165
- handleHttpSuccess(res) {
166
- return Promise.all(
167
- ((res.body && res.body.items) || res.body).map((item) => this.acceptItem(item))
168
- );
169
- },
170
-
171
- /**
172
- * Actions taken when the http request returns a failure. Typically, this
173
- * means failing the entire queue, but could be overridden in some
174
- * implementations to e.g. reenqueue.
175
- * Intended to be overridden
176
- * @param {WebexHttpError} reason
177
- * @returns {Promise<undefined>}
178
- */
179
- handleHttpError(reason) {
180
- if (reason instanceof WebexHttpError) {
181
- if (has(reason, 'options.body.map')) {
182
- return Promise.all(
183
- reason.options.body.map((item) =>
184
- this.getDeferredForRequest(item).then((defer) => {
185
- defer.reject(reason);
186
- })
187
- )
188
- );
189
- }
190
- }
191
- this.logger.error('http error handler called without a WebexHttpError object', reason);
192
-
193
- return Promise.reject(reason);
194
- },
195
-
196
- /**
197
- * Determines if the item succeeded or failed and delegates accordingly
198
- * @param {Object} item
199
- * @returns {Promise<undefined>}
200
- */
201
- acceptItem(item) {
202
- return this.didItemFail(item).then((didFail) => {
203
- if (didFail) {
204
- return this.handleItemFailure(item);
205
- }
206
-
207
- return this.handleItemSuccess(item);
208
- });
209
- },
210
-
211
- /**
212
- * Indicates if the specified response item implies a success or a failure
213
- * Intended to be overridden
214
- * @param {Object} item
215
- * @returns {Promise<Boolean>}
216
- */
217
- // eslint-disable-next-line no-unused-vars
218
- didItemFail(item) {
219
- return Promise.resolve(false);
220
- },
221
-
222
- /**
223
- * Finds the Defer for the specified item and rejects its promise
224
- * Intended to be overridden
225
- * @param {Object} item
226
- * @returns {Promise<undefined>}
227
- */
228
- handleItemFailure(item) {
229
- return this.getDeferredForResponse(item).then((defer) => {
230
- defer.reject(item);
231
- });
232
- },
233
-
234
- /**
235
- * Finds the Defer for the specified item and resolves its promise
236
- * Intended to be overridden
237
- * @param {Object} item
238
- * @returns {Promise<undefined>}
239
- */
240
- handleItemSuccess(item) {
241
- return this.getDeferredForResponse(item).then((defer) => {
242
- defer.resolve(item);
243
- });
244
- },
245
-
246
- /**
247
- * Returns the Deferred for the specified request item
248
- * @param {Object} item
249
- * @returns {Promise<Defer>}
250
- */
251
- getDeferredForRequest(item) {
252
- return this.fingerprintRequest(item).then((idx) => {
253
- const defer = this.deferreds.get(idx);
254
-
255
- /* istanbul ignore if */
256
- if (!defer) {
257
- throw new Error('Could not find pending request for received response');
258
- }
259
-
260
- return defer;
261
- });
262
- },
263
-
264
- /**
265
- * Returns the Deferred for the specified response item
266
- * @param {Object} item
267
- * @returns {Promise<Defer>}
268
- */
269
- getDeferredForResponse(item) {
270
- return this.fingerprintResponse(item).then((idx) => {
271
- const defer = this.deferreds.get(idx);
272
-
273
- /* istanbul ignore if */
274
- if (!defer) {
275
- throw new Error('Could not find pending request for received response');
276
- }
277
-
278
- return defer;
279
- });
280
- },
281
-
282
- /**
283
- * Generates a unique identifier for the item in a request payload
284
- * Intended to be overridden
285
- * Note that overrides must return a primitive.
286
- * @param {Object} item
287
- * @returns {Promise<primitive>}
288
- */
289
- // eslint-disable-next-line no-unused-vars
290
- fingerprintRequest(item) {
291
- throw new Error('fingerprintRequest() must be implemented');
292
- },
293
-
294
- /**
295
- * Generates a unique identifier for the item in a response payload
296
- * Intended to be overridden
297
- * Note that overrides must return a primitive.
298
- * @param {Object} item
299
- * @returns {Promise<primitive>}
300
- */
301
- // eslint-disable-next-line no-unused-vars
302
- fingerprintResponse(item) {
303
- throw new Error('fingerprintResponse() must be implemented');
304
- },
305
- });
306
-
307
- export default Batcher;
1
+ /*!
2
+ * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
+ */
4
+
5
+ import {has} from 'lodash';
6
+ import {cappedDebounce, Defer, tap} from '@webex/common';
7
+
8
+ import WebexPlugin from './webex-plugin';
9
+ import WebexHttpError from './webex-http-error';
10
+
11
+ /**
12
+ * Base class for coalescing requests to batched APIs
13
+ * @class Batcher
14
+ */
15
+ const Batcher = WebexPlugin.extend({
16
+ session: {
17
+ deferreds: {
18
+ type: 'object',
19
+ default() {
20
+ return new Map();
21
+ },
22
+ },
23
+ queue: {
24
+ type: 'array',
25
+ default() {
26
+ return [];
27
+ },
28
+ },
29
+ },
30
+
31
+ derived: {
32
+ bounce: {
33
+ fn() {
34
+ return cappedDebounce((...args) => this.executeQueue(...args), this.config.batcherWait, {
35
+ maxCalls: this.config.batcherMaxCalls,
36
+ maxWait: this.config.batcherMaxWait,
37
+ });
38
+ },
39
+ },
40
+ },
41
+
42
+ /**
43
+ * Requests an item from a batched API
44
+ * @param {Object} item
45
+ * @returns {Promise<mixed>}
46
+ */
47
+ request(item) {
48
+ // So far, I can't find a way to avoid three layers of nesting here.
49
+ /* eslint max-nested-callbacks: [0] */
50
+ const defer = new Defer();
51
+
52
+ this.fingerprintRequest(item)
53
+ .then((idx) => {
54
+ if (this.deferreds.has(idx)) {
55
+ defer.resolve(this.deferreds.get(idx).promise);
56
+
57
+ return;
58
+ }
59
+ this.deferreds.set(idx, defer);
60
+ this.prepareItem(item)
61
+ .then((req) => {
62
+ defer.promise = defer.promise
63
+ .then(tap(() => this.deferreds.delete(idx)))
64
+ .catch((reason) => {
65
+ this.deferreds.delete(idx);
66
+
67
+ return Promise.reject(reason);
68
+ });
69
+
70
+ this.enqueue(req)
71
+ .then(() => this.bounce())
72
+ .catch((reason) => defer.reject(reason));
73
+ })
74
+ .catch((reason) => defer.reject(reason));
75
+ })
76
+ .catch((reason) => defer.reject(reason));
77
+
78
+ return defer.promise;
79
+ },
80
+
81
+ /**
82
+ * Adds an item to the queue.
83
+ * Intended to be overridden
84
+ * @param {mixed} req
85
+ * @returns {Promise<undefined>}
86
+ */
87
+ enqueue(req) {
88
+ this.queue.push(req);
89
+
90
+ return Promise.resolve();
91
+ },
92
+
93
+ /**
94
+ * Transform the item before adding it to the queue
95
+ * Intended to be overridden
96
+ * @param {mixed} item
97
+ * @returns {Promise<mixed>}
98
+ */
99
+ prepareItem(item) {
100
+ return Promise.resolve(item);
101
+ },
102
+
103
+ /**
104
+ * Detaches the current queue, does any appropriate transforms, and submits it
105
+ * to the API.
106
+ * @returns {Promise<undefined>}
107
+ */
108
+ executeQueue() {
109
+ const queue = this.queue.splice(0, this.config.batcherMaxCalls);
110
+
111
+ return new Promise((resolve) => {
112
+ resolve(
113
+ this.prepareRequest(queue)
114
+ .then((payload) =>
115
+ this.submitHttpRequest(payload).then((res) => this.handleHttpSuccess(res))
116
+ )
117
+ .catch((reason) => {
118
+ if (reason instanceof WebexHttpError) {
119
+ return this.handleHttpError(reason);
120
+ }
121
+
122
+ return Promise.all(
123
+ queue.map((item) =>
124
+ this.getDeferredForRequest(item).then((defer) => {
125
+ defer.reject(reason);
126
+ })
127
+ )
128
+ );
129
+ })
130
+ );
131
+ }).catch((reason) => {
132
+ this.logger.error(process.env.NODE_ENV === 'production' ? reason : reason.stack);
133
+
134
+ return Promise.reject(reason);
135
+ });
136
+ },
137
+
138
+ /**
139
+ * Performs any final transforms on the queue before submitting it to the API
140
+ * Intended to be overridden
141
+ * @param {Object|Array} queue
142
+ * @returns {Promise<Object>}
143
+ */
144
+ prepareRequest(queue) {
145
+ return Promise.resolve(queue);
146
+ },
147
+
148
+ /**
149
+ * Submits the prepared request body to the API.
150
+ * This method *must* be overridden
151
+ * @param {Object} payload
152
+ * @returns {Promise<HttpResponseObject>}
153
+ */
154
+ // eslint-disable-next-line no-unused-vars
155
+ submitHttpRequest(payload) {
156
+ throw new Error('request() must be implemented');
157
+ },
158
+
159
+ /**
160
+ * Actions taken when the http request returns a success
161
+ * Intended to be overridden
162
+ * @param {Promise<HttpResponseObject>} res
163
+ * @returns {Promise<undefined>}
164
+ */
165
+ handleHttpSuccess(res) {
166
+ return Promise.all(
167
+ ((res.body && res.body.items) || res.body).map((item) => this.acceptItem(item))
168
+ );
169
+ },
170
+
171
+ /**
172
+ * Actions taken when the http request returns a failure. Typically, this
173
+ * means failing the entire queue, but could be overridden in some
174
+ * implementations to e.g. reenqueue.
175
+ * Intended to be overridden
176
+ * @param {WebexHttpError} reason
177
+ * @returns {Promise<undefined>}
178
+ */
179
+ handleHttpError(reason) {
180
+ if (reason instanceof WebexHttpError) {
181
+ if (has(reason, 'options.body.map')) {
182
+ return Promise.all(
183
+ reason.options.body.map((item) =>
184
+ this.getDeferredForRequest(item).then((defer) => {
185
+ defer.reject(reason);
186
+ })
187
+ )
188
+ );
189
+ }
190
+ }
191
+ this.logger.error('http error handler called without a WebexHttpError object', reason);
192
+
193
+ return Promise.reject(reason);
194
+ },
195
+
196
+ /**
197
+ * Determines if the item succeeded or failed and delegates accordingly
198
+ * @param {Object} item
199
+ * @returns {Promise<undefined>}
200
+ */
201
+ acceptItem(item) {
202
+ return this.didItemFail(item).then((didFail) => {
203
+ if (didFail) {
204
+ return this.handleItemFailure(item);
205
+ }
206
+
207
+ return this.handleItemSuccess(item);
208
+ });
209
+ },
210
+
211
+ /**
212
+ * Indicates if the specified response item implies a success or a failure
213
+ * Intended to be overridden
214
+ * @param {Object} item
215
+ * @returns {Promise<Boolean>}
216
+ */
217
+ // eslint-disable-next-line no-unused-vars
218
+ didItemFail(item) {
219
+ return Promise.resolve(false);
220
+ },
221
+
222
+ /**
223
+ * Finds the Defer for the specified item and rejects its promise
224
+ * Intended to be overridden
225
+ * @param {Object} item
226
+ * @returns {Promise<undefined>}
227
+ */
228
+ handleItemFailure(item) {
229
+ return this.getDeferredForResponse(item).then((defer) => {
230
+ defer.reject(item);
231
+ });
232
+ },
233
+
234
+ /**
235
+ * Finds the Defer for the specified item and resolves its promise
236
+ * Intended to be overridden
237
+ * @param {Object} item
238
+ * @returns {Promise<undefined>}
239
+ */
240
+ handleItemSuccess(item) {
241
+ return this.getDeferredForResponse(item).then((defer) => {
242
+ defer.resolve(item);
243
+ });
244
+ },
245
+
246
+ /**
247
+ * Returns the Deferred for the specified request item
248
+ * @param {Object} item
249
+ * @returns {Promise<Defer>}
250
+ */
251
+ getDeferredForRequest(item) {
252
+ return this.fingerprintRequest(item).then((idx) => {
253
+ const defer = this.deferreds.get(idx);
254
+
255
+ /* istanbul ignore if */
256
+ if (!defer) {
257
+ throw new Error('Could not find pending request for received response');
258
+ }
259
+
260
+ return defer;
261
+ });
262
+ },
263
+
264
+ /**
265
+ * Returns the Deferred for the specified response item
266
+ * @param {Object} item
267
+ * @returns {Promise<Defer>}
268
+ */
269
+ getDeferredForResponse(item) {
270
+ return this.fingerprintResponse(item).then((idx) => {
271
+ const defer = this.deferreds.get(idx);
272
+
273
+ /* istanbul ignore if */
274
+ if (!defer) {
275
+ throw new Error('Could not find pending request for received response');
276
+ }
277
+
278
+ return defer;
279
+ });
280
+ },
281
+
282
+ /**
283
+ * Generates a unique identifier for the item in a request payload
284
+ * Intended to be overridden
285
+ * Note that overrides must return a primitive.
286
+ * @param {Object} item
287
+ * @returns {Promise<primitive>}
288
+ */
289
+ // eslint-disable-next-line no-unused-vars
290
+ fingerprintRequest(item) {
291
+ throw new Error('fingerprintRequest() must be implemented');
292
+ },
293
+
294
+ /**
295
+ * Generates a unique identifier for the item in a response payload
296
+ * Intended to be overridden
297
+ * Note that overrides must return a primitive.
298
+ * @param {Object} item
299
+ * @returns {Promise<primitive>}
300
+ */
301
+ // eslint-disable-next-line no-unused-vars
302
+ fingerprintResponse(item) {
303
+ throw new Error('fingerprintResponse() must be implemented');
304
+ },
305
+ });
306
+
307
+ export default Batcher;