@webex/common 2.59.1 → 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.
- package/.eslintrc.js +6 -6
- package/README.md +42 -42
- package/babel.config.js +3 -3
- package/dist/base64.js +22 -22
- package/dist/base64.js.map +1 -1
- package/dist/browser-detection.js.map +1 -1
- package/dist/capped-debounce.js +12 -12
- package/dist/capped-debounce.js.map +1 -1
- package/dist/check-required.js +8 -8
- package/dist/check-required.js.map +1 -1
- package/dist/constants.js.map +1 -1
- package/dist/defer.js +13 -13
- package/dist/defer.js.map +1 -1
- package/dist/deprecated.js +5 -5
- package/dist/deprecated.js.map +1 -1
- package/dist/event-envelope.js +11 -11
- package/dist/event-envelope.js.map +1 -1
- package/dist/events.js +15 -15
- package/dist/events.js.map +1 -1
- package/dist/exception.js +13 -13
- package/dist/exception.js.map +1 -1
- package/dist/in-browser/browser.js +2 -2
- package/dist/in-browser/browser.js.map +1 -1
- package/dist/in-browser/index.js.map +1 -1
- package/dist/in-browser/node.js +2 -2
- package/dist/in-browser/node.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/isBuffer.js +6 -6
- package/dist/isBuffer.js.map +1 -1
- package/dist/make-state-datatype.js +14 -14
- package/dist/make-state-datatype.js.map +1 -1
- package/dist/one-flight.js +13 -13
- package/dist/one-flight.js.map +1 -1
- package/dist/patterns.js +30 -30
- package/dist/patterns.js.map +1 -1
- package/dist/resolve-with.js +19 -19
- package/dist/resolve-with.js.map +1 -1
- package/dist/retry.js +17 -17
- package/dist/retry.js.map +1 -1
- package/dist/tap.js +14 -14
- package/dist/tap.js.map +1 -1
- package/dist/template-container.js +51 -51
- package/dist/template-container.js.map +1 -1
- package/dist/uuid-utils.js +76 -76
- package/dist/uuid-utils.js.map +1 -1
- package/dist/while-in-flight.js +5 -5
- package/dist/while-in-flight.js.map +1 -1
- package/jest.config.js +3 -3
- package/package.json +12 -11
- package/process +1 -1
- package/src/base64.js +67 -67
- package/src/browser-detection.js +37 -37
- package/src/capped-debounce.js +65 -65
- package/src/check-required.js +18 -18
- package/src/constants.js +79 -79
- package/src/defer.js +24 -24
- package/src/deprecated.js +19 -19
- package/src/event-envelope.js +54 -54
- package/src/events.js +55 -55
- package/src/exception.js +45 -45
- package/src/in-browser/browser.js +5 -5
- package/src/in-browser/index.js +11 -11
- package/src/in-browser/node.js +5 -5
- package/src/index.js +44 -44
- package/src/isBuffer.js +12 -12
- package/src/make-state-datatype.js +91 -91
- package/src/one-flight.js +89 -89
- package/src/patterns.js +51 -51
- package/src/resolve-with.js +27 -27
- package/src/retry.js +124 -124
- package/src/tap.js +25 -25
- package/src/template-container.js +222 -222
- package/src/uuid-utils.js +189 -189
- package/src/while-in-flight.js +38 -38
- package/test/unit/spec/capped-debounce.js +103 -103
- package/test/unit/spec/common.js +42 -42
- package/test/unit/spec/exception.js +102 -102
- package/test/unit/spec/one-flight.js +211 -211
- package/test/unit/spec/template-container.js +81 -81
- package/test/unit/spec/while-in-flight.js +70 -70
package/src/one-flight.js
CHANGED
|
@@ -1,89 +1,89 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import {wrap} from 'lodash';
|
|
6
|
-
|
|
7
|
-
import make from './template-container';
|
|
8
|
-
|
|
9
|
-
// Alias Map and WeakMap to get around a babel compiler bug
|
|
10
|
-
const W = WeakMap;
|
|
11
|
-
const M = Map;
|
|
12
|
-
const WeakMappedMappedMap = make(W, M, M);
|
|
13
|
-
|
|
14
|
-
const flights = new WeakMappedMappedMap();
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @memberof Util
|
|
18
|
-
* @param {Object} options
|
|
19
|
-
* @param {Function} options.keyFactory
|
|
20
|
-
* @param {boolean} options.cacheFailures
|
|
21
|
-
* @param {boolean} options.cacheSuccesses
|
|
22
|
-
* @returns {Function}
|
|
23
|
-
*/
|
|
24
|
-
export default function oneFlight(...params) {
|
|
25
|
-
if (params.length === 3) {
|
|
26
|
-
return Reflect.apply(oneFlightDecorator, null, params);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const options = params[0] || {};
|
|
30
|
-
|
|
31
|
-
const {cacheFailures, cacheSuccesses, keyFactory} = options;
|
|
32
|
-
|
|
33
|
-
return oneFlightDecorator;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* @param {Object} target
|
|
37
|
-
* @param {string} prop
|
|
38
|
-
* @param {Object} descriptor
|
|
39
|
-
* @private
|
|
40
|
-
* @returns {Object}
|
|
41
|
-
*/
|
|
42
|
-
function oneFlightDecorator(target, prop, descriptor) {
|
|
43
|
-
const key = prop;
|
|
44
|
-
|
|
45
|
-
descriptor.value = wrap(descriptor.value, function oneFlightExecutor(fn, ...args) {
|
|
46
|
-
let innerKey = key;
|
|
47
|
-
|
|
48
|
-
if (keyFactory) {
|
|
49
|
-
innerKey = `${innerKey}_${keyFactory(...args)}`;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/* eslint no-invalid-this: [0] */
|
|
53
|
-
let flight = flights.get(this, target, innerKey);
|
|
54
|
-
|
|
55
|
-
if (flight) {
|
|
56
|
-
return flight;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
flight = Reflect.apply(fn, this, args);
|
|
60
|
-
if (!cacheFailures && flight && flight.catch) {
|
|
61
|
-
flight = flight.catch((reason) => {
|
|
62
|
-
flights.delete(this, target, innerKey);
|
|
63
|
-
|
|
64
|
-
return Promise.reject(reason);
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (!cacheSuccesses && flight && flight.then) {
|
|
69
|
-
flight = flight.then((result) => {
|
|
70
|
-
flights.delete(this, target, innerKey);
|
|
71
|
-
|
|
72
|
-
return result;
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
flights.set(this, target, innerKey, flight);
|
|
77
|
-
|
|
78
|
-
return flight;
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
// This *should* make decorators compatible with AmpersandState class
|
|
82
|
-
// definitions
|
|
83
|
-
if (typeof target === 'object' && !target.prototype) {
|
|
84
|
-
target[prop] = descriptor.value;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return descriptor;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {wrap} from 'lodash';
|
|
6
|
+
|
|
7
|
+
import make from './template-container';
|
|
8
|
+
|
|
9
|
+
// Alias Map and WeakMap to get around a babel compiler bug
|
|
10
|
+
const W = WeakMap;
|
|
11
|
+
const M = Map;
|
|
12
|
+
const WeakMappedMappedMap = make(W, M, M);
|
|
13
|
+
|
|
14
|
+
const flights = new WeakMappedMappedMap();
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @memberof Util
|
|
18
|
+
* @param {Object} options
|
|
19
|
+
* @param {Function} options.keyFactory
|
|
20
|
+
* @param {boolean} options.cacheFailures
|
|
21
|
+
* @param {boolean} options.cacheSuccesses
|
|
22
|
+
* @returns {Function}
|
|
23
|
+
*/
|
|
24
|
+
export default function oneFlight(...params) {
|
|
25
|
+
if (params.length === 3) {
|
|
26
|
+
return Reflect.apply(oneFlightDecorator, null, params);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const options = params[0] || {};
|
|
30
|
+
|
|
31
|
+
const {cacheFailures, cacheSuccesses, keyFactory} = options;
|
|
32
|
+
|
|
33
|
+
return oneFlightDecorator;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param {Object} target
|
|
37
|
+
* @param {string} prop
|
|
38
|
+
* @param {Object} descriptor
|
|
39
|
+
* @private
|
|
40
|
+
* @returns {Object}
|
|
41
|
+
*/
|
|
42
|
+
function oneFlightDecorator(target, prop, descriptor) {
|
|
43
|
+
const key = prop;
|
|
44
|
+
|
|
45
|
+
descriptor.value = wrap(descriptor.value, function oneFlightExecutor(fn, ...args) {
|
|
46
|
+
let innerKey = key;
|
|
47
|
+
|
|
48
|
+
if (keyFactory) {
|
|
49
|
+
innerKey = `${innerKey}_${keyFactory(...args)}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* eslint no-invalid-this: [0] */
|
|
53
|
+
let flight = flights.get(this, target, innerKey);
|
|
54
|
+
|
|
55
|
+
if (flight) {
|
|
56
|
+
return flight;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
flight = Reflect.apply(fn, this, args);
|
|
60
|
+
if (!cacheFailures && flight && flight.catch) {
|
|
61
|
+
flight = flight.catch((reason) => {
|
|
62
|
+
flights.delete(this, target, innerKey);
|
|
63
|
+
|
|
64
|
+
return Promise.reject(reason);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!cacheSuccesses && flight && flight.then) {
|
|
69
|
+
flight = flight.then((result) => {
|
|
70
|
+
flights.delete(this, target, innerKey);
|
|
71
|
+
|
|
72
|
+
return result;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
flights.set(this, target, innerKey, flight);
|
|
77
|
+
|
|
78
|
+
return flight;
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// This *should* make decorators compatible with AmpersandState class
|
|
82
|
+
// definitions
|
|
83
|
+
if (typeof target === 'object' && !target.prototype) {
|
|
84
|
+
target[prop] = descriptor.value;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return descriptor;
|
|
88
|
+
}
|
|
89
|
+
}
|
package/src/patterns.js
CHANGED
|
@@ -1,51 +1,51 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @description Set of regex patterns to compile once and use throughout the
|
|
7
|
-
* app. All non-prefixed patterns have start/end characters to ensure exact
|
|
8
|
-
* matches. Patterns prefixed with "exec" are the same as their non-prefixed
|
|
9
|
-
* counterparts but without the start/end characters so they can be used with
|
|
10
|
-
* methods like `RegExp#exec`.
|
|
11
|
-
*/
|
|
12
|
-
export default {
|
|
13
|
-
/**
|
|
14
|
-
* Regular express that validates a string is strictly an email.
|
|
15
|
-
* Allows for validation of emails within services such as conversation
|
|
16
|
-
* activities or user details.
|
|
17
|
-
* See [RegEx information here]{@link https://ihateregex.io/expr/email-2}.
|
|
18
|
-
*
|
|
19
|
-
* @type {RegExp}
|
|
20
|
-
*/
|
|
21
|
-
email:
|
|
22
|
-
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Regular expression that validates an ambiguous string contains emails
|
|
26
|
-
* (one or more) within.
|
|
27
|
-
* See [RegEx information here]{@link https://ihateregex.io/expr/email-2}.
|
|
28
|
-
*
|
|
29
|
-
* @type {RegExp}
|
|
30
|
-
*/
|
|
31
|
-
containsEmails:
|
|
32
|
-
/(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/g,
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Matches a UUID
|
|
36
|
-
* @type {RegExp}
|
|
37
|
-
*/
|
|
38
|
-
uuid: /^[a-f\d]{8}(?:-[a-f\d]{4}){3}-[a-f\d]{12}$/,
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Same as this.email, but allows for surrounding characters
|
|
42
|
-
* @type {RegExp}
|
|
43
|
-
*/
|
|
44
|
-
execEmail: /[^\s]+?@[^\s]+?/,
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Same as this.uuid but allows for surrounding characters
|
|
48
|
-
* @type {RegExp}
|
|
49
|
-
*/
|
|
50
|
-
execUuid: /[a-f\d]{8}(?:-[a-f\d]{4}){3}-[a-f\d]{12}/,
|
|
51
|
-
};
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @description Set of regex patterns to compile once and use throughout the
|
|
7
|
+
* app. All non-prefixed patterns have start/end characters to ensure exact
|
|
8
|
+
* matches. Patterns prefixed with "exec" are the same as their non-prefixed
|
|
9
|
+
* counterparts but without the start/end characters so they can be used with
|
|
10
|
+
* methods like `RegExp#exec`.
|
|
11
|
+
*/
|
|
12
|
+
export default {
|
|
13
|
+
/**
|
|
14
|
+
* Regular express that validates a string is strictly an email.
|
|
15
|
+
* Allows for validation of emails within services such as conversation
|
|
16
|
+
* activities or user details.
|
|
17
|
+
* See [RegEx information here]{@link https://ihateregex.io/expr/email-2}.
|
|
18
|
+
*
|
|
19
|
+
* @type {RegExp}
|
|
20
|
+
*/
|
|
21
|
+
email:
|
|
22
|
+
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Regular expression that validates an ambiguous string contains emails
|
|
26
|
+
* (one or more) within.
|
|
27
|
+
* See [RegEx information here]{@link https://ihateregex.io/expr/email-2}.
|
|
28
|
+
*
|
|
29
|
+
* @type {RegExp}
|
|
30
|
+
*/
|
|
31
|
+
containsEmails:
|
|
32
|
+
/(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/g,
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Matches a UUID
|
|
36
|
+
* @type {RegExp}
|
|
37
|
+
*/
|
|
38
|
+
uuid: /^[a-f\d]{8}(?:-[a-f\d]{4}){3}-[a-f\d]{12}$/,
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Same as this.email, but allows for surrounding characters
|
|
42
|
+
* @type {RegExp}
|
|
43
|
+
*/
|
|
44
|
+
execEmail: /[^\s]+?@[^\s]+?/,
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Same as this.uuid but allows for surrounding characters
|
|
48
|
+
* @type {RegExp}
|
|
49
|
+
*/
|
|
50
|
+
execUuid: /[a-f\d]{8}(?:-[a-f\d]{4}){3}-[a-f\d]{12}/,
|
|
51
|
+
};
|
package/src/resolve-with.js
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Sugar method for returning the desired object at the end of a promise chain
|
|
7
|
-
* @param {any} object the item with which to resolve the promise chain
|
|
8
|
-
* @returns {function}
|
|
9
|
-
* @example
|
|
10
|
-
* var item = {
|
|
11
|
-
* prop: 2
|
|
12
|
-
* };
|
|
13
|
-
* Promise
|
|
14
|
-
* .resolve(item.prop)
|
|
15
|
-
* .then(resolveWith(item))
|
|
16
|
-
* .then(function(res) {
|
|
17
|
-
* require('assert').deepEqual(res, {prop:2});
|
|
18
|
-
* return 'success'
|
|
19
|
-
* })
|
|
20
|
-
* // => success
|
|
21
|
-
*
|
|
22
|
-
*/
|
|
23
|
-
export default function resolveWith(object) {
|
|
24
|
-
return function resolver() {
|
|
25
|
-
return Promise.resolve(object);
|
|
26
|
-
};
|
|
27
|
-
}
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Sugar method for returning the desired object at the end of a promise chain
|
|
7
|
+
* @param {any} object the item with which to resolve the promise chain
|
|
8
|
+
* @returns {function}
|
|
9
|
+
* @example
|
|
10
|
+
* var item = {
|
|
11
|
+
* prop: 2
|
|
12
|
+
* };
|
|
13
|
+
* Promise
|
|
14
|
+
* .resolve(item.prop)
|
|
15
|
+
* .then(resolveWith(item))
|
|
16
|
+
* .then(function(res) {
|
|
17
|
+
* require('assert').deepEqual(res, {prop:2});
|
|
18
|
+
* return 'success'
|
|
19
|
+
* })
|
|
20
|
+
* // => success
|
|
21
|
+
*
|
|
22
|
+
*/
|
|
23
|
+
export default function resolveWith(object) {
|
|
24
|
+
return function resolver() {
|
|
25
|
+
return Promise.resolve(object);
|
|
26
|
+
};
|
|
27
|
+
}
|
package/src/retry.js
CHANGED
|
@@ -1,124 +1,124 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import {EventEmitter} from 'events';
|
|
6
|
-
|
|
7
|
-
import {defaults, isFunction, wrap} from 'lodash';
|
|
8
|
-
import backoff from 'backoff';
|
|
9
|
-
|
|
10
|
-
/* eslint max-nested-callbacks: [0] */
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Makes a promise-returning method retryable according to the specified backoff
|
|
14
|
-
* pattern
|
|
15
|
-
* @param {Object} options
|
|
16
|
-
* @param {boolean} options.backoff
|
|
17
|
-
* @param {number} options.delay
|
|
18
|
-
* @param {number} options.initialDelay
|
|
19
|
-
* @param {number} options.maxAttempts
|
|
20
|
-
* @param {number} options.maxDelay
|
|
21
|
-
*
|
|
22
|
-
* @returns {Function}
|
|
23
|
-
*/
|
|
24
|
-
export default function retry(...params) {
|
|
25
|
-
let options = params[0] || {};
|
|
26
|
-
|
|
27
|
-
options = {...options};
|
|
28
|
-
defaults(options, {
|
|
29
|
-
backoff: true,
|
|
30
|
-
delay: 1,
|
|
31
|
-
maxAttempts: 3,
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
let strategyOptions;
|
|
35
|
-
|
|
36
|
-
if (options.backoff) {
|
|
37
|
-
strategyOptions = {
|
|
38
|
-
initialDelay: options.delay,
|
|
39
|
-
maxDelay: options.maxDelay,
|
|
40
|
-
};
|
|
41
|
-
} else {
|
|
42
|
-
strategyOptions = {
|
|
43
|
-
initialDelay: 1,
|
|
44
|
-
maxDelay: 1,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (params.length === 3) {
|
|
49
|
-
return Reflect.apply(retryDecorator, null, params);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return retryDecorator;
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* @param {Object} target
|
|
56
|
-
* @param {string} prop
|
|
57
|
-
* @param {Object} descriptor
|
|
58
|
-
* @private
|
|
59
|
-
* @returns {Object}
|
|
60
|
-
*/
|
|
61
|
-
function retryDecorator(target, prop, descriptor) {
|
|
62
|
-
descriptor.value = wrap(descriptor.value, function retryExecutor(fn, ...args) {
|
|
63
|
-
const emitter = new EventEmitter();
|
|
64
|
-
const promise = new Promise((resolve, reject) => {
|
|
65
|
-
// backoff.call is not Function.prototype.call; it's an unfortunate naming
|
|
66
|
-
// collision.
|
|
67
|
-
/* eslint prefer-reflect: [0] */
|
|
68
|
-
const call = backoff.call(
|
|
69
|
-
(cb) => {
|
|
70
|
-
/* eslint no-invalid-this: [0] */
|
|
71
|
-
const innerPromise = Reflect.apply(fn, this, args);
|
|
72
|
-
|
|
73
|
-
if (isFunction(innerPromise.on)) {
|
|
74
|
-
innerPromise.on('progress', emitter.emit.bind(emitter, 'progress'));
|
|
75
|
-
innerPromise.on('upload-progress', emitter.emit.bind(emitter, 'upload-progress'));
|
|
76
|
-
innerPromise.on('download-progress', emitter.emit.bind(emitter, 'download-progress'));
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return innerPromise
|
|
80
|
-
.then((res) => {
|
|
81
|
-
cb(null, res);
|
|
82
|
-
})
|
|
83
|
-
.catch((reason) => {
|
|
84
|
-
if (!reason) {
|
|
85
|
-
reason = new Error('retryable method failed without providing an error object');
|
|
86
|
-
}
|
|
87
|
-
cb(reason);
|
|
88
|
-
});
|
|
89
|
-
},
|
|
90
|
-
(err, res) => {
|
|
91
|
-
if (err) {
|
|
92
|
-
return reject(err);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return resolve(res);
|
|
96
|
-
}
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
call.setStrategy(new backoff.ExponentialStrategy(strategyOptions));
|
|
100
|
-
if (options.maxAttempts) {
|
|
101
|
-
call.failAfter(options.maxAttempts - 1);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
call.start();
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
promise.on = function on(key, callback) {
|
|
108
|
-
emitter.on(key, callback);
|
|
109
|
-
|
|
110
|
-
return promise;
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
return promise;
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
// This *should* make decorators compatible with AmpersandState class
|
|
117
|
-
// definitions
|
|
118
|
-
if (typeof target === 'object' && !target.prototype) {
|
|
119
|
-
target[prop] = descriptor.value;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
return descriptor;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {EventEmitter} from 'events';
|
|
6
|
+
|
|
7
|
+
import {defaults, isFunction, wrap} from 'lodash';
|
|
8
|
+
import backoff from 'backoff';
|
|
9
|
+
|
|
10
|
+
/* eslint max-nested-callbacks: [0] */
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Makes a promise-returning method retryable according to the specified backoff
|
|
14
|
+
* pattern
|
|
15
|
+
* @param {Object} options
|
|
16
|
+
* @param {boolean} options.backoff
|
|
17
|
+
* @param {number} options.delay
|
|
18
|
+
* @param {number} options.initialDelay
|
|
19
|
+
* @param {number} options.maxAttempts
|
|
20
|
+
* @param {number} options.maxDelay
|
|
21
|
+
*
|
|
22
|
+
* @returns {Function}
|
|
23
|
+
*/
|
|
24
|
+
export default function retry(...params) {
|
|
25
|
+
let options = params[0] || {};
|
|
26
|
+
|
|
27
|
+
options = {...options};
|
|
28
|
+
defaults(options, {
|
|
29
|
+
backoff: true,
|
|
30
|
+
delay: 1,
|
|
31
|
+
maxAttempts: 3,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
let strategyOptions;
|
|
35
|
+
|
|
36
|
+
if (options.backoff) {
|
|
37
|
+
strategyOptions = {
|
|
38
|
+
initialDelay: options.delay,
|
|
39
|
+
maxDelay: options.maxDelay,
|
|
40
|
+
};
|
|
41
|
+
} else {
|
|
42
|
+
strategyOptions = {
|
|
43
|
+
initialDelay: 1,
|
|
44
|
+
maxDelay: 1,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (params.length === 3) {
|
|
49
|
+
return Reflect.apply(retryDecorator, null, params);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return retryDecorator;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @param {Object} target
|
|
56
|
+
* @param {string} prop
|
|
57
|
+
* @param {Object} descriptor
|
|
58
|
+
* @private
|
|
59
|
+
* @returns {Object}
|
|
60
|
+
*/
|
|
61
|
+
function retryDecorator(target, prop, descriptor) {
|
|
62
|
+
descriptor.value = wrap(descriptor.value, function retryExecutor(fn, ...args) {
|
|
63
|
+
const emitter = new EventEmitter();
|
|
64
|
+
const promise = new Promise((resolve, reject) => {
|
|
65
|
+
// backoff.call is not Function.prototype.call; it's an unfortunate naming
|
|
66
|
+
// collision.
|
|
67
|
+
/* eslint prefer-reflect: [0] */
|
|
68
|
+
const call = backoff.call(
|
|
69
|
+
(cb) => {
|
|
70
|
+
/* eslint no-invalid-this: [0] */
|
|
71
|
+
const innerPromise = Reflect.apply(fn, this, args);
|
|
72
|
+
|
|
73
|
+
if (isFunction(innerPromise.on)) {
|
|
74
|
+
innerPromise.on('progress', emitter.emit.bind(emitter, 'progress'));
|
|
75
|
+
innerPromise.on('upload-progress', emitter.emit.bind(emitter, 'upload-progress'));
|
|
76
|
+
innerPromise.on('download-progress', emitter.emit.bind(emitter, 'download-progress'));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return innerPromise
|
|
80
|
+
.then((res) => {
|
|
81
|
+
cb(null, res);
|
|
82
|
+
})
|
|
83
|
+
.catch((reason) => {
|
|
84
|
+
if (!reason) {
|
|
85
|
+
reason = new Error('retryable method failed without providing an error object');
|
|
86
|
+
}
|
|
87
|
+
cb(reason);
|
|
88
|
+
});
|
|
89
|
+
},
|
|
90
|
+
(err, res) => {
|
|
91
|
+
if (err) {
|
|
92
|
+
return reject(err);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return resolve(res);
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
call.setStrategy(new backoff.ExponentialStrategy(strategyOptions));
|
|
100
|
+
if (options.maxAttempts) {
|
|
101
|
+
call.failAfter(options.maxAttempts - 1);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
call.start();
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
promise.on = function on(key, callback) {
|
|
108
|
+
emitter.on(key, callback);
|
|
109
|
+
|
|
110
|
+
return promise;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
return promise;
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// This *should* make decorators compatible with AmpersandState class
|
|
117
|
+
// definitions
|
|
118
|
+
if (typeof target === 'object' && !target.prototype) {
|
|
119
|
+
target[prop] = descriptor.value;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return descriptor;
|
|
123
|
+
}
|
|
124
|
+
}
|
package/src/tap.js
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Injects code into a promise chain without modifying the promise chain's result
|
|
7
|
-
* @param {Function} fn
|
|
8
|
-
* @returns {Promise}
|
|
9
|
-
* @example
|
|
10
|
-
* function f() {
|
|
11
|
-
* return Promise.resolve(5);
|
|
12
|
-
* }
|
|
13
|
-
*
|
|
14
|
-
* f()
|
|
15
|
-
* .then(tap(() => 12))
|
|
16
|
-
* // => 5
|
|
17
|
-
*/
|
|
18
|
-
export default function tap(fn) {
|
|
19
|
-
return (r) =>
|
|
20
|
-
new Promise((resolve) => {
|
|
21
|
-
resolve(fn(r));
|
|
22
|
-
})
|
|
23
|
-
.then(() => r)
|
|
24
|
-
.catch(() => r);
|
|
25
|
-
}
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Injects code into a promise chain without modifying the promise chain's result
|
|
7
|
+
* @param {Function} fn
|
|
8
|
+
* @returns {Promise}
|
|
9
|
+
* @example
|
|
10
|
+
* function f() {
|
|
11
|
+
* return Promise.resolve(5);
|
|
12
|
+
* }
|
|
13
|
+
*
|
|
14
|
+
* f()
|
|
15
|
+
* .then(tap(() => 12))
|
|
16
|
+
* // => 5
|
|
17
|
+
*/
|
|
18
|
+
export default function tap(fn) {
|
|
19
|
+
return (r) =>
|
|
20
|
+
new Promise((resolve) => {
|
|
21
|
+
resolve(fn(r));
|
|
22
|
+
})
|
|
23
|
+
.then(() => r)
|
|
24
|
+
.catch(() => r);
|
|
25
|
+
}
|