@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/nestjs/index.cjs.js
CHANGED
|
@@ -50,58 +50,59 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
50
50
|
* Configuration for ZoomService
|
|
51
51
|
*/
|
|
52
52
|
class ZoomOAuthServiceConfig {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
53
|
+
zoomOAuth;
|
|
54
|
+
factoryConfig;
|
|
55
|
+
static assertValidConfig(config) {
|
|
56
|
+
const { zoomOAuth } = config;
|
|
57
|
+
if (!zoomOAuth) {
|
|
58
|
+
throw new Error('ZoomOAuthServiceConfig.zoomOAuth is required');
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
if (!zoomOAuth.accountId) {
|
|
62
|
+
throw new Error('ZoomOAuthServiceConfig.zoomOAuth.accountId is required');
|
|
63
|
+
}
|
|
64
|
+
else if (!zoomOAuth.clientSecret) {
|
|
65
|
+
throw new Error('ZoomOAuthServiceConfig.zoomOAuth.clientSecret is required');
|
|
66
|
+
}
|
|
67
|
+
else if (!zoomOAuth.clientId) {
|
|
68
|
+
throw new Error('ZoomOAuthServiceConfig.zoomOAuth.clientId is required');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
71
72
|
}
|
|
72
73
|
function readZoomOAuthServiceConfigFromConfigService(configService, prefix) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
};
|
|
91
|
-
ZoomOAuthServiceConfig.assertValidConfig(config);
|
|
92
|
-
return config;
|
|
74
|
+
const prefixString = util.characterPrefixSuffixInstance({ suffix: '_', suffixEmptyString: false }).prefixSuffixString(prefix ?? '');
|
|
75
|
+
const accountIdKey = `${prefixString}ZOOM_ACCOUNT_ID`;
|
|
76
|
+
const clientIdKey = `${prefixString}ZOOM_CLIENT_ID`;
|
|
77
|
+
const clientSecretKey = `${prefixString}ZOOM_CLIENT_SECRET`;
|
|
78
|
+
const accountId = configService.getOrThrow(accountIdKey);
|
|
79
|
+
const clientId = configService.getOrThrow(clientIdKey);
|
|
80
|
+
const clientSecret = configService.getOrThrow(clientSecretKey);
|
|
81
|
+
const config = {
|
|
82
|
+
zoomOAuth: {
|
|
83
|
+
authEntityType: 'account',
|
|
84
|
+
accountId,
|
|
85
|
+
clientId,
|
|
86
|
+
clientSecret
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
ZoomOAuthServiceConfig.assertValidConfig(config);
|
|
90
|
+
return config;
|
|
93
91
|
}
|
|
94
92
|
|
|
95
93
|
/**
|
|
96
94
|
* Service used for retrieving ZoomAccessTokenCache for Zoom services.
|
|
97
95
|
*/
|
|
98
|
-
exports.ZoomOAuthAccessTokenCacheService = class ZoomOAuthAccessTokenCacheService {
|
|
99
|
-
|
|
96
|
+
exports.ZoomOAuthAccessTokenCacheService = class ZoomOAuthAccessTokenCacheService {
|
|
97
|
+
};
|
|
98
|
+
exports.ZoomOAuthAccessTokenCacheService = __decorate([
|
|
99
|
+
common.Injectable()
|
|
100
|
+
], exports.ZoomOAuthAccessTokenCacheService);
|
|
100
101
|
function logMergeZoomOAuthAccessTokenCacheServiceErrorFunction(failedUpdates) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
console.warn(`mergeZoomOAuthAccessTokenCacheServices(): failed updating ${failedUpdates.length} caches.`);
|
|
103
|
+
failedUpdates.forEach(([x, e], i) => {
|
|
104
|
+
console.warn(`Cache update failure ${i + 1}: - ${e}`);
|
|
105
|
+
});
|
|
105
106
|
}
|
|
106
107
|
/**
|
|
107
108
|
* Merges the input services in order to use some as a backup source.
|
|
@@ -113,54 +114,62 @@ function logMergeZoomOAuthAccessTokenCacheServiceErrorFunction(failedUpdates) {
|
|
|
113
114
|
* @param servicesToMerge Must include atleast one service. Empty arrays will throw an error.
|
|
114
115
|
*/
|
|
115
116
|
function mergeZoomOAuthAccessTokenCacheServices(inputServicesToMerge, logError) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
return loadCachedTokenFromFirstService();
|
|
136
|
-
},
|
|
137
|
-
updateCachedToken: async function (accessToken) {
|
|
138
|
-
return Promise.allSettled(accessCachesForServices.map(x => x.updateCachedToken(accessToken).then(() => null).catch(e => {
|
|
139
|
-
return [x, e];
|
|
140
|
-
}))).then(x => {
|
|
141
|
-
// only find the failures if we're logging
|
|
142
|
-
if (logErrorFunction != null) {
|
|
143
|
-
const failedUpdates = util.filterMaybeArrayValues(x.map(y => y.value));
|
|
144
|
-
if (failedUpdates.length) {
|
|
145
|
-
logErrorFunction(failedUpdates);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
117
|
+
const allServices = [...inputServicesToMerge];
|
|
118
|
+
const logErrorFunction = typeof logError === 'function' ? logError : logError !== false ? logMergeZoomOAuthAccessTokenCacheServiceErrorFunction : undefined;
|
|
119
|
+
if (allServices.length === 0) {
|
|
120
|
+
throw new Error('mergeZoomOAuthAccessTokenCacheServices() input cannot be empty.');
|
|
121
|
+
}
|
|
122
|
+
const loadZoomAccessTokenCache = (accessCachesForServices) => {
|
|
123
|
+
const loadCachedTokenFromFirstService = util.tryWithPromiseFactoriesFunction({
|
|
124
|
+
promiseFactories: accessCachesForServices.map((x) => () => x
|
|
125
|
+
.loadCachedToken()
|
|
126
|
+
.catch(() => null)
|
|
127
|
+
.then((x) => {
|
|
128
|
+
let result = undefined;
|
|
129
|
+
if (x && !util.isPast(x.expiresAt)) {
|
|
130
|
+
result = x; // only return from cache if it is not expired
|
|
131
|
+
}
|
|
132
|
+
return result;
|
|
133
|
+
})),
|
|
134
|
+
successOnMaybe: false,
|
|
135
|
+
throwErrors: false
|
|
148
136
|
});
|
|
149
|
-
|
|
137
|
+
const cacheForService = {
|
|
138
|
+
loadCachedToken: function () {
|
|
139
|
+
return loadCachedTokenFromFirstService();
|
|
140
|
+
},
|
|
141
|
+
updateCachedToken: async function (accessToken) {
|
|
142
|
+
return Promise.allSettled(accessCachesForServices.map((x) => x
|
|
143
|
+
.updateCachedToken(accessToken)
|
|
144
|
+
.then(() => null)
|
|
145
|
+
.catch((e) => {
|
|
146
|
+
return [x, e];
|
|
147
|
+
}))).then((x) => {
|
|
148
|
+
// only find the failures if we're logging
|
|
149
|
+
if (logErrorFunction != null) {
|
|
150
|
+
const failedUpdates = util.filterMaybeArrayValues(x.map((y) => y.value));
|
|
151
|
+
if (failedUpdates.length) {
|
|
152
|
+
logErrorFunction(failedUpdates);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
return cacheForService;
|
|
159
|
+
};
|
|
160
|
+
const allServiceAccessTokenCaches = allServices.map((x) => x.loadZoomAccessTokenCache());
|
|
161
|
+
const allServicesWithCacheForRefreshToken = allServices.filter((x) => x.cacheForRefreshToken != null);
|
|
162
|
+
const cacheForRefreshToken = allServiceAccessTokenCaches.length > 0
|
|
163
|
+
? (refreshToken) => {
|
|
164
|
+
const allCaches = allServicesWithCacheForRefreshToken.map((x) => x.cacheForRefreshToken(refreshToken));
|
|
165
|
+
return loadZoomAccessTokenCache(allCaches);
|
|
166
|
+
}
|
|
167
|
+
: undefined;
|
|
168
|
+
const service = {
|
|
169
|
+
loadZoomAccessTokenCache: () => loadZoomAccessTokenCache(allServiceAccessTokenCaches),
|
|
170
|
+
cacheForRefreshToken
|
|
150
171
|
};
|
|
151
|
-
return
|
|
152
|
-
};
|
|
153
|
-
const allServiceAccessTokenCaches = allServices.map(x => x.loadZoomAccessTokenCache());
|
|
154
|
-
const allServicesWithCacheForRefreshToken = allServices.filter(x => x.cacheForRefreshToken != null);
|
|
155
|
-
const cacheForRefreshToken = allServiceAccessTokenCaches.length > 0 ? refreshToken => {
|
|
156
|
-
const allCaches = allServicesWithCacheForRefreshToken.map(x => x.cacheForRefreshToken(refreshToken));
|
|
157
|
-
return loadZoomAccessTokenCache(allCaches);
|
|
158
|
-
} : undefined;
|
|
159
|
-
const service = {
|
|
160
|
-
loadZoomAccessTokenCache: () => loadZoomAccessTokenCache(allServiceAccessTokenCaches),
|
|
161
|
-
cacheForRefreshToken
|
|
162
|
-
};
|
|
163
|
-
return service;
|
|
172
|
+
return service;
|
|
164
173
|
}
|
|
165
174
|
// MARK: Memory Access Token Cache
|
|
166
175
|
/**
|
|
@@ -169,32 +178,28 @@ function mergeZoomOAuthAccessTokenCacheServices(inputServicesToMerge, logError)
|
|
|
169
178
|
* @returns
|
|
170
179
|
*/
|
|
171
180
|
function memoryZoomOAuthAccessTokenCacheService(existingToken, logAccessToConsole) {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
181
|
+
let token = existingToken;
|
|
182
|
+
function loadZoomAccessTokenCache() {
|
|
183
|
+
const accessTokenCache = {
|
|
184
|
+
loadCachedToken: async function () {
|
|
185
|
+
if (logAccessToConsole) {
|
|
186
|
+
console.log('retrieving access token from memory: ', { token });
|
|
187
|
+
}
|
|
188
|
+
return token;
|
|
189
|
+
},
|
|
190
|
+
updateCachedToken: async function (accessToken) {
|
|
191
|
+
token = accessToken;
|
|
192
|
+
if (logAccessToConsole) {
|
|
193
|
+
console.log('updating access token in memory: ', { accessToken });
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
return accessTokenCache;
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
loadZoomAccessTokenCache,
|
|
201
|
+
cacheForRefreshToken: () => loadZoomAccessTokenCache()
|
|
191
202
|
};
|
|
192
|
-
return accessTokenCache;
|
|
193
|
-
}
|
|
194
|
-
return {
|
|
195
|
-
loadZoomAccessTokenCache,
|
|
196
|
-
cacheForRefreshToken: () => loadZoomAccessTokenCache()
|
|
197
|
-
};
|
|
198
203
|
}
|
|
199
204
|
// MARK: File System Access Token Cache
|
|
200
205
|
const DEFAULT_FILE_ZOOM_ACCOUNTS_ACCESS_TOKEN_CACHE_SERVICE_PATH = '.tmp/zoom-access-tokens.json';
|
|
@@ -206,128 +211,137 @@ const DEFAULT_FILE_ZOOM_ACCOUNTS_ACCESS_TOKEN_CACHE_SERVICE_PATH = '.tmp/zoom-ac
|
|
|
206
211
|
* @returns
|
|
207
212
|
*/
|
|
208
213
|
function fileZoomOAuthAccessTokenCacheService(filename = DEFAULT_FILE_ZOOM_ACCOUNTS_ACCESS_TOKEN_CACHE_SERVICE_PATH, useMemoryCache = true) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
} else {
|
|
215
|
-
token = loadedToken;
|
|
216
|
-
}
|
|
217
|
-
return token;
|
|
218
|
-
}
|
|
219
|
-
function readTokenFile() {
|
|
220
|
-
return new Promise(resolve => {
|
|
221
|
-
fs.mkdirSync(path.dirname(filename), {
|
|
222
|
-
recursive: true
|
|
223
|
-
}); // make the directory first
|
|
224
|
-
fs.readFile(filename, {}, (x, data) => {
|
|
225
|
-
let result = undefined;
|
|
226
|
-
if (!x) {
|
|
227
|
-
try {
|
|
228
|
-
result = JSON.parse(data.toString());
|
|
229
|
-
if (result?.token) {
|
|
230
|
-
result.token.expiresAt = new Date(result.token.expiresAt);
|
|
231
|
-
}
|
|
232
|
-
} catch (e) {
|
|
233
|
-
console.error('Failed reading token file: ', e);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
resolve(result);
|
|
237
|
-
});
|
|
238
|
-
}).then(x => {
|
|
239
|
-
// update loaded tokens
|
|
240
|
-
if (useMemoryCache) {
|
|
241
|
-
loadedToken = {
|
|
242
|
-
...loadedToken,
|
|
243
|
-
...x
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
return x;
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
async function writeTokenFile(tokens) {
|
|
250
|
-
return new Promise((resolve, reject) => {
|
|
251
|
-
fs.writeFile(filename, JSON.stringify(tokens), {}, x => {
|
|
252
|
-
if (!x) {
|
|
253
|
-
resolve();
|
|
254
|
-
} else {
|
|
255
|
-
reject(x);
|
|
214
|
+
let loadedToken = null;
|
|
215
|
+
async function loadTokenFile() {
|
|
216
|
+
let token = undefined;
|
|
217
|
+
if (!loadedToken) {
|
|
218
|
+
token = (await readTokenFile()) ?? {};
|
|
256
219
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
}
|
|
260
|
-
async function deleteTokenFile() {
|
|
261
|
-
return new Promise((resolve, reject) => {
|
|
262
|
-
fs.rm(filename, x => {
|
|
263
|
-
if (!x) {
|
|
264
|
-
resolve();
|
|
265
|
-
} else {
|
|
266
|
-
reject(x);
|
|
220
|
+
else {
|
|
221
|
+
token = loadedToken;
|
|
267
222
|
}
|
|
268
|
-
});
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
function loadZoomAccessTokenCache() {
|
|
272
|
-
const accessTokenCache = {
|
|
273
|
-
loadCachedToken: async function () {
|
|
274
|
-
const tokens = await loadTokenFile();
|
|
275
|
-
const token = tokens.token;
|
|
276
|
-
// console.log('retrieving access token from file: ', { token });
|
|
277
223
|
return token;
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
224
|
+
}
|
|
225
|
+
function readTokenFile() {
|
|
226
|
+
return new Promise((resolve) => {
|
|
227
|
+
fs.mkdirSync(path.dirname(filename), { recursive: true }); // make the directory first
|
|
228
|
+
fs.readFile(filename, {}, (x, data) => {
|
|
229
|
+
let result = undefined;
|
|
230
|
+
if (!x) {
|
|
231
|
+
try {
|
|
232
|
+
result = JSON.parse(data.toString());
|
|
233
|
+
if (result?.token) {
|
|
234
|
+
result.token.expiresAt = new Date(result.token.expiresAt);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
catch (e) {
|
|
238
|
+
console.error('Failed reading token file: ', e);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
resolve(result);
|
|
242
|
+
});
|
|
243
|
+
}).then((x) => {
|
|
244
|
+
// update loaded tokens
|
|
245
|
+
if (useMemoryCache) {
|
|
246
|
+
loadedToken = {
|
|
247
|
+
...loadedToken,
|
|
248
|
+
...x
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
return x;
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
async function writeTokenFile(tokens) {
|
|
255
|
+
return new Promise((resolve, reject) => {
|
|
256
|
+
fs.writeFile(filename, JSON.stringify(tokens), {}, (x) => {
|
|
257
|
+
if (!x) {
|
|
258
|
+
resolve();
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
reject(x);
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
async function deleteTokenFile() {
|
|
267
|
+
return new Promise((resolve, reject) => {
|
|
268
|
+
fs.rm(filename, (x) => {
|
|
269
|
+
if (!x) {
|
|
270
|
+
resolve();
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
reject(x);
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
function loadZoomAccessTokenCache() {
|
|
279
|
+
const accessTokenCache = {
|
|
280
|
+
loadCachedToken: async function () {
|
|
281
|
+
const tokens = await loadTokenFile();
|
|
282
|
+
const token = tokens.token;
|
|
283
|
+
// console.log('retrieving access token from file: ', { token });
|
|
284
|
+
return token;
|
|
285
|
+
},
|
|
286
|
+
updateCachedToken: async function (accessToken) {
|
|
287
|
+
const tokenFile = await loadTokenFile();
|
|
288
|
+
if (tokenFile) {
|
|
289
|
+
tokenFile.token = accessToken;
|
|
290
|
+
}
|
|
291
|
+
// console.log('updating access token in file: ', { accessToken });
|
|
292
|
+
try {
|
|
293
|
+
await writeTokenFile(tokenFile);
|
|
294
|
+
}
|
|
295
|
+
catch (e) {
|
|
296
|
+
console.error('Failed updating access token in file: ', e);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
return accessTokenCache;
|
|
301
|
+
}
|
|
302
|
+
return {
|
|
303
|
+
loadZoomAccessTokenCache,
|
|
304
|
+
readTokenFile,
|
|
305
|
+
writeTokenFile,
|
|
306
|
+
deleteTokenFile
|
|
291
307
|
};
|
|
292
|
-
return accessTokenCache;
|
|
293
|
-
}
|
|
294
|
-
return {
|
|
295
|
-
loadZoomAccessTokenCache,
|
|
296
|
-
readTokenFile,
|
|
297
|
-
writeTokenFile,
|
|
298
|
-
deleteTokenFile
|
|
299
|
-
};
|
|
300
308
|
}
|
|
301
309
|
|
|
302
310
|
exports.ZoomOAuthApi = class ZoomOAuthApi {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
311
|
+
config;
|
|
312
|
+
cacheService;
|
|
313
|
+
zoomOAuth;
|
|
314
|
+
get oauthContext() {
|
|
315
|
+
return this.zoomOAuth.oauthContext;
|
|
316
|
+
}
|
|
317
|
+
constructor(config, cacheService) {
|
|
318
|
+
this.config = config;
|
|
319
|
+
this.cacheService = cacheService;
|
|
320
|
+
const accessTokenCache = config.zoomOAuth.accessTokenCache ? config.zoomOAuth.accessTokenCache : cacheService.loadZoomAccessTokenCache();
|
|
321
|
+
this.zoomOAuth = zoom.zoomOAuthFactory(config.factoryConfig ?? {})({
|
|
322
|
+
accessTokenCache,
|
|
323
|
+
...config.zoomOAuth
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
// MARK: Accessors
|
|
327
|
+
get serverAccessToken() {
|
|
328
|
+
return zoom.serverAccessToken(this.oauthContext);
|
|
329
|
+
}
|
|
330
|
+
get userAccessToken() {
|
|
331
|
+
return zoom.userAccessToken(this.oauthContext);
|
|
332
|
+
}
|
|
325
333
|
};
|
|
326
|
-
exports.ZoomOAuthApi = __decorate([
|
|
334
|
+
exports.ZoomOAuthApi = __decorate([
|
|
335
|
+
common.Injectable(),
|
|
336
|
+
__param(0, common.Inject(ZoomOAuthServiceConfig)),
|
|
337
|
+
__param(1, common.Inject(exports.ZoomOAuthAccessTokenCacheService)),
|
|
338
|
+
__metadata("design:paramtypes", [ZoomOAuthServiceConfig,
|
|
339
|
+
exports.ZoomOAuthAccessTokenCacheService])
|
|
340
|
+
], exports.ZoomOAuthApi);
|
|
327
341
|
|
|
328
342
|
function zoomOAuthServiceConfigFactory(configService) {
|
|
329
|
-
|
|
330
|
-
|
|
343
|
+
const config = readZoomOAuthServiceConfigFromConfigService(configService);
|
|
344
|
+
return config;
|
|
331
345
|
}
|
|
332
346
|
/**
|
|
333
347
|
* Convenience function used to generate ModuleMetadata for an app's ZoomOAuthModule.
|
|
@@ -337,22 +351,21 @@ function zoomOAuthServiceConfigFactory(configService) {
|
|
|
337
351
|
* @returns
|
|
338
352
|
*/
|
|
339
353
|
function appZoomOAuthModuleMetadata(config$1) {
|
|
340
|
-
|
|
341
|
-
dependencyModule
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
}
|
|
355
|
-
};
|
|
354
|
+
const { dependencyModule, imports, exports: exports$1, providers } = config$1;
|
|
355
|
+
const dependencyModuleImport = dependencyModule ? [dependencyModule] : [];
|
|
356
|
+
return {
|
|
357
|
+
imports: [config.ConfigModule, ...dependencyModuleImport, ...(imports ?? [])],
|
|
358
|
+
exports: [exports.ZoomOAuthApi, ...(exports$1 ?? [])],
|
|
359
|
+
providers: [
|
|
360
|
+
{
|
|
361
|
+
provide: ZoomOAuthServiceConfig,
|
|
362
|
+
inject: [config.ConfigService],
|
|
363
|
+
useFactory: config$1.zoomOAuthServiceConfigFactory ?? zoomOAuthServiceConfigFactory
|
|
364
|
+
},
|
|
365
|
+
exports.ZoomOAuthApi,
|
|
366
|
+
...(providers ?? [])
|
|
367
|
+
]
|
|
368
|
+
};
|
|
356
369
|
}
|
|
357
370
|
|
|
358
371
|
const ZOOM_SECRET_TOKEN_ENV_VAR = 'ZOOM_SECRET_TOKEN';
|
|
@@ -360,12 +373,12 @@ const ZOOM_SECRET_TOKEN_ENV_VAR = 'ZOOM_SECRET_TOKEN';
|
|
|
360
373
|
* Configuration for ZoomService
|
|
361
374
|
*/
|
|
362
375
|
class ZoomWebhookServiceConfig {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
376
|
+
webhookConfig;
|
|
377
|
+
static assertValidConfig(config) {
|
|
378
|
+
if (!config.webhookConfig.zoomSecretToken) {
|
|
379
|
+
throw new Error('No zoom secret token specified.');
|
|
380
|
+
}
|
|
367
381
|
}
|
|
368
|
-
}
|
|
369
382
|
}
|
|
370
383
|
|
|
371
384
|
// MARK: Meeting Alert
|
|
@@ -390,29 +403,29 @@ const ZOOM_WEBHOOK_MEETING_PERMANENTLY_DELETED_EVENT_TYPE = 'meeting.permanently
|
|
|
390
403
|
* @returns
|
|
391
404
|
*/
|
|
392
405
|
function zoomWebhookEvent(event) {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
406
|
+
return {
|
|
407
|
+
event: event.event,
|
|
408
|
+
event_ts: event.event_ts,
|
|
409
|
+
payload: event.payload
|
|
410
|
+
};
|
|
398
411
|
}
|
|
399
|
-
const zoomEventHandlerFactory = util.handlerFactory(x => x.event);
|
|
412
|
+
const zoomEventHandlerFactory = util.handlerFactory((x) => x.event);
|
|
400
413
|
const zoomEventHandlerConfigurerFactory = util.handlerConfigurerFactory({
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
414
|
+
configurerForAccessor: (accessor) => {
|
|
415
|
+
// eslint-disable-next-line
|
|
416
|
+
const fnWithKey = util.handlerMappedSetFunctionFactory(accessor, zoomWebhookEvent);
|
|
417
|
+
const configurer = {
|
|
418
|
+
...accessor,
|
|
419
|
+
// Meetings
|
|
420
|
+
handleMeetingCreated: fnWithKey(ZOOM_WEBHOOK_MEETING_CREATED_EVENT_TYPE),
|
|
421
|
+
handleMeetingUpdated: fnWithKey(ZOOM_WEBHOOK_MEETING_UPDATED_EVENT_TYPE),
|
|
422
|
+
handleMeetingDeleted: fnWithKey(ZOOM_WEBHOOK_MEETING_DELETED_EVENT_TYPE),
|
|
423
|
+
handleMeetingStarted: fnWithKey(ZOOM_WEBHOOK_MEETING_STARTED_EVENT_TYPE),
|
|
424
|
+
handleMeetingEnded: fnWithKey(ZOOM_WEBHOOK_MEETING_ENDED_EVENT_TYPE),
|
|
425
|
+
handleMeetingPermanentlyDeleted: fnWithKey(ZOOM_WEBHOOK_MEETING_PERMANENTLY_DELETED_EVENT_TYPE)
|
|
426
|
+
};
|
|
427
|
+
return configurer;
|
|
428
|
+
}
|
|
416
429
|
});
|
|
417
430
|
|
|
418
431
|
/**
|
|
@@ -424,18 +437,18 @@ const zoomEventHandlerConfigurerFactory = util.handlerConfigurerFactory({
|
|
|
424
437
|
* @returns A function that verifies a Zoom webhook event.
|
|
425
438
|
*/
|
|
426
439
|
function zoomWebhookEventVerifier(zoomSecretToken) {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
440
|
+
return (request, rawBody) => {
|
|
441
|
+
const requestBodyString = String(request.body);
|
|
442
|
+
const message = `v0:${request.headers['x-zm-request-timestamp']}:${requestBodyString}`;
|
|
443
|
+
const hashForVerify = crypto.createHmac('sha256', zoomSecretToken).update(message).digest('hex');
|
|
444
|
+
const signature = `v0=${hashForVerify}`;
|
|
445
|
+
const valid = request.headers['x-zm-signature'] === signature;
|
|
446
|
+
const result = {
|
|
447
|
+
valid,
|
|
448
|
+
event: JSON.parse(requestBodyString)
|
|
449
|
+
};
|
|
450
|
+
return result;
|
|
436
451
|
};
|
|
437
|
-
return result;
|
|
438
|
-
};
|
|
439
452
|
}
|
|
440
453
|
|
|
441
454
|
const ZOOM_WEBHOOK_URL_VALIDATION_EVENT_TYPE = 'endpoint.url_validation';
|
|
@@ -447,193 +460,216 @@ const ZOOM_WEBHOOK_URL_VALIDATION_EVENT_TYPE = 'endpoint.url_validation';
|
|
|
447
460
|
* @returns A ZoomWebhookEventValidationFunction.
|
|
448
461
|
*/
|
|
449
462
|
function zoomWebhookEventValidationFunction(zoomSecretToken) {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
463
|
+
return (event) => {
|
|
464
|
+
const { plainToken } = event.payload;
|
|
465
|
+
if (!plainToken) {
|
|
466
|
+
throw new Error(`The expected plaintoken value was not provided by the event's payload.`);
|
|
467
|
+
}
|
|
468
|
+
const encryptedToken = crypto.createHmac('sha256', zoomSecretToken).update(plainToken).digest('hex');
|
|
469
|
+
const result = {
|
|
470
|
+
plainToken,
|
|
471
|
+
encryptedToken
|
|
472
|
+
};
|
|
473
|
+
return result;
|
|
461
474
|
};
|
|
462
|
-
return result;
|
|
463
|
-
};
|
|
464
475
|
}
|
|
465
476
|
|
|
466
477
|
/**
|
|
467
478
|
* Service that makes system changes based on Zoom webhook events.
|
|
468
479
|
*/
|
|
469
480
|
exports.ZoomWebhookService = class ZoomWebhookService {
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
}
|
|
481
|
+
logger = new common.Logger('ZoomWebhookService');
|
|
482
|
+
_verifier;
|
|
483
|
+
_validator;
|
|
484
|
+
handler = zoomEventHandlerFactory();
|
|
485
|
+
configure = zoomEventHandlerConfigurerFactory(this.handler);
|
|
486
|
+
constructor(config) {
|
|
487
|
+
this._verifier = zoomWebhookEventVerifier(config.webhookConfig.zoomSecretToken);
|
|
488
|
+
this._validator = zoomWebhookEventValidationFunction(config.webhookConfig.zoomSecretToken);
|
|
489
|
+
}
|
|
490
|
+
async updateForWebhook(req, rawBody) {
|
|
491
|
+
const { valid, event } = this._verifier(req, rawBody);
|
|
492
|
+
let handled = false;
|
|
493
|
+
let validationEventResponse;
|
|
494
|
+
if (!valid) {
|
|
495
|
+
this.logger.warn('Received invalid zoom event: ', event);
|
|
496
|
+
}
|
|
497
|
+
else if (event.event === ZOOM_WEBHOOK_URL_VALIDATION_EVENT_TYPE) {
|
|
498
|
+
validationEventResponse = this._validator(event);
|
|
499
|
+
handled = true;
|
|
500
|
+
}
|
|
501
|
+
else {
|
|
502
|
+
handled = await this.updateForZoomEvent(event);
|
|
503
|
+
}
|
|
504
|
+
const result = {
|
|
505
|
+
valid,
|
|
506
|
+
handled,
|
|
507
|
+
event,
|
|
508
|
+
validationEventResponse
|
|
509
|
+
};
|
|
510
|
+
return result;
|
|
511
|
+
}
|
|
512
|
+
async updateForZoomEvent(event) {
|
|
513
|
+
const handled = await this.handler(event);
|
|
514
|
+
if (!handled) {
|
|
515
|
+
this.logger.warn('Received unexpected/unhandled zoom event: ', event);
|
|
516
|
+
}
|
|
517
|
+
return handled;
|
|
518
|
+
}
|
|
509
519
|
};
|
|
510
|
-
exports.ZoomWebhookService = __decorate([
|
|
520
|
+
exports.ZoomWebhookService = __decorate([
|
|
521
|
+
common.Injectable(),
|
|
522
|
+
__param(0, common.Inject(ZoomWebhookServiceConfig)),
|
|
523
|
+
__metadata("design:paramtypes", [ZoomWebhookServiceConfig])
|
|
524
|
+
], exports.ZoomWebhookService);
|
|
511
525
|
|
|
512
526
|
exports.ZoomWebhookController = class ZoomWebhookController {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
}
|
|
528
|
-
}
|
|
527
|
+
zoomWebhookService;
|
|
528
|
+
constructor(zoomWebhookService) {
|
|
529
|
+
this.zoomWebhookService = zoomWebhookService;
|
|
530
|
+
}
|
|
531
|
+
async handleZoomWebhook(res, req, rawBody) {
|
|
532
|
+
const { valid, validationEventResponse } = await this.zoomWebhookService.updateForWebhook(req, rawBody);
|
|
533
|
+
const response = res.status(200); // always return a 200 status code
|
|
534
|
+
if (valid && validationEventResponse) {
|
|
535
|
+
response.json(validationEventResponse);
|
|
536
|
+
}
|
|
537
|
+
else {
|
|
538
|
+
response.json({});
|
|
539
|
+
}
|
|
540
|
+
}
|
|
529
541
|
};
|
|
530
|
-
__decorate([
|
|
531
|
-
|
|
542
|
+
__decorate([
|
|
543
|
+
common.Post(),
|
|
544
|
+
__param(0, common.Res()),
|
|
545
|
+
__param(1, common.Req()),
|
|
546
|
+
__param(2, nestjs.RawBody()),
|
|
547
|
+
__metadata("design:type", Function),
|
|
548
|
+
__metadata("design:paramtypes", [Object, Object, Object]),
|
|
549
|
+
__metadata("design:returntype", Promise)
|
|
550
|
+
], exports.ZoomWebhookController.prototype, "handleZoomWebhook", null);
|
|
551
|
+
exports.ZoomWebhookController = __decorate([
|
|
552
|
+
common.Controller('/webhook/zoom'),
|
|
553
|
+
__param(0, common.Inject(exports.ZoomWebhookService)),
|
|
554
|
+
__metadata("design:paramtypes", [exports.ZoomWebhookService])
|
|
555
|
+
], exports.ZoomWebhookController);
|
|
532
556
|
|
|
533
557
|
function zoomWebhookServiceConfigFactory(configService) {
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
558
|
+
const config = {
|
|
559
|
+
webhookConfig: {
|
|
560
|
+
zoomSecretToken: configService.get(ZOOM_SECRET_TOKEN_ENV_VAR)
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
ZoomWebhookServiceConfig.assertValidConfig(config);
|
|
564
|
+
return config;
|
|
541
565
|
}
|
|
542
566
|
/**
|
|
543
567
|
* Configures webhooks for the service.
|
|
544
568
|
*/
|
|
545
|
-
exports.ZoomWebhookModule = class ZoomWebhookModule {
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
569
|
+
exports.ZoomWebhookModule = class ZoomWebhookModule {
|
|
570
|
+
};
|
|
571
|
+
exports.ZoomWebhookModule = __decorate([
|
|
572
|
+
common.Module({
|
|
573
|
+
imports: [config.ConfigModule],
|
|
574
|
+
controllers: [exports.ZoomWebhookController],
|
|
575
|
+
exports: [exports.ZoomWebhookService],
|
|
576
|
+
providers: [
|
|
577
|
+
{
|
|
578
|
+
provide: ZoomWebhookServiceConfig,
|
|
579
|
+
inject: [config.ConfigService],
|
|
580
|
+
useFactory: zoomWebhookServiceConfigFactory
|
|
581
|
+
},
|
|
582
|
+
exports.ZoomWebhookService
|
|
583
|
+
]
|
|
584
|
+
})
|
|
585
|
+
], exports.ZoomWebhookModule);
|
|
556
586
|
|
|
557
587
|
/**
|
|
558
588
|
* Configuration for ZoomService
|
|
559
589
|
*/
|
|
560
590
|
class ZoomServiceConfig {
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
591
|
+
zoom;
|
|
592
|
+
factoryConfig;
|
|
593
|
+
static assertValidConfig(config) {
|
|
594
|
+
// TODO?
|
|
595
|
+
}
|
|
566
596
|
}
|
|
567
597
|
|
|
568
598
|
exports.ZoomApi = class ZoomApi {
|
|
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
|
-
|
|
620
|
-
|
|
621
|
-
|
|
599
|
+
config;
|
|
600
|
+
zoomOAuthApi;
|
|
601
|
+
zoom;
|
|
602
|
+
get zoomContext() {
|
|
603
|
+
return this.zoom.zoomServerContext;
|
|
604
|
+
}
|
|
605
|
+
get zoomRateLimiter() {
|
|
606
|
+
return this.zoom.zoomServerContext.zoomRateLimiter;
|
|
607
|
+
}
|
|
608
|
+
constructor(config, zoomOAuthApi) {
|
|
609
|
+
this.config = config;
|
|
610
|
+
this.zoomOAuthApi = zoomOAuthApi;
|
|
611
|
+
this.zoom = zoom.zoomFactory({
|
|
612
|
+
...config.factoryConfig,
|
|
613
|
+
oauthContext: zoomOAuthApi.oauthContext
|
|
614
|
+
})(config.zoom);
|
|
615
|
+
}
|
|
616
|
+
// MARK: Users
|
|
617
|
+
get getUser() {
|
|
618
|
+
return zoom.getUser(this.zoomContext);
|
|
619
|
+
}
|
|
620
|
+
get listUsers() {
|
|
621
|
+
return zoom.listUsers(this.zoomContext);
|
|
622
|
+
}
|
|
623
|
+
get listUsersPageFactory() {
|
|
624
|
+
return zoom.listUsersPageFactory(this.zoomContext);
|
|
625
|
+
}
|
|
626
|
+
// MARK: Meetings
|
|
627
|
+
get listMeetingsForUser() {
|
|
628
|
+
return zoom.listMeetingsForUser(this.zoomContext);
|
|
629
|
+
}
|
|
630
|
+
get listMeetingsForUserPageFactory() {
|
|
631
|
+
return zoom.listMeetingsForUserPageFactory(this.zoomContext);
|
|
632
|
+
}
|
|
633
|
+
get createMeetingForUser() {
|
|
634
|
+
return zoom.createMeetingForUser(this.zoomContext);
|
|
635
|
+
}
|
|
636
|
+
get getMeeting() {
|
|
637
|
+
return zoom.getMeeting(this.zoomContext);
|
|
638
|
+
}
|
|
639
|
+
get updateMeeting() {
|
|
640
|
+
return zoom.updateMeeting(this.zoomContext);
|
|
641
|
+
}
|
|
642
|
+
get deleteMeeting() {
|
|
643
|
+
return zoom.deleteMeeting(this.zoomContext);
|
|
644
|
+
}
|
|
645
|
+
// MARK: Past Meetings
|
|
646
|
+
get getPastMeeting() {
|
|
647
|
+
return zoom.getPastMeeting(this.zoomContext);
|
|
648
|
+
}
|
|
649
|
+
get getPastMeetingParticipants() {
|
|
650
|
+
return zoom.getPastMeetingParticipants(this.zoomContext);
|
|
651
|
+
}
|
|
622
652
|
};
|
|
623
|
-
exports.ZoomApi = __decorate([
|
|
653
|
+
exports.ZoomApi = __decorate([
|
|
654
|
+
common.Injectable(),
|
|
655
|
+
__param(0, common.Inject(ZoomServiceConfig)),
|
|
656
|
+
__param(1, common.Inject(exports.ZoomOAuthApi)),
|
|
657
|
+
__metadata("design:paramtypes", [ZoomServiceConfig,
|
|
658
|
+
exports.ZoomOAuthApi])
|
|
659
|
+
], exports.ZoomApi);
|
|
624
660
|
class ZoomApiUserContext {
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
661
|
+
constructor(refreshToken) {
|
|
662
|
+
// TODO: ...
|
|
663
|
+
}
|
|
628
664
|
}
|
|
629
665
|
|
|
630
666
|
// MARK: Provider Factories
|
|
631
667
|
function zoomServiceConfigFactory(configService) {
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
668
|
+
const config = {
|
|
669
|
+
zoom: {}
|
|
670
|
+
};
|
|
671
|
+
ZoomServiceConfig.assertValidConfig(config);
|
|
672
|
+
return config;
|
|
637
673
|
}
|
|
638
674
|
/**
|
|
639
675
|
* Convenience function used to generate ModuleMetadata for an app's ZoomModule.
|
|
@@ -643,22 +679,21 @@ function zoomServiceConfigFactory(configService) {
|
|
|
643
679
|
* @returns
|
|
644
680
|
*/
|
|
645
681
|
function appZoomModuleMetadata(config$1) {
|
|
646
|
-
|
|
647
|
-
dependencyModule
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
}
|
|
661
|
-
};
|
|
682
|
+
const { dependencyModule, imports, exports: exports$1, providers } = config$1;
|
|
683
|
+
const dependencyModuleImport = dependencyModule ? [dependencyModule] : [];
|
|
684
|
+
return {
|
|
685
|
+
imports: [config.ConfigModule, ...dependencyModuleImport, ...(imports ?? [])],
|
|
686
|
+
exports: [exports.ZoomApi, ...(exports$1 ?? [])],
|
|
687
|
+
providers: [
|
|
688
|
+
{
|
|
689
|
+
provide: ZoomServiceConfig,
|
|
690
|
+
inject: [config.ConfigService],
|
|
691
|
+
useFactory: zoomServiceConfigFactory
|
|
692
|
+
},
|
|
693
|
+
exports.ZoomApi,
|
|
694
|
+
...(providers ?? [])
|
|
695
|
+
]
|
|
696
|
+
};
|
|
662
697
|
}
|
|
663
698
|
|
|
664
699
|
exports.DEFAULT_FILE_ZOOM_ACCOUNTS_ACCESS_TOKEN_CACHE_SERVICE_PATH = DEFAULT_FILE_ZOOM_ACCOUNTS_ACCESS_TOKEN_CACHE_SERVICE_PATH;
|