@webex/common 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.
- 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 +11 -12
- 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/uuid-utils.js
CHANGED
|
@@ -1,189 +1,189 @@
|
|
|
1
|
-
import {encode, decode} from './base64';
|
|
2
|
-
import {
|
|
3
|
-
SDK_EVENT,
|
|
4
|
-
hydraTypes,
|
|
5
|
-
INTERNAL_US_CLUSTER_NAME,
|
|
6
|
-
INTERNAL_US_INTEGRATION_CLUSTER_NAME,
|
|
7
|
-
} from './constants';
|
|
8
|
-
|
|
9
|
-
const hydraBaseUrl = 'https://api.ciscospark.com/v1';
|
|
10
|
-
|
|
11
|
-
const isRequired = () => {
|
|
12
|
-
throw Error('parameter is required');
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Constructs a Hydra ID for a given UUID and type.
|
|
17
|
-
*
|
|
18
|
-
* @export
|
|
19
|
-
* @param {string} type one of PEOPLE, TEAM, ROOM
|
|
20
|
-
* @param {any} id identifying the "TYPE" object
|
|
21
|
-
* @param {string} cluster containing the "TYPE" object
|
|
22
|
-
* @returns {string}
|
|
23
|
-
*/
|
|
24
|
-
export function constructHydraId(type = isRequired(), id = isRequired(), cluster = 'us') {
|
|
25
|
-
if (!type.toUpperCase) {
|
|
26
|
-
throw Error('"type" must be a string');
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (type === hydraTypes.PEOPLE || type === hydraTypes.ORGANIZATION) {
|
|
30
|
-
// Cluster is always "us" for people and orgs
|
|
31
|
-
return encode(`ciscospark://us/${type.toUpperCase()}/${id}`);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return encode(`ciscospark://${cluster}/${type.toUpperCase()}/${id}`);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* @typedef {Object} DeconstructedHydraId
|
|
39
|
-
* @property {UUID} id identifying the object
|
|
40
|
-
* @property {String} type of the object
|
|
41
|
-
* @property {String} cluster containing the object
|
|
42
|
-
*/
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Deconstructs a Hydra ID.
|
|
46
|
-
*
|
|
47
|
-
* @export
|
|
48
|
-
* @param {String} id Hydra style id
|
|
49
|
-
* @returns {DeconstructedHydraId} deconstructed id
|
|
50
|
-
*/
|
|
51
|
-
export function deconstructHydraId(id) {
|
|
52
|
-
const payload = decode(id).split('/');
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
id: payload.pop(),
|
|
56
|
-
type: payload.pop(),
|
|
57
|
-
cluster: payload.pop(),
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Constructs a Hydra ID for a message based on internal UUID
|
|
63
|
-
*
|
|
64
|
-
* @export
|
|
65
|
-
* @param {any} uuid
|
|
66
|
-
* @param {string} cluster containing the message
|
|
67
|
-
* @returns {string}
|
|
68
|
-
*/
|
|
69
|
-
export function buildHydraMessageId(uuid, cluster) {
|
|
70
|
-
return constructHydraId(hydraTypes.MESSAGE, uuid, cluster);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Constructs a Hydra ID for a person based on internal UUID
|
|
75
|
-
*
|
|
76
|
-
* @export
|
|
77
|
-
* @param {any} uuid
|
|
78
|
-
* @param {string} cluster containing the person
|
|
79
|
-
* @returns {string}
|
|
80
|
-
*/
|
|
81
|
-
export function buildHydraPersonId(uuid, cluster) {
|
|
82
|
-
return constructHydraId(hydraTypes.PEOPLE, uuid, cluster);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Constructs a Hydra ID for a room based on internal UUID
|
|
87
|
-
*
|
|
88
|
-
* @export
|
|
89
|
-
* @param {any} uuid
|
|
90
|
-
* @param {string} cluster containing the room
|
|
91
|
-
* @returns {string}
|
|
92
|
-
*/
|
|
93
|
-
export function buildHydraRoomId(uuid, cluster) {
|
|
94
|
-
return constructHydraId(hydraTypes.ROOM, uuid, cluster);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Constructs a Hydra ID for an organization based on internal UUID
|
|
99
|
-
*
|
|
100
|
-
* @export
|
|
101
|
-
* @param {any} uuid
|
|
102
|
-
* @param {string} cluster containing the organization
|
|
103
|
-
* @returns {string}
|
|
104
|
-
*/
|
|
105
|
-
export function buildHydraOrgId(uuid, cluster) {
|
|
106
|
-
return constructHydraId(hydraTypes.ORGANIZATION, uuid, cluster);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Constructs a Hydra ID for an membership based on an
|
|
111
|
-
* internal UUID for the person, and the space
|
|
112
|
-
*
|
|
113
|
-
* @export
|
|
114
|
-
* @param {any} personUUID
|
|
115
|
-
* @param {any} spaceUUID
|
|
116
|
-
* @param {string} cluster containing the membership
|
|
117
|
-
* @returns {string}
|
|
118
|
-
*/
|
|
119
|
-
export function buildHydraMembershipId(personUUID, spaceUUID, cluster) {
|
|
120
|
-
return constructHydraId(hydraTypes.MEMBERSHIP, `${personUUID}:${spaceUUID}`, cluster);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Returns a hydra cluster string based on a conversation url
|
|
125
|
-
* @private
|
|
126
|
-
* @memberof Messages
|
|
127
|
-
* @param {Object} webex sdk instance
|
|
128
|
-
* @param {String} conversationUrl url of space where activity took place
|
|
129
|
-
* @returns {String} string suitable for UUID -> public ID encoding
|
|
130
|
-
*/
|
|
131
|
-
export function getHydraClusterString(webex, conversationUrl) {
|
|
132
|
-
const internalClusterString = webex.internal.services.getClusterId(conversationUrl);
|
|
133
|
-
|
|
134
|
-
if (
|
|
135
|
-
internalClusterString.startsWith(INTERNAL_US_CLUSTER_NAME) ||
|
|
136
|
-
internalClusterString.startsWith(INTERNAL_US_INTEGRATION_CLUSTER_NAME)
|
|
137
|
-
) {
|
|
138
|
-
// Original US cluster is simply 'us' for backwards compatibility
|
|
139
|
-
return 'us';
|
|
140
|
-
}
|
|
141
|
-
const clusterParts = internalClusterString.split(':');
|
|
142
|
-
|
|
143
|
-
if (clusterParts.length < 3) {
|
|
144
|
-
throw Error(`Unable to determine cluster for convo: ${conversationUrl}`);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return `${clusterParts[0]}:${clusterParts[1]}:${clusterParts[2]}`;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Returns a Hydra roomType based on conversation tags
|
|
152
|
-
*
|
|
153
|
-
* @export
|
|
154
|
-
* @param {arra} tags
|
|
155
|
-
* @returns {string}
|
|
156
|
-
*/
|
|
157
|
-
export function getHydraRoomType(tags) {
|
|
158
|
-
if (tags.includes(SDK_EVENT.INTERNAL.ACTIVITY_TAG.ONE_ON_ONE)) {
|
|
159
|
-
return SDK_EVENT.EXTERNAL.SPACE_TYPE.DIRECT;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
return SDK_EVENT.EXTERNAL.SPACE_TYPE.GROUP;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Returns file URLs for the activity, adhering to Hydra details,
|
|
167
|
-
* e.g., https://api.ciscospark.com/v1/contents/Y2lzY29zcGF...
|
|
168
|
-
* @see https://developer.webex.com/docs/api/v1/messages/get-message-details
|
|
169
|
-
* @param {Object} activity from mercury
|
|
170
|
-
* @param {string} cluster containing the files
|
|
171
|
-
* @returns {Array} file URLs
|
|
172
|
-
*/
|
|
173
|
-
export function getHydraFiles(activity, cluster) {
|
|
174
|
-
const hydraFiles = [];
|
|
175
|
-
const {files} = activity.object;
|
|
176
|
-
|
|
177
|
-
if (files) {
|
|
178
|
-
const {items} = files;
|
|
179
|
-
|
|
180
|
-
// Note: Generated ID is dependent on file order.
|
|
181
|
-
for (let i = 0; i < items.length; i += 1) {
|
|
182
|
-
const contentId = constructHydraId(hydraTypes.CONTENT, `${activity.id}/${i}`, cluster);
|
|
183
|
-
|
|
184
|
-
hydraFiles.push(`${hydraBaseUrl}/contents/${contentId}`);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return hydraFiles;
|
|
189
|
-
}
|
|
1
|
+
import {encode, decode} from './base64';
|
|
2
|
+
import {
|
|
3
|
+
SDK_EVENT,
|
|
4
|
+
hydraTypes,
|
|
5
|
+
INTERNAL_US_CLUSTER_NAME,
|
|
6
|
+
INTERNAL_US_INTEGRATION_CLUSTER_NAME,
|
|
7
|
+
} from './constants';
|
|
8
|
+
|
|
9
|
+
const hydraBaseUrl = 'https://api.ciscospark.com/v1';
|
|
10
|
+
|
|
11
|
+
const isRequired = () => {
|
|
12
|
+
throw Error('parameter is required');
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Constructs a Hydra ID for a given UUID and type.
|
|
17
|
+
*
|
|
18
|
+
* @export
|
|
19
|
+
* @param {string} type one of PEOPLE, TEAM, ROOM
|
|
20
|
+
* @param {any} id identifying the "TYPE" object
|
|
21
|
+
* @param {string} cluster containing the "TYPE" object
|
|
22
|
+
* @returns {string}
|
|
23
|
+
*/
|
|
24
|
+
export function constructHydraId(type = isRequired(), id = isRequired(), cluster = 'us') {
|
|
25
|
+
if (!type.toUpperCase) {
|
|
26
|
+
throw Error('"type" must be a string');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (type === hydraTypes.PEOPLE || type === hydraTypes.ORGANIZATION) {
|
|
30
|
+
// Cluster is always "us" for people and orgs
|
|
31
|
+
return encode(`ciscospark://us/${type.toUpperCase()}/${id}`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return encode(`ciscospark://${cluster}/${type.toUpperCase()}/${id}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @typedef {Object} DeconstructedHydraId
|
|
39
|
+
* @property {UUID} id identifying the object
|
|
40
|
+
* @property {String} type of the object
|
|
41
|
+
* @property {String} cluster containing the object
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Deconstructs a Hydra ID.
|
|
46
|
+
*
|
|
47
|
+
* @export
|
|
48
|
+
* @param {String} id Hydra style id
|
|
49
|
+
* @returns {DeconstructedHydraId} deconstructed id
|
|
50
|
+
*/
|
|
51
|
+
export function deconstructHydraId(id) {
|
|
52
|
+
const payload = decode(id).split('/');
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
id: payload.pop(),
|
|
56
|
+
type: payload.pop(),
|
|
57
|
+
cluster: payload.pop(),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Constructs a Hydra ID for a message based on internal UUID
|
|
63
|
+
*
|
|
64
|
+
* @export
|
|
65
|
+
* @param {any} uuid
|
|
66
|
+
* @param {string} cluster containing the message
|
|
67
|
+
* @returns {string}
|
|
68
|
+
*/
|
|
69
|
+
export function buildHydraMessageId(uuid, cluster) {
|
|
70
|
+
return constructHydraId(hydraTypes.MESSAGE, uuid, cluster);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Constructs a Hydra ID for a person based on internal UUID
|
|
75
|
+
*
|
|
76
|
+
* @export
|
|
77
|
+
* @param {any} uuid
|
|
78
|
+
* @param {string} cluster containing the person
|
|
79
|
+
* @returns {string}
|
|
80
|
+
*/
|
|
81
|
+
export function buildHydraPersonId(uuid, cluster) {
|
|
82
|
+
return constructHydraId(hydraTypes.PEOPLE, uuid, cluster);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Constructs a Hydra ID for a room based on internal UUID
|
|
87
|
+
*
|
|
88
|
+
* @export
|
|
89
|
+
* @param {any} uuid
|
|
90
|
+
* @param {string} cluster containing the room
|
|
91
|
+
* @returns {string}
|
|
92
|
+
*/
|
|
93
|
+
export function buildHydraRoomId(uuid, cluster) {
|
|
94
|
+
return constructHydraId(hydraTypes.ROOM, uuid, cluster);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Constructs a Hydra ID for an organization based on internal UUID
|
|
99
|
+
*
|
|
100
|
+
* @export
|
|
101
|
+
* @param {any} uuid
|
|
102
|
+
* @param {string} cluster containing the organization
|
|
103
|
+
* @returns {string}
|
|
104
|
+
*/
|
|
105
|
+
export function buildHydraOrgId(uuid, cluster) {
|
|
106
|
+
return constructHydraId(hydraTypes.ORGANIZATION, uuid, cluster);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Constructs a Hydra ID for an membership based on an
|
|
111
|
+
* internal UUID for the person, and the space
|
|
112
|
+
*
|
|
113
|
+
* @export
|
|
114
|
+
* @param {any} personUUID
|
|
115
|
+
* @param {any} spaceUUID
|
|
116
|
+
* @param {string} cluster containing the membership
|
|
117
|
+
* @returns {string}
|
|
118
|
+
*/
|
|
119
|
+
export function buildHydraMembershipId(personUUID, spaceUUID, cluster) {
|
|
120
|
+
return constructHydraId(hydraTypes.MEMBERSHIP, `${personUUID}:${spaceUUID}`, cluster);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Returns a hydra cluster string based on a conversation url
|
|
125
|
+
* @private
|
|
126
|
+
* @memberof Messages
|
|
127
|
+
* @param {Object} webex sdk instance
|
|
128
|
+
* @param {String} conversationUrl url of space where activity took place
|
|
129
|
+
* @returns {String} string suitable for UUID -> public ID encoding
|
|
130
|
+
*/
|
|
131
|
+
export function getHydraClusterString(webex, conversationUrl) {
|
|
132
|
+
const internalClusterString = webex.internal.services.getClusterId(conversationUrl);
|
|
133
|
+
|
|
134
|
+
if (
|
|
135
|
+
internalClusterString.startsWith(INTERNAL_US_CLUSTER_NAME) ||
|
|
136
|
+
internalClusterString.startsWith(INTERNAL_US_INTEGRATION_CLUSTER_NAME)
|
|
137
|
+
) {
|
|
138
|
+
// Original US cluster is simply 'us' for backwards compatibility
|
|
139
|
+
return 'us';
|
|
140
|
+
}
|
|
141
|
+
const clusterParts = internalClusterString.split(':');
|
|
142
|
+
|
|
143
|
+
if (clusterParts.length < 3) {
|
|
144
|
+
throw Error(`Unable to determine cluster for convo: ${conversationUrl}`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return `${clusterParts[0]}:${clusterParts[1]}:${clusterParts[2]}`;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Returns a Hydra roomType based on conversation tags
|
|
152
|
+
*
|
|
153
|
+
* @export
|
|
154
|
+
* @param {arra} tags
|
|
155
|
+
* @returns {string}
|
|
156
|
+
*/
|
|
157
|
+
export function getHydraRoomType(tags) {
|
|
158
|
+
if (tags.includes(SDK_EVENT.INTERNAL.ACTIVITY_TAG.ONE_ON_ONE)) {
|
|
159
|
+
return SDK_EVENT.EXTERNAL.SPACE_TYPE.DIRECT;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return SDK_EVENT.EXTERNAL.SPACE_TYPE.GROUP;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Returns file URLs for the activity, adhering to Hydra details,
|
|
167
|
+
* e.g., https://api.ciscospark.com/v1/contents/Y2lzY29zcGF...
|
|
168
|
+
* @see https://developer.webex.com/docs/api/v1/messages/get-message-details
|
|
169
|
+
* @param {Object} activity from mercury
|
|
170
|
+
* @param {string} cluster containing the files
|
|
171
|
+
* @returns {Array} file URLs
|
|
172
|
+
*/
|
|
173
|
+
export function getHydraFiles(activity, cluster) {
|
|
174
|
+
const hydraFiles = [];
|
|
175
|
+
const {files} = activity.object;
|
|
176
|
+
|
|
177
|
+
if (files) {
|
|
178
|
+
const {items} = files;
|
|
179
|
+
|
|
180
|
+
// Note: Generated ID is dependent on file order.
|
|
181
|
+
for (let i = 0; i < items.length; i += 1) {
|
|
182
|
+
const contentId = constructHydraId(hydraTypes.CONTENT, `${activity.id}/${i}`, cluster);
|
|
183
|
+
|
|
184
|
+
hydraFiles.push(`${hydraBaseUrl}/contents/${contentId}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return hydraFiles;
|
|
189
|
+
}
|
package/src/while-in-flight.js
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/* eslint no-invalid-this: [0] */
|
|
6
|
-
|
|
7
|
-
import {wrap} from 'lodash';
|
|
8
|
-
|
|
9
|
-
import tap from './tap';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* While the promise returned by the decorated is unfullfilled, sets, the
|
|
13
|
-
* specified boolean on the target class to `true`
|
|
14
|
-
* @param {string} param
|
|
15
|
-
* @returns {Function}
|
|
16
|
-
*/
|
|
17
|
-
export default function whileInFlight(param) {
|
|
18
|
-
return function whileInFlightDecorator(target, name, descriptor) {
|
|
19
|
-
descriptor.value = wrap(descriptor.value, function whileInFlightExecutor(fn, ...args) {
|
|
20
|
-
return new Promise((resolve) => {
|
|
21
|
-
this[param] = true;
|
|
22
|
-
resolve(
|
|
23
|
-
Reflect.apply(fn, this, args)
|
|
24
|
-
.then(
|
|
25
|
-
tap(() => {
|
|
26
|
-
this[param] = false;
|
|
27
|
-
})
|
|
28
|
-
)
|
|
29
|
-
.catch((reason) => {
|
|
30
|
-
this[param] = false;
|
|
31
|
-
|
|
32
|
-
return Promise.reject(reason);
|
|
33
|
-
})
|
|
34
|
-
);
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
};
|
|
38
|
-
}
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/* eslint no-invalid-this: [0] */
|
|
6
|
+
|
|
7
|
+
import {wrap} from 'lodash';
|
|
8
|
+
|
|
9
|
+
import tap from './tap';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* While the promise returned by the decorated is unfullfilled, sets, the
|
|
13
|
+
* specified boolean on the target class to `true`
|
|
14
|
+
* @param {string} param
|
|
15
|
+
* @returns {Function}
|
|
16
|
+
*/
|
|
17
|
+
export default function whileInFlight(param) {
|
|
18
|
+
return function whileInFlightDecorator(target, name, descriptor) {
|
|
19
|
+
descriptor.value = wrap(descriptor.value, function whileInFlightExecutor(fn, ...args) {
|
|
20
|
+
return new Promise((resolve) => {
|
|
21
|
+
this[param] = true;
|
|
22
|
+
resolve(
|
|
23
|
+
Reflect.apply(fn, this, args)
|
|
24
|
+
.then(
|
|
25
|
+
tap(() => {
|
|
26
|
+
this[param] = false;
|
|
27
|
+
})
|
|
28
|
+
)
|
|
29
|
+
.catch((reason) => {
|
|
30
|
+
this[param] = false;
|
|
31
|
+
|
|
32
|
+
return Promise.reject(reason);
|
|
33
|
+
})
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -1,103 +1,103 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import {assert} from '@webex/test-helper-chai';
|
|
6
|
-
import sinon from 'sinon';
|
|
7
|
-
import {cappedDebounce} from '@webex/common';
|
|
8
|
-
import FakeTimers from '@sinonjs/fake-timers';
|
|
9
|
-
|
|
10
|
-
describe('common', () => {
|
|
11
|
-
describe('cappedDebounce()', () => {
|
|
12
|
-
let clock;
|
|
13
|
-
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
clock = FakeTimers.install({now: Date.now()});
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
afterEach(() => {
|
|
19
|
-
clock.uninstall();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('requires a function', () => {
|
|
23
|
-
assert.throws(cappedDebounce, /`fn` must be a function/);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('requires a `wait`', () => {
|
|
27
|
-
assert.throws(cappedDebounce.bind(null, sinon.spy()), /`wait` is required/);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('requires a `maxWait`', () => {
|
|
31
|
-
assert.throws(cappedDebounce.bind(null, sinon.spy(), 5), /`options.maxWait` is required/);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('requires a `maxCalls`', () => {
|
|
35
|
-
assert.throws(
|
|
36
|
-
cappedDebounce.bind(null, sinon.spy(), 5, {maxWait: 10}),
|
|
37
|
-
/`options.maxCalls` is required/
|
|
38
|
-
);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('returns a function that will execute once it stops being invoked for `wait` ms', () => {
|
|
42
|
-
const spy = sinon.spy();
|
|
43
|
-
const fn = cappedDebounce(spy, 50, {maxWait: 1000, maxCalls: 10000});
|
|
44
|
-
|
|
45
|
-
fn();
|
|
46
|
-
fn();
|
|
47
|
-
fn();
|
|
48
|
-
fn();
|
|
49
|
-
assert.notCalled(spy);
|
|
50
|
-
clock.tick(20);
|
|
51
|
-
assert.notCalled(spy);
|
|
52
|
-
clock.tick(40);
|
|
53
|
-
assert.calledOnce(spy);
|
|
54
|
-
clock.tick(40);
|
|
55
|
-
assert.calledOnce(spy);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('returns a function that will execute once if it continues to be invoked for `wait` ms after `maxWait` ms', () => {
|
|
59
|
-
const spy = sinon.spy();
|
|
60
|
-
const fn = cappedDebounce(spy, 100, {maxWait: 130, maxCalls: 10000});
|
|
61
|
-
|
|
62
|
-
fn();
|
|
63
|
-
assert.notCalled(spy);
|
|
64
|
-
clock.tick(50);
|
|
65
|
-
fn();
|
|
66
|
-
assert.notCalled(spy);
|
|
67
|
-
clock.tick(50);
|
|
68
|
-
fn();
|
|
69
|
-
assert.notCalled(spy);
|
|
70
|
-
clock.tick(50);
|
|
71
|
-
fn();
|
|
72
|
-
assert.calledOnce(spy);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('returns a function that will execute once it has been invoked `maxCalls` times', () => {
|
|
76
|
-
const spy = sinon.spy();
|
|
77
|
-
const fn = cappedDebounce(spy, 50, {maxWait: 100, maxCalls: 4});
|
|
78
|
-
|
|
79
|
-
fn();
|
|
80
|
-
assert.notCalled(spy);
|
|
81
|
-
fn();
|
|
82
|
-
assert.notCalled(spy);
|
|
83
|
-
fn();
|
|
84
|
-
assert.notCalled(spy);
|
|
85
|
-
fn();
|
|
86
|
-
assert.called(spy);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it('returns a function that will execute once it has been invoked `maxCalls` times and executes again after `maxWait` ms', () => {
|
|
90
|
-
const spy = sinon.spy();
|
|
91
|
-
const fn = cappedDebounce(spy, 50, {maxWait: 100, maxCalls: 3});
|
|
92
|
-
|
|
93
|
-
fn();
|
|
94
|
-
fn();
|
|
95
|
-
fn();
|
|
96
|
-
assert.called(spy);
|
|
97
|
-
fn();
|
|
98
|
-
fn();
|
|
99
|
-
clock.tick(150);
|
|
100
|
-
assert.calledTwice(spy);
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
});
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {assert} from '@webex/test-helper-chai';
|
|
6
|
+
import sinon from 'sinon';
|
|
7
|
+
import {cappedDebounce} from '@webex/common';
|
|
8
|
+
import FakeTimers from '@sinonjs/fake-timers';
|
|
9
|
+
|
|
10
|
+
describe('common', () => {
|
|
11
|
+
describe('cappedDebounce()', () => {
|
|
12
|
+
let clock;
|
|
13
|
+
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
clock = FakeTimers.install({now: Date.now()});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
clock.uninstall();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('requires a function', () => {
|
|
23
|
+
assert.throws(cappedDebounce, /`fn` must be a function/);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('requires a `wait`', () => {
|
|
27
|
+
assert.throws(cappedDebounce.bind(null, sinon.spy()), /`wait` is required/);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('requires a `maxWait`', () => {
|
|
31
|
+
assert.throws(cappedDebounce.bind(null, sinon.spy(), 5), /`options.maxWait` is required/);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('requires a `maxCalls`', () => {
|
|
35
|
+
assert.throws(
|
|
36
|
+
cappedDebounce.bind(null, sinon.spy(), 5, {maxWait: 10}),
|
|
37
|
+
/`options.maxCalls` is required/
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('returns a function that will execute once it stops being invoked for `wait` ms', () => {
|
|
42
|
+
const spy = sinon.spy();
|
|
43
|
+
const fn = cappedDebounce(spy, 50, {maxWait: 1000, maxCalls: 10000});
|
|
44
|
+
|
|
45
|
+
fn();
|
|
46
|
+
fn();
|
|
47
|
+
fn();
|
|
48
|
+
fn();
|
|
49
|
+
assert.notCalled(spy);
|
|
50
|
+
clock.tick(20);
|
|
51
|
+
assert.notCalled(spy);
|
|
52
|
+
clock.tick(40);
|
|
53
|
+
assert.calledOnce(spy);
|
|
54
|
+
clock.tick(40);
|
|
55
|
+
assert.calledOnce(spy);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('returns a function that will execute once if it continues to be invoked for `wait` ms after `maxWait` ms', () => {
|
|
59
|
+
const spy = sinon.spy();
|
|
60
|
+
const fn = cappedDebounce(spy, 100, {maxWait: 130, maxCalls: 10000});
|
|
61
|
+
|
|
62
|
+
fn();
|
|
63
|
+
assert.notCalled(spy);
|
|
64
|
+
clock.tick(50);
|
|
65
|
+
fn();
|
|
66
|
+
assert.notCalled(spy);
|
|
67
|
+
clock.tick(50);
|
|
68
|
+
fn();
|
|
69
|
+
assert.notCalled(spy);
|
|
70
|
+
clock.tick(50);
|
|
71
|
+
fn();
|
|
72
|
+
assert.calledOnce(spy);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('returns a function that will execute once it has been invoked `maxCalls` times', () => {
|
|
76
|
+
const spy = sinon.spy();
|
|
77
|
+
const fn = cappedDebounce(spy, 50, {maxWait: 100, maxCalls: 4});
|
|
78
|
+
|
|
79
|
+
fn();
|
|
80
|
+
assert.notCalled(spy);
|
|
81
|
+
fn();
|
|
82
|
+
assert.notCalled(spy);
|
|
83
|
+
fn();
|
|
84
|
+
assert.notCalled(spy);
|
|
85
|
+
fn();
|
|
86
|
+
assert.called(spy);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('returns a function that will execute once it has been invoked `maxCalls` times and executes again after `maxWait` ms', () => {
|
|
90
|
+
const spy = sinon.spy();
|
|
91
|
+
const fn = cappedDebounce(spy, 50, {maxWait: 100, maxCalls: 3});
|
|
92
|
+
|
|
93
|
+
fn();
|
|
94
|
+
fn();
|
|
95
|
+
fn();
|
|
96
|
+
assert.called(spy);
|
|
97
|
+
fn();
|
|
98
|
+
fn();
|
|
99
|
+
clock.tick(150);
|
|
100
|
+
assert.calledTwice(spy);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
});
|