@dereekb/zoom 13.0.0 → 13.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs.default.js +1 -0
- package/index.cjs.js +476 -525
- package/index.cjs.mjs +2 -0
- package/index.esm.js +476 -525
- package/nestjs/index.cjs.default.js +1 -0
- package/nestjs/index.cjs.js +487 -452
- package/nestjs/index.cjs.mjs +2 -0
- package/nestjs/index.esm.js +487 -452
- package/nestjs/package.json +20 -15
- package/package.json +21 -24
package/index.esm.js
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import 'core-js/modules/es.json.stringify.js';
|
|
2
1
|
import { fetchPageFactory, FetchResponseError, mergeMakeUrlSearchParamsOptions, makeUrlSearchParams, FetchRequestFactoryError, rateLimitedFetchHandler, fetchApiFetchService, fetchJsonFunction, returnNullHandleFetchJsonParseErrorFunction } from '@dereekb/util/fetch';
|
|
3
|
-
import 'core-js/modules/es.set.difference.v2.js';
|
|
4
|
-
import 'core-js/modules/es.set.symmetric-difference.v2.js';
|
|
5
|
-
import 'core-js/modules/es.set.union.v2.js';
|
|
6
2
|
import { MS_IN_SECOND, asArray, resetPeriodPromiseRateLimiter, MS_IN_MINUTE } from '@dereekb/util';
|
|
7
3
|
import { BaseError } from 'make-error';
|
|
8
4
|
|
|
@@ -15,23 +11,17 @@ import { BaseError } from 'make-error';
|
|
|
15
11
|
* @returns
|
|
16
12
|
*/
|
|
17
13
|
function mapToZoomPageResult(dataTypeKey) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
next_page_token,
|
|
29
|
-
page_count,
|
|
30
|
-
page_number,
|
|
31
|
-
page_size,
|
|
32
|
-
total_records
|
|
14
|
+
return (data) => {
|
|
15
|
+
const { next_page_token, page_count, page_number, page_size, total_records } = data;
|
|
16
|
+
return {
|
|
17
|
+
data: data[dataTypeKey],
|
|
18
|
+
next_page_token,
|
|
19
|
+
page_count,
|
|
20
|
+
page_number,
|
|
21
|
+
page_size,
|
|
22
|
+
total_records
|
|
23
|
+
};
|
|
33
24
|
};
|
|
34
|
-
};
|
|
35
25
|
}
|
|
36
26
|
/**
|
|
37
27
|
* Creates a FetchPageFactory using the input ZoomFetchPageFetchFunction.
|
|
@@ -41,23 +31,19 @@ function mapToZoomPageResult(dataTypeKey) {
|
|
|
41
31
|
* @returns
|
|
42
32
|
*/
|
|
43
33
|
function zoomFetchPageFactory(fetch, defaults) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
page_size: options.maxItemsPerPage ?? input.page_size
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
});
|
|
34
|
+
return fetchPageFactory({
|
|
35
|
+
...defaults,
|
|
36
|
+
fetch,
|
|
37
|
+
readFetchPageResultInfo: function (result) {
|
|
38
|
+
return {
|
|
39
|
+
nextPageCursor: result.next_page_token,
|
|
40
|
+
hasNext: Boolean(result.next_page_token) // has more when a non-empty next_page_token is returned
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
buildInputForNextPage: function (pageResult, input, options) {
|
|
44
|
+
return { ...input, next_page_token: pageResult.nextPageCursor, page_size: options.maxItemsPerPage ?? input.page_size };
|
|
45
|
+
}
|
|
46
|
+
});
|
|
61
47
|
}
|
|
62
48
|
|
|
63
49
|
/**
|
|
@@ -68,26 +54,26 @@ const ZOOM_SUCCESS_CODE = 'SUCCESS';
|
|
|
68
54
|
* Zoom Server Error
|
|
69
55
|
*/
|
|
70
56
|
class ZoomServerError extends BaseError {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
57
|
+
error;
|
|
58
|
+
get code() {
|
|
59
|
+
return this.error.code;
|
|
60
|
+
}
|
|
61
|
+
constructor(error) {
|
|
62
|
+
super(error.message);
|
|
63
|
+
this.error = error;
|
|
64
|
+
}
|
|
79
65
|
}
|
|
80
66
|
/**
|
|
81
67
|
* Zoom Server Error that includes the FetchResponseError
|
|
82
68
|
*/
|
|
83
69
|
class ZoomServerFetchResponseError extends ZoomServerError {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
70
|
+
data;
|
|
71
|
+
responseError;
|
|
72
|
+
constructor(data, responseError) {
|
|
73
|
+
super(data);
|
|
74
|
+
this.data = data;
|
|
75
|
+
this.responseError = responseError;
|
|
76
|
+
}
|
|
91
77
|
}
|
|
92
78
|
/**
|
|
93
79
|
* Creates a logZoomServerErrorFunction that logs the error to console.
|
|
@@ -96,22 +82,17 @@ class ZoomServerFetchResponseError extends ZoomServerError {
|
|
|
96
82
|
* @returns
|
|
97
83
|
*/
|
|
98
84
|
function logZoomServerErrorFunction(zoomApiNamePrefix) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
console.log(`${zoomApiNamePrefix}Error(name:${error.name}): `, {
|
|
111
|
-
error
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
};
|
|
85
|
+
return (error) => {
|
|
86
|
+
if (error instanceof ZoomServerFetchResponseError) {
|
|
87
|
+
console.log(`${zoomApiNamePrefix}Error(${error.responseError.response.status}): `, { error, errorData: error.data });
|
|
88
|
+
}
|
|
89
|
+
else if (error instanceof ZoomServerError) {
|
|
90
|
+
console.log(`${zoomApiNamePrefix}Error(code:${error.code}): `, { error });
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
console.log(`${zoomApiNamePrefix}Error(name:${error.name}): `, { error });
|
|
94
|
+
}
|
|
95
|
+
};
|
|
115
96
|
}
|
|
116
97
|
/**
|
|
117
98
|
* Wraps a ConfiguredFetch to support handling errors returned by fetch.
|
|
@@ -120,22 +101,23 @@ function logZoomServerErrorFunction(zoomApiNamePrefix) {
|
|
|
120
101
|
* @returns
|
|
121
102
|
*/
|
|
122
103
|
function handleZoomErrorFetchFactory(parseZoomError, defaultLogError) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
104
|
+
return (fetch, logError = defaultLogError) => {
|
|
105
|
+
return async (x, y) => {
|
|
106
|
+
try {
|
|
107
|
+
return await fetch(x, y); // await to catch thrown errors
|
|
108
|
+
}
|
|
109
|
+
catch (e) {
|
|
110
|
+
if (e instanceof FetchResponseError) {
|
|
111
|
+
const error = await parseZoomError(e);
|
|
112
|
+
if (error) {
|
|
113
|
+
logError(error); // log before throwing.
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
throw e;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
137
120
|
};
|
|
138
|
-
};
|
|
139
121
|
}
|
|
140
122
|
// MARK: Parsed Errors
|
|
141
123
|
/**
|
|
@@ -154,34 +136,27 @@ const ZOOM_RATE_LIMIT_RETRY_AFTER_HEADER = 'Retry-After';
|
|
|
154
136
|
const DEFAULT_ZOOM_API_RATE_LIMIT = 2;
|
|
155
137
|
const DEFAULT_ZOOM_API_RATE_LIMIT_RESET_PERIOD = MS_IN_SECOND;
|
|
156
138
|
function zoomRateLimitHeaderDetails(headers) {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
retryAfter,
|
|
174
|
-
retryAfterAt,
|
|
175
|
-
category,
|
|
176
|
-
type
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
return result;
|
|
139
|
+
const limitHeader = headers.get(ZOOM_RATE_LIMIT_LIMIT_HEADER);
|
|
140
|
+
const remainingHeader = headers.get(ZOOM_RATE_LIMIT_REMAINING_HEADER);
|
|
141
|
+
const retryAfterHeader = headers.get(ZOOM_RATE_LIMIT_RETRY_AFTER_HEADER);
|
|
142
|
+
const categoryHeader = headers.get(ZOOM_RATE_LIMIT_CATEGORY_HEADER);
|
|
143
|
+
const typeHeader = headers.get(ZOOM_RATE_LIMIT_TYPE_HEADER);
|
|
144
|
+
let result = null;
|
|
145
|
+
if (categoryHeader != null && typeHeader != null) {
|
|
146
|
+
const category = categoryHeader;
|
|
147
|
+
const type = typeHeader;
|
|
148
|
+
const limit = limitHeader ? Number(limitHeader) : undefined;
|
|
149
|
+
const remaining = remainingHeader ? Number(remainingHeader) : undefined;
|
|
150
|
+
const retryAfter = retryAfterHeader ? Number(retryAfterHeader) : undefined;
|
|
151
|
+
const retryAfterAt = retryAfterHeader ? new Date(retryAfterHeader) : undefined;
|
|
152
|
+
result = { limit, remaining, retryAfter, retryAfterAt, category, type };
|
|
153
|
+
}
|
|
154
|
+
return result;
|
|
180
155
|
}
|
|
181
156
|
class ZoomTooManyRequestsError extends ZoomServerFetchResponseError {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
157
|
+
get headerDetails() {
|
|
158
|
+
return zoomRateLimitHeaderDetails(this.responseError.response.headers);
|
|
159
|
+
}
|
|
185
160
|
}
|
|
186
161
|
/**
|
|
187
162
|
* Function that parses/transforms a ZoomServerErrorData into a general ZoomServerError or other known error type.
|
|
@@ -191,22 +166,23 @@ class ZoomTooManyRequestsError extends ZoomServerFetchResponseError {
|
|
|
191
166
|
* @returns
|
|
192
167
|
*/
|
|
193
168
|
function parseZoomServerErrorData(zoomServerError, responseError) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
} else if (zoomServerError) {
|
|
203
|
-
switch (zoomServerError.code) {
|
|
204
|
-
default:
|
|
205
|
-
result = new ZoomServerFetchResponseError(zoomServerError, responseError);
|
|
206
|
-
break;
|
|
169
|
+
let result;
|
|
170
|
+
if (responseError.response.status === ZOOM_TOO_MANY_REQUESTS_HTTP_STATUS_CODE) {
|
|
171
|
+
result = new ZoomTooManyRequestsError(zoomServerError, responseError);
|
|
172
|
+
console.warn('ZoomTooManyRequestsError', {
|
|
173
|
+
result,
|
|
174
|
+
responseError,
|
|
175
|
+
headerDetails: result.headerDetails
|
|
176
|
+
});
|
|
207
177
|
}
|
|
208
|
-
|
|
209
|
-
|
|
178
|
+
else if (zoomServerError) {
|
|
179
|
+
switch (zoomServerError.code) {
|
|
180
|
+
default:
|
|
181
|
+
result = new ZoomServerFetchResponseError(zoomServerError, responseError);
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return result;
|
|
210
186
|
}
|
|
211
187
|
/**
|
|
212
188
|
* Returns a pre-configured MakeUrlSearchParamsOptions that omits the silenceError key.
|
|
@@ -214,84 +190,80 @@ function parseZoomServerErrorData(zoomServerError, responseError) {
|
|
|
214
190
|
* If other options are input, it merges those two options together and adds silenceError to the omitted keys.
|
|
215
191
|
*/
|
|
216
192
|
function omitSilenceZoomErrorKeys(options) {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
omitKeys
|
|
220
|
-
}]);
|
|
193
|
+
const omitKeys = ['silenceError'];
|
|
194
|
+
return mergeMakeUrlSearchParamsOptions([options, { omitKeys }]);
|
|
221
195
|
}
|
|
222
196
|
function silenceZoomErrorWithCodesFunction(codes, returnFn) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
197
|
+
const codesSet = new Set(asArray(codes));
|
|
198
|
+
return (silence) => {
|
|
199
|
+
return (reason) => {
|
|
200
|
+
if (silence !== false && reason instanceof ZoomServerFetchResponseError) {
|
|
201
|
+
if (codesSet.has(reason.code)) {
|
|
202
|
+
return returnFn?.(reason);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
throw reason;
|
|
206
|
+
};
|
|
232
207
|
};
|
|
233
|
-
};
|
|
234
208
|
}
|
|
235
209
|
|
|
236
210
|
/**
|
|
237
211
|
* https://developers.zoom.us/docs/api/rest/reference/zoom-api/methods/#operation/meeting
|
|
238
212
|
*/
|
|
239
213
|
function getMeeting(context) {
|
|
240
|
-
|
|
214
|
+
return (input) => context.fetchJson(`/meetings/${input.meetingId}`, 'GET');
|
|
241
215
|
}
|
|
242
216
|
/**
|
|
243
217
|
* https://developers.zoom.us/docs/api/rest/reference/zoom-api/methods/#operation/meetings
|
|
244
218
|
*/
|
|
245
219
|
function listMeetingsForUser(context) {
|
|
246
|
-
|
|
220
|
+
return (input) => context.fetchJson(`/users/${input.user}/meetings`, 'GET').then(mapToZoomPageResult('meetings'));
|
|
247
221
|
}
|
|
248
222
|
function listMeetingsForUserPageFactory(context) {
|
|
249
|
-
|
|
223
|
+
return zoomFetchPageFactory(listMeetingsForUser(context));
|
|
250
224
|
}
|
|
251
225
|
/**
|
|
252
226
|
* https://developers.zoom.us/docs/api/meetings/#tag/meetings/POST/users/{userId}/meetings
|
|
253
227
|
*/
|
|
254
228
|
function createMeetingForUser(context) {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
229
|
+
return (input) => {
|
|
230
|
+
return context.fetchJson(`/users/${input.user}/meetings`, {
|
|
231
|
+
method: 'POST',
|
|
232
|
+
body: JSON.stringify(input.template)
|
|
233
|
+
});
|
|
234
|
+
};
|
|
261
235
|
}
|
|
262
236
|
/**
|
|
263
237
|
* https://developers.zoom.us/docs/api/meetings/#tag/meetings/PUT/meetings/{meetingId}
|
|
264
238
|
*/
|
|
265
239
|
function updateMeeting(context) {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
body: JSON.stringify(input.template)
|
|
271
|
-
});
|
|
240
|
+
return (input) => context.fetchJson(`/meetings/${input.meetingId}?${makeUrlSearchParams({ occurrence_id: input.occurrence_id })}`, {
|
|
241
|
+
method: 'PATCH',
|
|
242
|
+
body: JSON.stringify(input.template)
|
|
243
|
+
});
|
|
272
244
|
}
|
|
273
245
|
const DELETE_MEETING_DOES_NOT_EXIST_ERROR_CODE = 3001;
|
|
274
246
|
/**
|
|
275
247
|
* https://developers.zoom.us/docs/api/meetings/#tag/meetings/DELETE/meetings/{meetingId}
|
|
276
248
|
*/
|
|
277
249
|
function deleteMeeting(context) {
|
|
278
|
-
|
|
279
|
-
|
|
250
|
+
const silenceDoesNotExistError = silenceZoomErrorWithCodesFunction(DELETE_MEETING_DOES_NOT_EXIST_ERROR_CODE);
|
|
251
|
+
return (input) => context.fetchJson(`/meetings/${input.meetingId}?${makeUrlSearchParams(input, omitSilenceZoomErrorKeys())}`, 'DELETE').catch(silenceDoesNotExistError(input.silenceError));
|
|
280
252
|
}
|
|
281
253
|
/**
|
|
282
254
|
* https://developers.zoom.us/docs/api/meetings/#tag/meetings/GET/past_meetings/{meetingId}
|
|
283
255
|
*/
|
|
284
256
|
function getPastMeeting(context) {
|
|
285
|
-
|
|
257
|
+
return (input) => context.fetchJson(`/past_meetings/${input.meetingId}`, 'GET');
|
|
286
258
|
}
|
|
287
259
|
/**
|
|
288
260
|
* https://developers.zoom.us/docs/api/meetings/#tag/meetings/GET/past_meetings/{meetingId}/participants
|
|
289
261
|
*/
|
|
290
262
|
function getPastMeetingParticipants(context) {
|
|
291
|
-
|
|
263
|
+
return (input) => context.fetchJson(`/past_meetings/${input.meetingId}/participants`, 'GET').then(mapToZoomPageResult('participants'));
|
|
292
264
|
}
|
|
293
265
|
function getPastMeetingParticipantsPageFactory(context) {
|
|
294
|
-
|
|
266
|
+
return zoomFetchPageFactory(getPastMeetingParticipants(context));
|
|
295
267
|
}
|
|
296
268
|
|
|
297
269
|
/**
|
|
@@ -305,66 +277,66 @@ function getPastMeetingParticipantsPageFactory(context) {
|
|
|
305
277
|
*/
|
|
306
278
|
var ZoomMeetingType;
|
|
307
279
|
(function (ZoomMeetingType) {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
280
|
+
ZoomMeetingType[ZoomMeetingType["INSTANT"] = 1] = "INSTANT";
|
|
281
|
+
ZoomMeetingType[ZoomMeetingType["SCHEDULED"] = 2] = "SCHEDULED";
|
|
282
|
+
ZoomMeetingType[ZoomMeetingType["RECURRING_NO_FIXED_TIME"] = 3] = "RECURRING_NO_FIXED_TIME";
|
|
283
|
+
ZoomMeetingType[ZoomMeetingType["PMI"] = 4] = "PMI";
|
|
284
|
+
ZoomMeetingType[ZoomMeetingType["RECURRING_FIXED_TIME"] = 8] = "RECURRING_FIXED_TIME";
|
|
285
|
+
ZoomMeetingType[ZoomMeetingType["SCREEN_SHARE_ONLY"] = 10] = "SCREEN_SHARE_ONLY";
|
|
314
286
|
})(ZoomMeetingType || (ZoomMeetingType = {}));
|
|
315
287
|
var ZoomRecurrenceType;
|
|
316
288
|
(function (ZoomRecurrenceType) {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
289
|
+
ZoomRecurrenceType[ZoomRecurrenceType["DAILY"] = 1] = "DAILY";
|
|
290
|
+
ZoomRecurrenceType[ZoomRecurrenceType["WEEKLY"] = 2] = "WEEKLY";
|
|
291
|
+
ZoomRecurrenceType[ZoomRecurrenceType["MONTHLY"] = 3] = "MONTHLY";
|
|
320
292
|
})(ZoomRecurrenceType || (ZoomRecurrenceType = {}));
|
|
321
293
|
var ZoomMonthlyWeek;
|
|
322
294
|
(function (ZoomMonthlyWeek) {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
295
|
+
ZoomMonthlyWeek[ZoomMonthlyWeek["LAST_WEEK"] = -1] = "LAST_WEEK";
|
|
296
|
+
ZoomMonthlyWeek[ZoomMonthlyWeek["FIRST_WEEK"] = 1] = "FIRST_WEEK";
|
|
297
|
+
ZoomMonthlyWeek[ZoomMonthlyWeek["SECOND_WEEK"] = 2] = "SECOND_WEEK";
|
|
298
|
+
ZoomMonthlyWeek[ZoomMonthlyWeek["THIRD_WEEK"] = 3] = "THIRD_WEEK";
|
|
299
|
+
ZoomMonthlyWeek[ZoomMonthlyWeek["FOURTH_WEEK"] = 4] = "FOURTH_WEEK";
|
|
328
300
|
})(ZoomMonthlyWeek || (ZoomMonthlyWeek = {}));
|
|
329
301
|
var ZoomMonthlyWeekDay;
|
|
330
302
|
(function (ZoomMonthlyWeekDay) {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
303
|
+
ZoomMonthlyWeekDay[ZoomMonthlyWeekDay["SUNDAY"] = 1] = "SUNDAY";
|
|
304
|
+
ZoomMonthlyWeekDay[ZoomMonthlyWeekDay["MONDAY"] = 2] = "MONDAY";
|
|
305
|
+
ZoomMonthlyWeekDay[ZoomMonthlyWeekDay["TUESDAY"] = 3] = "TUESDAY";
|
|
306
|
+
ZoomMonthlyWeekDay[ZoomMonthlyWeekDay["WEDNESDAY"] = 4] = "WEDNESDAY";
|
|
307
|
+
ZoomMonthlyWeekDay[ZoomMonthlyWeekDay["THURSDAY"] = 5] = "THURSDAY";
|
|
308
|
+
ZoomMonthlyWeekDay[ZoomMonthlyWeekDay["FRIDAY"] = 6] = "FRIDAY";
|
|
309
|
+
ZoomMonthlyWeekDay[ZoomMonthlyWeekDay["SATURDAY"] = 7] = "SATURDAY";
|
|
338
310
|
})(ZoomMonthlyWeekDay || (ZoomMonthlyWeekDay = {}));
|
|
339
311
|
var ZoomApprovalType;
|
|
340
312
|
(function (ZoomApprovalType) {
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
313
|
+
/**
|
|
314
|
+
* Automatically approve.
|
|
315
|
+
*/
|
|
316
|
+
ZoomApprovalType[ZoomApprovalType["AUTOMATICALLY_APPROVE"] = 0] = "AUTOMATICALLY_APPROVE";
|
|
317
|
+
/**
|
|
318
|
+
* Manually approve.
|
|
319
|
+
*/
|
|
320
|
+
ZoomApprovalType[ZoomApprovalType["MANUALLY_APPROVE"] = 1] = "MANUALLY_APPROVE";
|
|
321
|
+
/**
|
|
322
|
+
* No registration required.
|
|
323
|
+
*/
|
|
324
|
+
ZoomApprovalType[ZoomApprovalType["NO_REGISTRATION_REQUIRED"] = 2] = "NO_REGISTRATION_REQUIRED";
|
|
353
325
|
})(ZoomApprovalType || (ZoomApprovalType = {}));
|
|
354
326
|
var ZoomRegistrationType;
|
|
355
327
|
(function (ZoomRegistrationType) {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
328
|
+
/**
|
|
329
|
+
* Attendees register once and can attend any meeting occurrence.
|
|
330
|
+
*/
|
|
331
|
+
ZoomRegistrationType[ZoomRegistrationType["REGISTER_ONCE_ATTEND_ANY"] = 1] = "REGISTER_ONCE_ATTEND_ANY";
|
|
332
|
+
/**
|
|
333
|
+
* Attendees must register for each meeting occurrence.
|
|
334
|
+
*/
|
|
335
|
+
ZoomRegistrationType[ZoomRegistrationType["REGISTER_FOR_EACH_OCCURRENCE"] = 2] = "REGISTER_FOR_EACH_OCCURRENCE";
|
|
336
|
+
/**
|
|
337
|
+
* Attendees register once and can select one or more meeting occurrences to attend.
|
|
338
|
+
*/
|
|
339
|
+
ZoomRegistrationType[ZoomRegistrationType["REGISTER_ONCE_CHOOSE_OCCURRENCES"] = 3] = "REGISTER_ONCE_CHOOSE_OCCURRENCES";
|
|
368
340
|
})(ZoomRegistrationType || (ZoomRegistrationType = {}));
|
|
369
341
|
|
|
370
342
|
/**
|
|
@@ -374,7 +346,7 @@ var ZoomRegistrationType;
|
|
|
374
346
|
* @returns
|
|
375
347
|
*/
|
|
376
348
|
function getUser(context) {
|
|
377
|
-
|
|
349
|
+
return (input) => context.fetchJson(`/users/${input.userId}`, 'GET');
|
|
378
350
|
}
|
|
379
351
|
/**
|
|
380
352
|
* https://developers.zoom.us/docs/api/users/#tag/users/GET/users
|
|
@@ -383,40 +355,40 @@ function getUser(context) {
|
|
|
383
355
|
* @returns
|
|
384
356
|
*/
|
|
385
357
|
function listUsers(context) {
|
|
386
|
-
|
|
358
|
+
return (input) => context.fetchJson(`/users?${makeUrlSearchParams(input)}`, 'GET').then(mapToZoomPageResult('users'));
|
|
387
359
|
}
|
|
388
360
|
function listUsersPageFactory(context) {
|
|
389
|
-
|
|
361
|
+
return zoomFetchPageFactory(listUsers(context));
|
|
390
362
|
}
|
|
391
363
|
|
|
392
364
|
var ZoomUserType;
|
|
393
365
|
(function (ZoomUserType) {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
366
|
+
ZoomUserType[ZoomUserType["Basic"] = 1] = "Basic";
|
|
367
|
+
ZoomUserType[ZoomUserType["Licensed"] = 2] = "Licensed";
|
|
368
|
+
ZoomUserType[ZoomUserType["Unassigned"] = 4] = "Unassigned";
|
|
369
|
+
ZoomUserType[ZoomUserType["None"] = 99] = "None";
|
|
398
370
|
})(ZoomUserType || (ZoomUserType = {}));
|
|
399
371
|
|
|
400
372
|
// MARK: Parser
|
|
401
373
|
const logZoomErrorToConsole = logZoomServerErrorFunction('Zoom');
|
|
402
374
|
async function parseZoomApiError(responseError) {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
375
|
+
const data = await responseError.response.json().catch((x) => undefined);
|
|
376
|
+
let result;
|
|
377
|
+
if (data) {
|
|
378
|
+
result = parseZoomApiServerErrorResponseData(data, responseError);
|
|
379
|
+
}
|
|
380
|
+
return result;
|
|
409
381
|
}
|
|
410
382
|
function parseZoomApiServerErrorResponseData(zoomServerError, responseError) {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
383
|
+
let result;
|
|
384
|
+
if (zoomServerError) {
|
|
385
|
+
switch (zoomServerError.code) {
|
|
386
|
+
default:
|
|
387
|
+
result = parseZoomServerErrorData(zoomServerError, responseError);
|
|
388
|
+
break;
|
|
389
|
+
}
|
|
417
390
|
}
|
|
418
|
-
|
|
419
|
-
return result;
|
|
391
|
+
return result;
|
|
420
392
|
}
|
|
421
393
|
const handleZoomErrorFetch = handleZoomErrorFetchFactory(parseZoomApiError, logZoomErrorToConsole);
|
|
422
394
|
|
|
@@ -429,46 +401,46 @@ const ZOOM_ACCOUNTS_INVALID_GRANT_ERROR_CODE = 'invalid_grant';
|
|
|
429
401
|
* Thrown if the call to the Zoom API creating an access token using a refresh token fails.
|
|
430
402
|
*/
|
|
431
403
|
class ZoomOAuthAccessTokenError extends FetchRequestFactoryError {
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
404
|
+
errorCode;
|
|
405
|
+
constructor(errorCode) {
|
|
406
|
+
super(`ZoomOAuthAccessTokenError: ${errorCode}`);
|
|
407
|
+
this.errorCode = errorCode;
|
|
408
|
+
}
|
|
437
409
|
}
|
|
438
410
|
/**
|
|
439
411
|
* Thrown if a valid ZoomAccessToken cannot be retrieved successfully.
|
|
440
412
|
*/
|
|
441
413
|
class ZoomOAuthAuthFailureError extends FetchRequestFactoryError {
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
414
|
+
reason;
|
|
415
|
+
constructor(reason) {
|
|
416
|
+
super(`Failed to retrieve proper authentication for the API call. Reason: ${reason}`);
|
|
417
|
+
this.reason = reason;
|
|
418
|
+
}
|
|
447
419
|
}
|
|
448
420
|
const logZoomOAuthErrorToConsole = logZoomServerErrorFunction('ZoomOAuth');
|
|
449
421
|
async function parseZoomOAuthError(responseError) {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
422
|
+
const data = await responseError.response.json().catch((x) => undefined);
|
|
423
|
+
let result;
|
|
424
|
+
if (data) {
|
|
425
|
+
result = parseZoomOAuthServerErrorResponseData(data, responseError);
|
|
426
|
+
}
|
|
427
|
+
return result;
|
|
456
428
|
}
|
|
457
429
|
function parseZoomOAuthServerErrorResponseData(zoomServerError, responseError) {
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
430
|
+
let result;
|
|
431
|
+
if (zoomServerError) {
|
|
432
|
+
const potentialErrorStringCode = zoomServerError.error;
|
|
433
|
+
const errorCode = potentialErrorStringCode ?? zoomServerError.code;
|
|
434
|
+
switch (errorCode) {
|
|
435
|
+
case ZOOM_ACCOUNTS_INVALID_GRANT_ERROR_CODE:
|
|
436
|
+
result = new ZoomOAuthAccessTokenError(errorCode);
|
|
437
|
+
break;
|
|
438
|
+
default:
|
|
439
|
+
result = parseZoomServerErrorData(zoomServerError, responseError);
|
|
440
|
+
break;
|
|
441
|
+
}
|
|
469
442
|
}
|
|
470
|
-
|
|
471
|
-
return result;
|
|
443
|
+
return result;
|
|
472
444
|
}
|
|
473
445
|
const handleZoomOAuthErrorFetch = handleZoomErrorFetchFactory(parseZoomOAuthError, logZoomOAuthErrorToConsole);
|
|
474
446
|
|
|
@@ -476,76 +448,72 @@ const handleZoomOAuthErrorFetch = handleZoomErrorFetchFactory(parseZoomOAuthErro
|
|
|
476
448
|
* Generates a new ZoomAccessTokenStringFactory.
|
|
477
449
|
*/
|
|
478
450
|
function zoomAccessTokenStringFactory(zoomAccessTokenFactory) {
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
451
|
+
return async () => {
|
|
452
|
+
const token = await zoomAccessTokenFactory();
|
|
453
|
+
if (!token?.accessToken) {
|
|
454
|
+
throw new ZoomOAuthAuthFailureError();
|
|
455
|
+
}
|
|
456
|
+
return token.accessToken;
|
|
457
|
+
};
|
|
486
458
|
}
|
|
487
459
|
|
|
488
|
-
const DEFAULT_ZOOM_RATE_LIMITED_TOO_MANY_REQUETS_LOG_FUNCTION = headers => {
|
|
489
|
-
|
|
460
|
+
const DEFAULT_ZOOM_RATE_LIMITED_TOO_MANY_REQUETS_LOG_FUNCTION = (headers) => {
|
|
461
|
+
console.warn(`zoomRateLimitedFetchHandler(): Too many requests made. The limit is ${headers.limit} requests per reset period. RetryAt is set for ${headers.retryAfterAt}.`);
|
|
490
462
|
};
|
|
491
463
|
function zoomRateLimitedFetchHandler(config) {
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
464
|
+
const onTooManyRequests = config?.onTooManyRequests !== false ? (config?.onTooManyRequests ?? DEFAULT_ZOOM_RATE_LIMITED_TOO_MANY_REQUETS_LOG_FUNCTION) : undefined;
|
|
465
|
+
const defaultLimit = config?.maxRateLimit ?? DEFAULT_ZOOM_API_RATE_LIMIT;
|
|
466
|
+
const defaultResetPeriod = config?.resetPeriod ?? DEFAULT_ZOOM_API_RATE_LIMIT_RESET_PERIOD;
|
|
467
|
+
function configForLimit(limit, resetAt) {
|
|
468
|
+
return {
|
|
469
|
+
limit: defaultLimit,
|
|
470
|
+
startLimitAt: 2,
|
|
471
|
+
cooldownRate: 1,
|
|
472
|
+
exponentRate: 1.2,
|
|
473
|
+
maxWaitTime: MS_IN_SECOND * 5,
|
|
474
|
+
resetPeriod: defaultResetPeriod,
|
|
475
|
+
resetAt
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
const defaultConfig = configForLimit();
|
|
479
|
+
const rateLimiter = resetPeriodPromiseRateLimiter(defaultConfig);
|
|
480
|
+
return rateLimitedFetchHandler({
|
|
481
|
+
rateLimiter,
|
|
482
|
+
updateWithResponse: function (response, fetchResponseError) {
|
|
483
|
+
const hasLimitHeader = response.headers.has(ZOOM_RATE_LIMIT_REMAINING_HEADER);
|
|
484
|
+
let shouldRetry = false;
|
|
485
|
+
// let enabled = false; // rate limiter should not be turned off
|
|
486
|
+
if (hasLimitHeader) {
|
|
487
|
+
const headerDetails = zoomRateLimitHeaderDetails(response.headers);
|
|
488
|
+
if (headerDetails) {
|
|
489
|
+
const { type, limit, retryAfterAt, remaining } = headerDetails;
|
|
490
|
+
if (response.status === ZOOM_TOO_MANY_REQUESTS_HTTP_STATUS_CODE) {
|
|
491
|
+
// For simple query-per-second rate limits, just schedule a retry
|
|
492
|
+
if (type === 'QPS') {
|
|
493
|
+
shouldRetry = true;
|
|
494
|
+
try {
|
|
495
|
+
onTooManyRequests?.(headerDetails, response, fetchResponseError);
|
|
496
|
+
}
|
|
497
|
+
catch (e) { }
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
// NOTE: typically it seems like these headers are not available usually.
|
|
501
|
+
// There is a daily limit for message requests
|
|
502
|
+
if (limit != null && retryAfterAt != null && remaining != null) {
|
|
503
|
+
if (limit !== defaultLimit) {
|
|
504
|
+
const newConfig = configForLimit(limit, retryAfterAt);
|
|
505
|
+
rateLimiter.setConfig(newConfig, false);
|
|
506
|
+
}
|
|
507
|
+
rateLimiter.setRemainingLimit(remaining);
|
|
508
|
+
rateLimiter.setNextResetAt(retryAfterAt);
|
|
509
|
+
// enabled = true;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
538
512
|
}
|
|
539
|
-
rateLimiter.
|
|
540
|
-
|
|
541
|
-
// enabled = true;
|
|
542
|
-
}
|
|
513
|
+
// rateLimiter.setEnabled(enabled);
|
|
514
|
+
return shouldRetry;
|
|
543
515
|
}
|
|
544
|
-
|
|
545
|
-
// rateLimiter.setEnabled(enabled);
|
|
546
|
-
return shouldRetry;
|
|
547
|
-
}
|
|
548
|
-
});
|
|
516
|
+
});
|
|
549
517
|
}
|
|
550
518
|
|
|
551
519
|
/**
|
|
@@ -554,76 +522,69 @@ function zoomRateLimitedFetchHandler(config) {
|
|
|
554
522
|
const ZOOM_API_URL = 'https://api.zoom.us/v2';
|
|
555
523
|
|
|
556
524
|
function zoomFactory(factoryConfig) {
|
|
557
|
-
|
|
558
|
-
oauthContext
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
config,
|
|
620
|
-
zoomRateLimiter: fetchHandler._rateLimiter
|
|
621
|
-
};
|
|
622
|
-
const zoom = {
|
|
623
|
-
zoomServerContext: zoomContext
|
|
525
|
+
const { oauthContext } = factoryConfig;
|
|
526
|
+
const serverAccessTokenStringFactory = zoomAccessTokenStringFactory(oauthContext.loadAccessToken);
|
|
527
|
+
const fetchHandler = zoomRateLimitedFetchHandler(factoryConfig.rateLimiterConfig);
|
|
528
|
+
const { logZoomServerErrorFunction, fetchFactory = (input) => fetchApiFetchService.makeFetch({
|
|
529
|
+
baseUrl: ZOOM_API_URL,
|
|
530
|
+
baseRequest: async () => ({
|
|
531
|
+
headers: {
|
|
532
|
+
'Content-Type': 'application/json',
|
|
533
|
+
Authorization: `Bearer ${await input.zoomAccessTokenStringFactory()}`
|
|
534
|
+
}
|
|
535
|
+
}),
|
|
536
|
+
fetchHandler,
|
|
537
|
+
timeout: 20 * 1000, // 20 second timeout
|
|
538
|
+
requireOkResponse: true, // enforce ok response
|
|
539
|
+
useTimeout: true // use timeout
|
|
540
|
+
}) } = factoryConfig;
|
|
541
|
+
return (config) => {
|
|
542
|
+
const baseFetch = fetchFactory({
|
|
543
|
+
zoomAccessTokenStringFactory: serverAccessTokenStringFactory
|
|
544
|
+
});
|
|
545
|
+
const serverFetch = handleZoomErrorFetch(baseFetch, logZoomServerErrorFunction);
|
|
546
|
+
const serverFetchJson = fetchJsonFunction(serverFetch, {
|
|
547
|
+
handleFetchJsonParseErrorFunction: returnNullHandleFetchJsonParseErrorFunction
|
|
548
|
+
});
|
|
549
|
+
// MARK: Make User Context
|
|
550
|
+
const makeUserContext = (input) => {
|
|
551
|
+
const userAccessTokenFactory = oauthContext.makeUserAccessTokenFactory({
|
|
552
|
+
refreshToken: input.refreshToken,
|
|
553
|
+
userAccessTokenCache: input.accessTokenCache
|
|
554
|
+
});
|
|
555
|
+
const userAccessTokenStringFactory = zoomAccessTokenStringFactory(userAccessTokenFactory);
|
|
556
|
+
const userFetch = fetchFactory({
|
|
557
|
+
zoomAccessTokenStringFactory: userAccessTokenStringFactory
|
|
558
|
+
});
|
|
559
|
+
const userFetchJson = fetchJsonFunction(userFetch, {
|
|
560
|
+
handleFetchJsonParseErrorFunction: returnNullHandleFetchJsonParseErrorFunction
|
|
561
|
+
});
|
|
562
|
+
const result = {
|
|
563
|
+
zoomServerContext: zoomContext,
|
|
564
|
+
type: 'user',
|
|
565
|
+
fetch: userFetch,
|
|
566
|
+
fetchJson: userFetchJson,
|
|
567
|
+
userFetch,
|
|
568
|
+
userFetchJson,
|
|
569
|
+
zoomRateLimiter: fetchHandler._rateLimiter
|
|
570
|
+
};
|
|
571
|
+
return result;
|
|
572
|
+
};
|
|
573
|
+
const zoomContext = {
|
|
574
|
+
type: 'server',
|
|
575
|
+
fetch: serverFetch,
|
|
576
|
+
fetchJson: serverFetchJson,
|
|
577
|
+
serverFetch,
|
|
578
|
+
serverFetchJson,
|
|
579
|
+
makeUserContext,
|
|
580
|
+
config,
|
|
581
|
+
zoomRateLimiter: fetchHandler._rateLimiter
|
|
582
|
+
};
|
|
583
|
+
const zoom = {
|
|
584
|
+
zoomServerContext: zoomContext
|
|
585
|
+
};
|
|
586
|
+
return zoom;
|
|
624
587
|
};
|
|
625
|
-
return zoom;
|
|
626
|
-
};
|
|
627
588
|
}
|
|
628
589
|
|
|
629
590
|
/**
|
|
@@ -633,9 +594,9 @@ function zoomFactory(factoryConfig) {
|
|
|
633
594
|
* @returns
|
|
634
595
|
*/
|
|
635
596
|
function serverAccessToken(context) {
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
597
|
+
return (input) => {
|
|
598
|
+
return context.fetchJson(`/token?grant_type=account_credentials&account_id=${input?.accountId ?? context.config.accountId}`, zoomOAuthApiFetchJsonInput(context, input));
|
|
599
|
+
};
|
|
639
600
|
}
|
|
640
601
|
/**
|
|
641
602
|
* Retrieves a new AccessToken for a user using their refresh token.
|
|
@@ -644,27 +605,27 @@ function serverAccessToken(context) {
|
|
|
644
605
|
* @returns
|
|
645
606
|
*/
|
|
646
607
|
function userAccessToken(context) {
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
608
|
+
return (input) => {
|
|
609
|
+
const refreshToken = input.refreshToken;
|
|
610
|
+
return context.fetchJson(`/token?grant_type=refresh_token&refresh_token=${refreshToken}`, zoomOAuthApiFetchJsonInput(context, input));
|
|
611
|
+
};
|
|
651
612
|
}
|
|
652
613
|
function zoomOAuthApiFetchJsonInput(context, input) {
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
614
|
+
const clientId = input?.client?.clientId ?? context.config.clientId;
|
|
615
|
+
const clientSecret = input?.client?.clientSecret ?? context.config.clientSecret;
|
|
616
|
+
const fetchJsonInput = {
|
|
617
|
+
headers: {
|
|
618
|
+
Authorization: zoomOAuthServerBasicAuthorizationHeaderValue({
|
|
619
|
+
clientId,
|
|
620
|
+
clientSecret
|
|
621
|
+
})
|
|
622
|
+
},
|
|
623
|
+
method: 'POST'
|
|
624
|
+
};
|
|
625
|
+
return fetchJsonInput;
|
|
665
626
|
}
|
|
666
627
|
function zoomOAuthServerBasicAuthorizationHeaderValue(input) {
|
|
667
|
-
|
|
628
|
+
return `Basic ${Buffer.from(`${input.clientId}:${input.clientSecret}`).toString('base64')}`;
|
|
668
629
|
}
|
|
669
630
|
|
|
670
631
|
/**
|
|
@@ -673,85 +634,77 @@ function zoomOAuthServerBasicAuthorizationHeaderValue(input) {
|
|
|
673
634
|
const ZOOM_OAUTH_API_URL = 'https://zoom.us/oauth';
|
|
674
635
|
|
|
675
636
|
function zoomOAuthFactory(factoryConfig) {
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
637
|
+
const fetchHandler = zoomRateLimitedFetchHandler();
|
|
638
|
+
const { logZoomServerErrorFunction, fetchFactory = (_) => fetchApiFetchService.makeFetch({
|
|
639
|
+
baseUrl: ZOOM_OAUTH_API_URL,
|
|
640
|
+
baseRequest: {
|
|
641
|
+
headers: {
|
|
642
|
+
'Content-Type': 'application/json'
|
|
643
|
+
}
|
|
644
|
+
},
|
|
645
|
+
fetchHandler,
|
|
646
|
+
timeout: 20 * 1000, // 20 second timeout
|
|
647
|
+
requireOkResponse: true, // enforce ok response
|
|
648
|
+
useTimeout: true // use timeout
|
|
649
|
+
}) } = factoryConfig;
|
|
650
|
+
return (config) => {
|
|
651
|
+
if (!config.clientId) {
|
|
652
|
+
throw new Error('ZoomOAuthConfig missing clientId.');
|
|
684
653
|
}
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
return zoomOAuthZoomAccessTokenFactory({
|
|
739
|
-
tokenRefresher: userTokenRefresher,
|
|
740
|
-
accessTokenCache: input.userAccessTokenCache
|
|
741
|
-
});
|
|
742
|
-
};
|
|
743
|
-
const oauthContext = {
|
|
744
|
-
fetch,
|
|
745
|
-
fetchJson,
|
|
746
|
-
loadAccessToken,
|
|
747
|
-
makeUserAccessTokenFactory,
|
|
748
|
-
config
|
|
749
|
-
};
|
|
750
|
-
const zoomOAuth = {
|
|
751
|
-
oauthContext
|
|
654
|
+
else if (!config.clientSecret) {
|
|
655
|
+
throw new Error('ZoomOAuthConfig missing clientSecret.');
|
|
656
|
+
}
|
|
657
|
+
else if (!config.accountId) {
|
|
658
|
+
throw new Error('ZoomOAuthConfig missing accountId.');
|
|
659
|
+
}
|
|
660
|
+
const baseFetch = fetchFactory();
|
|
661
|
+
const fetch = handleZoomOAuthErrorFetch(baseFetch, logZoomServerErrorFunction);
|
|
662
|
+
const fetchJson = fetchJsonFunction(fetch, {
|
|
663
|
+
handleFetchJsonParseErrorFunction: returnNullHandleFetchJsonParseErrorFunction
|
|
664
|
+
});
|
|
665
|
+
function accessTokenFromTokenResponse(result) {
|
|
666
|
+
const createdAt = new Date().getTime();
|
|
667
|
+
const { access_token, api_url, scope, expires_in } = result;
|
|
668
|
+
const accessToken = {
|
|
669
|
+
accessToken: access_token,
|
|
670
|
+
apiDomain: api_url,
|
|
671
|
+
expiresIn: expires_in,
|
|
672
|
+
expiresAt: new Date(createdAt + expires_in * MS_IN_SECOND),
|
|
673
|
+
scope
|
|
674
|
+
};
|
|
675
|
+
return accessToken;
|
|
676
|
+
}
|
|
677
|
+
const tokenRefresher = async () => {
|
|
678
|
+
const accessToken = await serverAccessToken(oauthContext)();
|
|
679
|
+
return accessTokenFromTokenResponse(accessToken);
|
|
680
|
+
};
|
|
681
|
+
const loadAccessToken = zoomOAuthZoomAccessTokenFactory({
|
|
682
|
+
tokenRefresher,
|
|
683
|
+
accessTokenCache: config.accessTokenCache
|
|
684
|
+
});
|
|
685
|
+
// User Access Token
|
|
686
|
+
const makeUserAccessTokenFactory = (input) => {
|
|
687
|
+
const userTokenRefresher = async () => {
|
|
688
|
+
const accessToken = await userAccessToken(oauthContext)(input);
|
|
689
|
+
return accessTokenFromTokenResponse(accessToken);
|
|
690
|
+
};
|
|
691
|
+
return zoomOAuthZoomAccessTokenFactory({
|
|
692
|
+
tokenRefresher: userTokenRefresher,
|
|
693
|
+
accessTokenCache: input.userAccessTokenCache
|
|
694
|
+
});
|
|
695
|
+
};
|
|
696
|
+
const oauthContext = {
|
|
697
|
+
fetch,
|
|
698
|
+
fetchJson,
|
|
699
|
+
loadAccessToken,
|
|
700
|
+
makeUserAccessTokenFactory,
|
|
701
|
+
config
|
|
702
|
+
};
|
|
703
|
+
const zoomOAuth = {
|
|
704
|
+
oauthContext
|
|
705
|
+
};
|
|
706
|
+
return zoomOAuth;
|
|
752
707
|
};
|
|
753
|
-
return zoomOAuth;
|
|
754
|
-
};
|
|
755
708
|
}
|
|
756
709
|
/**
|
|
757
710
|
* Creates a ZoomOAuthZoomAccessTokenFactoryConfig
|
|
@@ -760,49 +713,47 @@ function zoomOAuthFactory(factoryConfig) {
|
|
|
760
713
|
* @returns
|
|
761
714
|
*/
|
|
762
715
|
function zoomOAuthZoomAccessTokenFactory(config) {
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
const cachedToken = await accessTokenCache?.loadCachedToken();
|
|
777
|
-
if (cachedToken) {
|
|
778
|
-
currentToken = cachedToken;
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
// check expiration
|
|
782
|
-
if (currentToken != null) {
|
|
783
|
-
const isExpired = new Date().getTime() + tokenExpirationBuffer >= currentToken.expiresAt.getTime();
|
|
784
|
-
if (isExpired) {
|
|
785
|
-
currentToken = null;
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
// load from source
|
|
789
|
-
if (!currentToken) {
|
|
790
|
-
try {
|
|
791
|
-
currentToken = await tokenRefresher();
|
|
792
|
-
} catch (e) {
|
|
793
|
-
console.error(`zoomOAuthZoomAccessTokenFactory(): Failed retrieving new token from tokenRefresher: `, e);
|
|
794
|
-
throw new ZoomOAuthAuthFailureError('Token Refresh Failed');
|
|
795
|
-
}
|
|
796
|
-
if (currentToken) {
|
|
797
|
-
try {
|
|
798
|
-
await accessTokenCache?.updateCachedToken(currentToken);
|
|
799
|
-
} catch (e) {
|
|
800
|
-
// do nothing
|
|
716
|
+
const { tokenRefresher, accessTokenCache, tokenExpirationBuffer: inputTokenExpirationBuffer } = config;
|
|
717
|
+
const tokenExpirationBuffer = inputTokenExpirationBuffer ?? MS_IN_MINUTE;
|
|
718
|
+
/**
|
|
719
|
+
* Caches the token internally here until it expires.
|
|
720
|
+
*/
|
|
721
|
+
let currentToken = null;
|
|
722
|
+
return async () => {
|
|
723
|
+
// load from cache
|
|
724
|
+
if (!currentToken) {
|
|
725
|
+
const cachedToken = await accessTokenCache?.loadCachedToken();
|
|
726
|
+
if (cachedToken) {
|
|
727
|
+
currentToken = cachedToken;
|
|
728
|
+
}
|
|
801
729
|
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
730
|
+
// check expiration
|
|
731
|
+
if (currentToken != null) {
|
|
732
|
+
const isExpired = new Date().getTime() + tokenExpirationBuffer >= currentToken.expiresAt.getTime();
|
|
733
|
+
if (isExpired) {
|
|
734
|
+
currentToken = null;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
// load from source
|
|
738
|
+
if (!currentToken) {
|
|
739
|
+
try {
|
|
740
|
+
currentToken = await tokenRefresher();
|
|
741
|
+
}
|
|
742
|
+
catch (e) {
|
|
743
|
+
console.error(`zoomOAuthZoomAccessTokenFactory(): Failed retrieving new token from tokenRefresher: `, e);
|
|
744
|
+
throw new ZoomOAuthAuthFailureError('Token Refresh Failed');
|
|
745
|
+
}
|
|
746
|
+
if (currentToken) {
|
|
747
|
+
try {
|
|
748
|
+
await accessTokenCache?.updateCachedToken(currentToken);
|
|
749
|
+
}
|
|
750
|
+
catch (e) {
|
|
751
|
+
// do nothing
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
return currentToken;
|
|
756
|
+
};
|
|
806
757
|
}
|
|
807
758
|
|
|
808
759
|
export { DEFAULT_ZOOM_API_RATE_LIMIT, DEFAULT_ZOOM_API_RATE_LIMIT_RESET_PERIOD, DEFAULT_ZOOM_RATE_LIMITED_TOO_MANY_REQUETS_LOG_FUNCTION, DELETE_MEETING_DOES_NOT_EXIST_ERROR_CODE, ZOOM_ACCOUNTS_INVALID_GRANT_ERROR_CODE, ZOOM_API_URL, ZOOM_OAUTH_API_URL, ZOOM_RATE_LIMIT_CATEGORY_HEADER, ZOOM_RATE_LIMIT_LIMIT_HEADER, ZOOM_RATE_LIMIT_REMAINING_HEADER, ZOOM_RATE_LIMIT_RETRY_AFTER_HEADER, ZOOM_RATE_LIMIT_TYPE_HEADER, ZOOM_SUCCESS_CODE, ZOOM_TOO_MANY_REQUESTS_ERROR_CODE, ZOOM_TOO_MANY_REQUESTS_HTTP_STATUS_CODE, ZoomApprovalType, ZoomMeetingType, ZoomMonthlyWeek, ZoomMonthlyWeekDay, ZoomOAuthAccessTokenError, ZoomOAuthAuthFailureError, ZoomRecurrenceType, ZoomRegistrationType, ZoomServerError, ZoomServerFetchResponseError, ZoomTooManyRequestsError, ZoomUserType, createMeetingForUser, deleteMeeting, getMeeting, getPastMeeting, getPastMeetingParticipants, getPastMeetingParticipantsPageFactory, getUser, handleZoomErrorFetch, handleZoomErrorFetchFactory, handleZoomOAuthErrorFetch, listMeetingsForUser, listMeetingsForUserPageFactory, listUsers, listUsersPageFactory, logZoomErrorToConsole, logZoomOAuthErrorToConsole, logZoomServerErrorFunction, mapToZoomPageResult, omitSilenceZoomErrorKeys, parseZoomApiError, parseZoomApiServerErrorResponseData, parseZoomOAuthError, parseZoomOAuthServerErrorResponseData, parseZoomServerErrorData, serverAccessToken, silenceZoomErrorWithCodesFunction, updateMeeting, userAccessToken, zoomAccessTokenStringFactory, zoomFactory, zoomFetchPageFactory, zoomOAuthApiFetchJsonInput, zoomOAuthFactory, zoomOAuthServerBasicAuthorizationHeaderValue, zoomOAuthZoomAccessTokenFactory, zoomRateLimitHeaderDetails, zoomRateLimitedFetchHandler };
|