@dereekb/zoom 13.10.9 → 13.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,19 +3,17 @@
3
3
  var common = require('@nestjs/common');
4
4
  var zoom = require('@dereekb/zoom');
5
5
  var util = require('@dereekb/util');
6
- var node_path = require('node:path');
7
- var node_fs = require('node:fs');
8
- var config = require('@nestjs/config');
9
6
  var nestjs = require('@dereekb/nestjs');
7
+ var config = require('@nestjs/config');
10
8
  var node_crypto = require('node:crypto');
11
9
 
12
- function _type_of(obj) {
10
+ function _type_of$1(obj) {
13
11
  "@swc/helpers - typeof";
14
12
  return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
15
13
  }
16
14
  function __decorate(decorators, target, key, desc) {
17
15
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
18
- if ((typeof Reflect === "undefined" ? "undefined" : _type_of(Reflect)) === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
16
+ if ((typeof Reflect === "undefined" ? "undefined" : _type_of$1(Reflect)) === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
19
17
  else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
20
18
  return c > 3 && r && Object.defineProperty(target, key, r), r;
21
19
  }
@@ -177,6 +175,14 @@ function _define_property$7(obj, key, value) {
177
175
  }
178
176
  return obj;
179
177
  }
178
+ function _instanceof(left, right) {
179
+ "@swc/helpers - instanceof";
180
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
181
+ return !!right[Symbol.hasInstance](left);
182
+ } else {
183
+ return left instanceof right;
184
+ }
185
+ }
180
186
  function _iterable_to_array$2(iter) {
181
187
  if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
182
188
  }
@@ -225,12 +231,35 @@ function _object_spread$3(target) {
225
231
  }
226
232
  return target;
227
233
  }
234
+ function ownKeys$2(object, enumerableOnly) {
235
+ var keys = Object.keys(object);
236
+ if (Object.getOwnPropertySymbols) {
237
+ var symbols = Object.getOwnPropertySymbols(object);
238
+ keys.push.apply(keys, symbols);
239
+ }
240
+ return keys;
241
+ }
242
+ function _object_spread_props$2(target, source) {
243
+ source = source != null ? source : {};
244
+ if (Object.getOwnPropertyDescriptors) {
245
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
246
+ } else {
247
+ ownKeys$2(Object(source)).forEach(function(key) {
248
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
249
+ });
250
+ }
251
+ return target;
252
+ }
228
253
  function _sliced_to_array(arr, i) {
229
254
  return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array$2(arr, i) || _non_iterable_rest();
230
255
  }
231
256
  function _to_consumable_array$2(arr) {
232
257
  return _array_without_holes$2(arr) || _iterable_to_array$2(arr) || _unsupported_iterable_to_array$2(arr) || _non_iterable_spread$2();
233
258
  }
259
+ function _type_of(obj) {
260
+ "@swc/helpers - typeof";
261
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
262
+ }
234
263
  function _unsupported_iterable_to_array$2(o, minLen) {
235
264
  if (!o) return;
236
265
  if (typeof o === "string") return _array_like_to_array$2(o, minLen);
@@ -346,6 +375,56 @@ function _ts_generator$2(thisArg, body) {
346
375
  exports.ZoomOAuthAccessTokenCacheService = __decorate([
347
376
  common.Injectable()
348
377
  ], exports.ZoomOAuthAccessTokenCacheService);
378
+ // MARK: Merge
379
+ function buildZoomReadAdapter(cache) {
380
+ return {
381
+ load: function load() {
382
+ return _async_to_generator$2(function() {
383
+ var value;
384
+ return _ts_generator$2(this, function(_state) {
385
+ switch(_state.label){
386
+ case 0:
387
+ return [
388
+ 4,
389
+ cache.loadCachedToken().catch(function() {
390
+ return undefined;
391
+ })
392
+ ];
393
+ case 1:
394
+ value = _state.sent();
395
+ return [
396
+ 2,
397
+ value != null && !util.isExpired(value) ? value : undefined
398
+ ];
399
+ }
400
+ });
401
+ })();
402
+ },
403
+ update: function update(token) {
404
+ return cache.updateCachedToken(token);
405
+ },
406
+ clear: function clear() {
407
+ return _async_to_generator$2(function() {
408
+ return _ts_generator$2(this, function(_state) {
409
+ return [
410
+ 2
411
+ ];
412
+ });
413
+ // ZoomAccessTokenCache does not expose a clear method.
414
+ })();
415
+ }
416
+ };
417
+ }
418
+ function updateZoomCacheCapturingError(cache, accessToken) {
419
+ return cache.updateCachedToken(accessToken).then(function() {
420
+ return null;
421
+ }).catch(function(e) {
422
+ return [
423
+ cache,
424
+ e
425
+ ];
426
+ });
427
+ }
349
428
  /**
350
429
  * Default error logging function for merged cache service update failures.
351
430
  *
@@ -364,6 +443,11 @@ exports.ZoomOAuthAccessTokenCacheService = __decorate([
364
443
  *
365
444
  * When updating a cached token, it will update the token across all services.
366
445
  *
446
+ * Read fall-through is delegated to {@link mergeAsyncValueCaches} after wrapping each
447
+ * underlying cache with an {@link isExpired}-aware filter, so an expired cached token
448
+ * never short-circuits the lookup. Updates run across all services in parallel via
449
+ * `Promise.allSettled`, mirroring the previous behavior, with optional error logging.
450
+ *
367
451
  * @param inputServicesToMerge Must include at least one service. Empty arrays will throw an error.
368
452
  * @param logError Optional error logging configuration. Pass a function, true for default logging, or false to disable.
369
453
  * @returns A merged ZoomOAuthAccessTokenCacheService
@@ -373,60 +457,45 @@ exports.ZoomOAuthAccessTokenCacheService = __decorate([
373
457
  if (allServices.length === 0) {
374
458
  throw new Error('mergeZoomOAuthAccessTokenCacheServices() input cannot be empty.');
375
459
  }
376
- var loadZoomAccessTokenCache = function loadZoomAccessTokenCache(accessCachesForServices) {
377
- var loadCachedTokenFromFirstService = util.tryWithPromiseFactoriesFunction({
378
- promiseFactories: accessCachesForServices.map(function(x) {
379
- return function() {
380
- return x.loadCachedToken().catch(function() {
381
- return null;
382
- }).then(function(x) {
383
- var result = undefined;
384
- if (x && !util.isPast(x.expiresAt)) {
385
- result = x; // only return from cache if it is not expired
386
- }
387
- return result;
388
- });
389
- };
390
- }),
391
- successOnMaybe: false,
392
- throwErrors: false
393
- });
394
- var cacheForService = {
460
+ function mergeCachesForService(accessCachesForServices) {
461
+ // Per-cache adapters with expiry filtering so reads fall through to the next tier when a cache holds an expired token.
462
+ var readAdapters = accessCachesForServices.map(buildZoomReadAdapter);
463
+ var merged = util.mergeAsyncValueCaches(readAdapters);
464
+ return {
395
465
  loadCachedToken: function loadCachedToken() {
396
- return loadCachedTokenFromFirstService();
466
+ return merged.load();
397
467
  },
398
468
  updateCachedToken: function updateCachedToken(accessToken) {
399
469
  return _async_to_generator$2(function() {
470
+ var settled, failedUpdates;
400
471
  return _ts_generator$2(this, function(_state) {
401
- return [
402
- 2,
403
- Promise.allSettled(accessCachesForServices.map(function(x) {
404
- return x.updateCachedToken(accessToken).then(function() {
405
- return null;
406
- }).catch(function(e) {
407
- return [
408
- x,
409
- e
410
- ];
411
- });
412
- })).then(function(x) {
413
- // only find the failures if we're logging
414
- if (logErrorFunction) {
415
- var failedUpdates = util.filterMaybeArrayValues(x.map(function(y) {
472
+ switch(_state.label){
473
+ case 0:
474
+ return [
475
+ 4,
476
+ Promise.allSettled(accessCachesForServices.map(function(cache) {
477
+ return updateZoomCacheCapturingError(cache, accessToken);
478
+ }))
479
+ ];
480
+ case 1:
481
+ settled = _state.sent();
482
+ if (logErrorFunction != null) {
483
+ failedUpdates = util.filterMaybeArrayValues(settled.map(function(y) {
416
484
  return y.value;
417
485
  }));
418
486
  if (failedUpdates.length) {
419
487
  logErrorFunction(failedUpdates);
420
488
  }
421
489
  }
422
- })
423
- ];
490
+ return [
491
+ 2
492
+ ];
493
+ }
424
494
  });
425
495
  })();
426
496
  }
427
497
  };
428
- return cacheForService;
429
- };
498
+ }
430
499
  var allServiceAccessTokenCaches = allServices.map(function(service) {
431
500
  return service.loadZoomAccessTokenCache();
432
501
  });
@@ -437,11 +506,11 @@ exports.ZoomOAuthAccessTokenCacheService = __decorate([
437
506
  var allCaches = allServicesWithCacheForRefreshToken.map(function(x) {
438
507
  return x.cacheForRefreshToken(refreshToken);
439
508
  });
440
- return loadZoomAccessTokenCache(allCaches);
509
+ return mergeCachesForService(allCaches);
441
510
  } : undefined;
442
511
  var service = {
443
- loadZoomAccessTokenCache: function loadZoomAccessTokenCache1() {
444
- return loadZoomAccessTokenCache(allServiceAccessTokenCaches);
512
+ loadZoomAccessTokenCache: function loadZoomAccessTokenCache() {
513
+ return mergeCachesForService(allServiceAccessTokenCaches);
445
514
  },
446
515
  cacheForRefreshToken: cacheForRefreshToken
447
516
  };
@@ -451,45 +520,65 @@ exports.ZoomOAuthAccessTokenCacheService = __decorate([
451
520
  /**
452
521
  * Creates a ZoomOAuthAccessTokenCacheService that uses in-memory storage.
453
522
  *
523
+ * Backed by {@link inMemoryAsyncValueCache} so all consumers share the same single token slot.
524
+ *
454
525
  * @param existingToken Optional initial token to seed the cache with
455
526
  * @param logAccessToConsole Whether to log token access to console
456
527
  * @returns A memory-backed ZoomOAuthAccessTokenCacheService
457
528
  */ function memoryZoomOAuthAccessTokenCacheService(existingToken, logAccessToConsole) {
458
- var token = existingToken;
529
+ var cache = util.inMemoryAsyncValueCache(existingToken);
459
530
  function loadZoomAccessTokenCache() {
460
- var accessTokenCache = {
531
+ return {
461
532
  loadCachedToken: function loadCachedToken() {
462
533
  return _async_to_generator$2(function() {
534
+ var token;
463
535
  return _ts_generator$2(this, function(_state) {
464
- if (logAccessToConsole) {
465
- console.log('retrieving access token from memory: ', {
466
- token: token
467
- });
536
+ switch(_state.label){
537
+ case 0:
538
+ return [
539
+ 4,
540
+ cache.load()
541
+ ];
542
+ case 1:
543
+ token = _state.sent();
544
+ if (logAccessToConsole) {
545
+ console.log('retrieving access token from memory: ', {
546
+ hit: token != null,
547
+ expiresAt: token === null || token === void 0 ? void 0 : token.expiresAt
548
+ });
549
+ }
550
+ return [
551
+ 2,
552
+ token
553
+ ];
468
554
  }
469
- return [
470
- 2,
471
- token
472
- ];
473
555
  });
474
556
  })();
475
557
  },
476
558
  updateCachedToken: function updateCachedToken(accessToken) {
477
559
  return _async_to_generator$2(function() {
478
560
  return _ts_generator$2(this, function(_state) {
479
- token = accessToken;
480
- if (logAccessToConsole) {
481
- console.log('updating access token in memory: ', {
482
- accessToken: accessToken
483
- });
561
+ switch(_state.label){
562
+ case 0:
563
+ return [
564
+ 4,
565
+ cache.update(accessToken)
566
+ ];
567
+ case 1:
568
+ _state.sent();
569
+ if (logAccessToConsole) {
570
+ console.log('updating access token in memory: ', {
571
+ expiresAt: accessToken === null || accessToken === void 0 ? void 0 : accessToken.expiresAt
572
+ });
573
+ }
574
+ return [
575
+ 2
576
+ ];
484
577
  }
485
- return [
486
- 2
487
- ];
488
578
  });
489
579
  })();
490
580
  }
491
581
  };
492
- return accessTokenCache;
493
582
  }
494
583
  return {
495
584
  loadZoomAccessTokenCache: loadZoomAccessTokenCache,
@@ -500,9 +589,33 @@ exports.ZoomOAuthAccessTokenCacheService = __decorate([
500
589
  }
501
590
  // MARK: File System Access Token Cache
502
591
  var DEFAULT_FILE_ZOOM_ACCOUNTS_ACCESS_TOKEN_CACHE_SERVICE_PATH = '.tmp/zoom-access-tokens.json';
592
+ /**
593
+ * Reviver applied to the cached file payload on load so `expiresAt` is always a `Date`
594
+ * regardless of how it was serialized.
595
+ *
596
+ * @param raw - the raw JSON-parsed file payload
597
+ * @returns the revived ZoomAccessToken, or undefined when the payload is empty/invalid
598
+ */ function reviveZoomAccessTokenFile(raw) {
599
+ if (raw == null || (typeof raw === "undefined" ? "undefined" : _type_of(raw)) !== 'object') {
600
+ return undefined;
601
+ }
602
+ var wrapper = raw;
603
+ var token = wrapper.token;
604
+ if (token == null) {
605
+ return undefined;
606
+ }
607
+ var rawExpiresAt = token.expiresAt;
608
+ var expiresAt = rawExpiresAt != null && !_instanceof(rawExpiresAt, Date) ? new Date(rawExpiresAt) : rawExpiresAt;
609
+ return _object_spread_props$2(_object_spread$3({}, token), {
610
+ expiresAt: expiresAt
611
+ });
612
+ }
503
613
  /**
504
614
  * Creates a ZoomOAuthAccessTokenCacheService that reads and writes the access token to the file system.
505
615
  *
616
+ * Composes {@link createMemoizedJsonFileAsyncValueCache} (for the on-disk slot, with optional
617
+ * per-process memoization) so reads after the first hit memory.
618
+ *
506
619
  * Useful for testing.
507
620
  *
508
621
  * @param filename Path to the token cache file
@@ -510,165 +623,51 @@ var DEFAULT_FILE_ZOOM_ACCOUNTS_ACCESS_TOKEN_CACHE_SERVICE_PATH = '.tmp/zoom-acce
510
623
  * @returns A file-system-backed ZoomOAuthAccessTokenCacheService
511
624
  */ function fileZoomOAuthAccessTokenCacheService() {
512
625
  var filename = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : DEFAULT_FILE_ZOOM_ACCOUNTS_ACCESS_TOKEN_CACHE_SERVICE_PATH, useMemoryCache = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : true;
513
- var loadedToken = null;
514
- function loadTokenFile() {
515
- return _async_to_generator$2(function() {
516
- var token, _ref;
517
- return _ts_generator$2(this, function(_state) {
518
- switch(_state.label){
519
- case 0:
520
- token = undefined;
521
- if (!!loadedToken) return [
522
- 3,
523
- 2
524
- ];
525
- return [
526
- 4,
527
- readTokenFile()
528
- ];
529
- case 1:
530
- token = (_ref = _state.sent()) !== null && _ref !== void 0 ? _ref : {};
531
- return [
532
- 3,
533
- 3
534
- ];
535
- case 2:
536
- token = loadedToken;
537
- _state.label = 3;
538
- case 3:
539
- return [
540
- 2,
541
- token
542
- ];
543
- }
544
- });
545
- })();
546
- }
547
- function readTokenFile() {
548
- return new Promise(function(resolve) {
549
- node_fs.mkdirSync(node_path.dirname(filename), {
550
- recursive: true
551
- }); // make the directory first
552
- node_fs.readFile(filename, {}, function(x, data) {
553
- var result = undefined;
554
- if (!x) {
555
- try {
556
- result = JSON.parse(data.toString());
557
- if (result === null || result === void 0 ? void 0 : result.token) {
558
- result.token.expiresAt = new Date(result.token.expiresAt);
559
- }
560
- } catch (e) {
561
- console.error('Failed reading token file: ', e);
562
- }
563
- }
564
- resolve(result);
565
- });
566
- }).then(function(x) {
567
- // update loaded tokens
568
- if (useMemoryCache) {
569
- loadedToken = _object_spread$3({}, loadedToken, x);
570
- }
571
- return x;
572
- });
573
- }
574
- function writeTokenFile(tokens) {
575
- return _async_to_generator$2(function() {
576
- return _ts_generator$2(this, function(_state) {
577
- return [
578
- 2,
579
- new Promise(function(resolve, reject) {
580
- node_fs.writeFile(filename, JSON.stringify(tokens), {}, function(x) {
581
- if (!x) {
582
- resolve();
583
- } else {
584
- reject(x);
585
- }
586
- });
587
- })
588
- ];
589
- });
590
- })();
591
- }
592
- function deleteTokenFile() {
593
- return _async_to_generator$2(function() {
594
- return _ts_generator$2(this, function(_state) {
595
- return [
596
- 2,
597
- new Promise(function(resolve, reject) {
598
- node_fs.rm(filename, function(x) {
599
- if (!x) {
600
- resolve();
601
- } else {
602
- reject(x);
603
- }
604
- });
605
- })
606
- ];
607
- });
608
- })();
609
- }
626
+ var innerCacheInput = {
627
+ filePath: filename,
628
+ reviver: reviveZoomAccessTokenFile,
629
+ replacer: function replacer(token) {
630
+ return {
631
+ token: token
632
+ };
633
+ }
634
+ };
635
+ var cache = useMemoryCache ? nestjs.createMemoizedJsonFileAsyncValueCache(innerCacheInput) : nestjs.createJsonFileAsyncValueCache(innerCacheInput);
610
636
  function loadZoomAccessTokenCache() {
611
- var accessTokenCache = {
637
+ return {
612
638
  loadCachedToken: function loadCachedToken() {
613
- return _async_to_generator$2(function() {
614
- var tokens;
615
- return _ts_generator$2(this, function(_state) {
616
- switch(_state.label){
617
- case 0:
618
- return [
619
- 4,
620
- loadTokenFile()
621
- ];
622
- case 1:
623
- tokens = _state.sent();
624
- // console.log('retrieving access token from file: ', { token });
625
- return [
626
- 2,
627
- tokens.token
628
- ];
629
- }
630
- });
631
- })();
639
+ return cache.load();
632
640
  },
633
641
  updateCachedToken: function updateCachedToken(accessToken) {
634
642
  return _async_to_generator$2(function() {
635
- var tokenFile, e;
643
+ var e;
636
644
  return _ts_generator$2(this, function(_state) {
637
645
  switch(_state.label){
638
646
  case 0:
639
- return [
640
- 4,
641
- loadTokenFile()
642
- ];
643
- case 1:
644
- tokenFile = _state.sent();
645
- tokenFile.token = accessToken;
646
- _state.label = 2;
647
- case 2:
648
647
  _state.trys.push([
648
+ 0,
649
649
  2,
650
- 4,
651
650
  ,
652
- 5
651
+ 3
653
652
  ]);
654
653
  return [
655
654
  4,
656
- writeTokenFile(tokenFile)
655
+ cache.update(accessToken)
657
656
  ];
658
- case 3:
657
+ case 1:
659
658
  _state.sent();
660
659
  return [
661
660
  3,
662
- 5
661
+ 3
663
662
  ];
664
- case 4:
663
+ case 2:
665
664
  e = _state.sent();
666
665
  console.error('Failed updating access token in file: ', e);
667
666
  return [
668
667
  3,
669
- 5
668
+ 3
670
669
  ];
671
- case 5:
670
+ case 3:
672
671
  return [
673
672
  2
674
673
  ];
@@ -677,7 +676,92 @@ var DEFAULT_FILE_ZOOM_ACCOUNTS_ACCESS_TOKEN_CACHE_SERVICE_PATH = '.tmp/zoom-acce
677
676
  })();
678
677
  }
679
678
  };
680
- return accessTokenCache;
679
+ }
680
+ function readTokenFile() {
681
+ return _async_to_generator$2(function() {
682
+ var raw, token;
683
+ return _ts_generator$2(this, function(_state) {
684
+ switch(_state.label){
685
+ case 0:
686
+ return [
687
+ 4,
688
+ nestjs.readJsonFile(filename)
689
+ ];
690
+ case 1:
691
+ raw = _state.sent();
692
+ if (raw == null) {
693
+ return [
694
+ 2,
695
+ undefined
696
+ ];
697
+ }
698
+ token = reviveZoomAccessTokenFile(raw);
699
+ return [
700
+ 2,
701
+ {
702
+ token: token
703
+ }
704
+ ];
705
+ }
706
+ });
707
+ })();
708
+ }
709
+ // Route the file-mutation helpers through the same `cache` instance used by
710
+ // loadZoomAccessTokenCache so the memoized in-memory layer (when useMemoryCache=true) stays
711
+ // consistent with disk. Direct writeJsonFile / removeFile would otherwise leave the memo
712
+ // holding a stale token that no future read could refresh.
713
+ function writeTokenFile(content) {
714
+ return _async_to_generator$2(function() {
715
+ return _ts_generator$2(this, function(_state) {
716
+ switch(_state.label){
717
+ case 0:
718
+ if (!(content.token == null)) return [
719
+ 3,
720
+ 2
721
+ ];
722
+ return [
723
+ 4,
724
+ cache.clear()
725
+ ];
726
+ case 1:
727
+ _state.sent();
728
+ return [
729
+ 3,
730
+ 4
731
+ ];
732
+ case 2:
733
+ return [
734
+ 4,
735
+ cache.update(content.token)
736
+ ];
737
+ case 3:
738
+ _state.sent();
739
+ _state.label = 4;
740
+ case 4:
741
+ return [
742
+ 2
743
+ ];
744
+ }
745
+ });
746
+ })();
747
+ }
748
+ function deleteTokenFile() {
749
+ return _async_to_generator$2(function() {
750
+ return _ts_generator$2(this, function(_state) {
751
+ switch(_state.label){
752
+ case 0:
753
+ return [
754
+ 4,
755
+ cache.clear()
756
+ ];
757
+ case 1:
758
+ _state.sent();
759
+ return [
760
+ 2
761
+ ];
762
+ }
763
+ });
764
+ })();
681
765
  }
682
766
  return {
683
767
  loadZoomAccessTokenCache: loadZoomAccessTokenCache,
@@ -1,19 +1,17 @@
1
1
  import { Injectable, Inject, Logger, Post, Res, Req, Controller, Module } from '@nestjs/common';
2
2
  import { zoomOAuthFactory, serverAccessToken, userAccessToken, zoomFactory, getUser, listUsers, listUsersPageFactory, listMeetingsForUser, listMeetingsForUserPageFactory, createMeetingForUser, getMeeting, updateMeeting, deleteMeeting, getPastMeeting, getPastMeetingParticipants } from '@dereekb/zoom';
3
- import { characterPrefixSuffixInstance, tryWithPromiseFactoriesFunction, isPast, filterMaybeArrayValues, handlerFactory, handlerConfigurerFactory, handlerMappedSetFunctionFactory } from '@dereekb/util';
4
- import { dirname } from 'node:path';
5
- import { mkdirSync, readFile, writeFile, rm } from 'node:fs';
3
+ import { characterPrefixSuffixInstance, inMemoryAsyncValueCache, mergeAsyncValueCaches, isExpired, filterMaybeArrayValues, handlerFactory, handlerConfigurerFactory, handlerMappedSetFunctionFactory } from '@dereekb/util';
4
+ import { createMemoizedJsonFileAsyncValueCache, createJsonFileAsyncValueCache, readJsonFile, RawBody } from '@dereekb/nestjs';
6
5
  import { ConfigService, ConfigModule } from '@nestjs/config';
7
- import { RawBody } from '@dereekb/nestjs';
8
6
  import { createHmac } from 'node:crypto';
9
7
 
10
- function _type_of(obj) {
8
+ function _type_of$1(obj) {
11
9
  "@swc/helpers - typeof";
12
10
  return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
13
11
  }
14
12
  function __decorate(decorators, target, key, desc) {
15
13
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
- if ((typeof Reflect === "undefined" ? "undefined" : _type_of(Reflect)) === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
14
+ if ((typeof Reflect === "undefined" ? "undefined" : _type_of$1(Reflect)) === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
17
15
  else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
18
16
  return c > 3 && r && Object.defineProperty(target, key, r), r;
19
17
  }
@@ -175,6 +173,14 @@ function _define_property$7(obj, key, value) {
175
173
  }
176
174
  return obj;
177
175
  }
176
+ function _instanceof(left, right) {
177
+ "@swc/helpers - instanceof";
178
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
179
+ return !!right[Symbol.hasInstance](left);
180
+ } else {
181
+ return left instanceof right;
182
+ }
183
+ }
178
184
  function _iterable_to_array$2(iter) {
179
185
  if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
180
186
  }
@@ -223,12 +229,35 @@ function _object_spread$3(target) {
223
229
  }
224
230
  return target;
225
231
  }
232
+ function ownKeys$2(object, enumerableOnly) {
233
+ var keys = Object.keys(object);
234
+ if (Object.getOwnPropertySymbols) {
235
+ var symbols = Object.getOwnPropertySymbols(object);
236
+ keys.push.apply(keys, symbols);
237
+ }
238
+ return keys;
239
+ }
240
+ function _object_spread_props$2(target, source) {
241
+ source = source != null ? source : {};
242
+ if (Object.getOwnPropertyDescriptors) {
243
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
244
+ } else {
245
+ ownKeys$2(Object(source)).forEach(function(key) {
246
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
247
+ });
248
+ }
249
+ return target;
250
+ }
226
251
  function _sliced_to_array(arr, i) {
227
252
  return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array$2(arr, i) || _non_iterable_rest();
228
253
  }
229
254
  function _to_consumable_array$2(arr) {
230
255
  return _array_without_holes$2(arr) || _iterable_to_array$2(arr) || _unsupported_iterable_to_array$2(arr) || _non_iterable_spread$2();
231
256
  }
257
+ function _type_of(obj) {
258
+ "@swc/helpers - typeof";
259
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
260
+ }
232
261
  function _unsupported_iterable_to_array$2(o, minLen) {
233
262
  if (!o) return;
234
263
  if (typeof o === "string") return _array_like_to_array$2(o, minLen);
@@ -344,6 +373,56 @@ function _ts_generator$2(thisArg, body) {
344
373
  ZoomOAuthAccessTokenCacheService = __decorate([
345
374
  Injectable()
346
375
  ], ZoomOAuthAccessTokenCacheService);
376
+ // MARK: Merge
377
+ function buildZoomReadAdapter(cache) {
378
+ return {
379
+ load: function load() {
380
+ return _async_to_generator$2(function() {
381
+ var value;
382
+ return _ts_generator$2(this, function(_state) {
383
+ switch(_state.label){
384
+ case 0:
385
+ return [
386
+ 4,
387
+ cache.loadCachedToken().catch(function() {
388
+ return undefined;
389
+ })
390
+ ];
391
+ case 1:
392
+ value = _state.sent();
393
+ return [
394
+ 2,
395
+ value != null && !isExpired(value) ? value : undefined
396
+ ];
397
+ }
398
+ });
399
+ })();
400
+ },
401
+ update: function update(token) {
402
+ return cache.updateCachedToken(token);
403
+ },
404
+ clear: function clear() {
405
+ return _async_to_generator$2(function() {
406
+ return _ts_generator$2(this, function(_state) {
407
+ return [
408
+ 2
409
+ ];
410
+ });
411
+ // ZoomAccessTokenCache does not expose a clear method.
412
+ })();
413
+ }
414
+ };
415
+ }
416
+ function updateZoomCacheCapturingError(cache, accessToken) {
417
+ return cache.updateCachedToken(accessToken).then(function() {
418
+ return null;
419
+ }).catch(function(e) {
420
+ return [
421
+ cache,
422
+ e
423
+ ];
424
+ });
425
+ }
347
426
  /**
348
427
  * Default error logging function for merged cache service update failures.
349
428
  *
@@ -362,6 +441,11 @@ ZoomOAuthAccessTokenCacheService = __decorate([
362
441
  *
363
442
  * When updating a cached token, it will update the token across all services.
364
443
  *
444
+ * Read fall-through is delegated to {@link mergeAsyncValueCaches} after wrapping each
445
+ * underlying cache with an {@link isExpired}-aware filter, so an expired cached token
446
+ * never short-circuits the lookup. Updates run across all services in parallel via
447
+ * `Promise.allSettled`, mirroring the previous behavior, with optional error logging.
448
+ *
365
449
  * @param inputServicesToMerge Must include at least one service. Empty arrays will throw an error.
366
450
  * @param logError Optional error logging configuration. Pass a function, true for default logging, or false to disable.
367
451
  * @returns A merged ZoomOAuthAccessTokenCacheService
@@ -371,60 +455,45 @@ ZoomOAuthAccessTokenCacheService = __decorate([
371
455
  if (allServices.length === 0) {
372
456
  throw new Error('mergeZoomOAuthAccessTokenCacheServices() input cannot be empty.');
373
457
  }
374
- var loadZoomAccessTokenCache = function loadZoomAccessTokenCache(accessCachesForServices) {
375
- var loadCachedTokenFromFirstService = tryWithPromiseFactoriesFunction({
376
- promiseFactories: accessCachesForServices.map(function(x) {
377
- return function() {
378
- return x.loadCachedToken().catch(function() {
379
- return null;
380
- }).then(function(x) {
381
- var result = undefined;
382
- if (x && !isPast(x.expiresAt)) {
383
- result = x; // only return from cache if it is not expired
384
- }
385
- return result;
386
- });
387
- };
388
- }),
389
- successOnMaybe: false,
390
- throwErrors: false
391
- });
392
- var cacheForService = {
458
+ function mergeCachesForService(accessCachesForServices) {
459
+ // Per-cache adapters with expiry filtering so reads fall through to the next tier when a cache holds an expired token.
460
+ var readAdapters = accessCachesForServices.map(buildZoomReadAdapter);
461
+ var merged = mergeAsyncValueCaches(readAdapters);
462
+ return {
393
463
  loadCachedToken: function loadCachedToken() {
394
- return loadCachedTokenFromFirstService();
464
+ return merged.load();
395
465
  },
396
466
  updateCachedToken: function updateCachedToken(accessToken) {
397
467
  return _async_to_generator$2(function() {
468
+ var settled, failedUpdates;
398
469
  return _ts_generator$2(this, function(_state) {
399
- return [
400
- 2,
401
- Promise.allSettled(accessCachesForServices.map(function(x) {
402
- return x.updateCachedToken(accessToken).then(function() {
403
- return null;
404
- }).catch(function(e) {
405
- return [
406
- x,
407
- e
408
- ];
409
- });
410
- })).then(function(x) {
411
- // only find the failures if we're logging
412
- if (logErrorFunction) {
413
- var failedUpdates = filterMaybeArrayValues(x.map(function(y) {
470
+ switch(_state.label){
471
+ case 0:
472
+ return [
473
+ 4,
474
+ Promise.allSettled(accessCachesForServices.map(function(cache) {
475
+ return updateZoomCacheCapturingError(cache, accessToken);
476
+ }))
477
+ ];
478
+ case 1:
479
+ settled = _state.sent();
480
+ if (logErrorFunction != null) {
481
+ failedUpdates = filterMaybeArrayValues(settled.map(function(y) {
414
482
  return y.value;
415
483
  }));
416
484
  if (failedUpdates.length) {
417
485
  logErrorFunction(failedUpdates);
418
486
  }
419
487
  }
420
- })
421
- ];
488
+ return [
489
+ 2
490
+ ];
491
+ }
422
492
  });
423
493
  })();
424
494
  }
425
495
  };
426
- return cacheForService;
427
- };
496
+ }
428
497
  var allServiceAccessTokenCaches = allServices.map(function(service) {
429
498
  return service.loadZoomAccessTokenCache();
430
499
  });
@@ -435,11 +504,11 @@ ZoomOAuthAccessTokenCacheService = __decorate([
435
504
  var allCaches = allServicesWithCacheForRefreshToken.map(function(x) {
436
505
  return x.cacheForRefreshToken(refreshToken);
437
506
  });
438
- return loadZoomAccessTokenCache(allCaches);
507
+ return mergeCachesForService(allCaches);
439
508
  } : undefined;
440
509
  var service = {
441
- loadZoomAccessTokenCache: function loadZoomAccessTokenCache1() {
442
- return loadZoomAccessTokenCache(allServiceAccessTokenCaches);
510
+ loadZoomAccessTokenCache: function loadZoomAccessTokenCache() {
511
+ return mergeCachesForService(allServiceAccessTokenCaches);
443
512
  },
444
513
  cacheForRefreshToken: cacheForRefreshToken
445
514
  };
@@ -449,45 +518,65 @@ ZoomOAuthAccessTokenCacheService = __decorate([
449
518
  /**
450
519
  * Creates a ZoomOAuthAccessTokenCacheService that uses in-memory storage.
451
520
  *
521
+ * Backed by {@link inMemoryAsyncValueCache} so all consumers share the same single token slot.
522
+ *
452
523
  * @param existingToken Optional initial token to seed the cache with
453
524
  * @param logAccessToConsole Whether to log token access to console
454
525
  * @returns A memory-backed ZoomOAuthAccessTokenCacheService
455
526
  */ function memoryZoomOAuthAccessTokenCacheService(existingToken, logAccessToConsole) {
456
- var token = existingToken;
527
+ var cache = inMemoryAsyncValueCache(existingToken);
457
528
  function loadZoomAccessTokenCache() {
458
- var accessTokenCache = {
529
+ return {
459
530
  loadCachedToken: function loadCachedToken() {
460
531
  return _async_to_generator$2(function() {
532
+ var token;
461
533
  return _ts_generator$2(this, function(_state) {
462
- if (logAccessToConsole) {
463
- console.log('retrieving access token from memory: ', {
464
- token: token
465
- });
534
+ switch(_state.label){
535
+ case 0:
536
+ return [
537
+ 4,
538
+ cache.load()
539
+ ];
540
+ case 1:
541
+ token = _state.sent();
542
+ if (logAccessToConsole) {
543
+ console.log('retrieving access token from memory: ', {
544
+ hit: token != null,
545
+ expiresAt: token === null || token === void 0 ? void 0 : token.expiresAt
546
+ });
547
+ }
548
+ return [
549
+ 2,
550
+ token
551
+ ];
466
552
  }
467
- return [
468
- 2,
469
- token
470
- ];
471
553
  });
472
554
  })();
473
555
  },
474
556
  updateCachedToken: function updateCachedToken(accessToken) {
475
557
  return _async_to_generator$2(function() {
476
558
  return _ts_generator$2(this, function(_state) {
477
- token = accessToken;
478
- if (logAccessToConsole) {
479
- console.log('updating access token in memory: ', {
480
- accessToken: accessToken
481
- });
559
+ switch(_state.label){
560
+ case 0:
561
+ return [
562
+ 4,
563
+ cache.update(accessToken)
564
+ ];
565
+ case 1:
566
+ _state.sent();
567
+ if (logAccessToConsole) {
568
+ console.log('updating access token in memory: ', {
569
+ expiresAt: accessToken === null || accessToken === void 0 ? void 0 : accessToken.expiresAt
570
+ });
571
+ }
572
+ return [
573
+ 2
574
+ ];
482
575
  }
483
- return [
484
- 2
485
- ];
486
576
  });
487
577
  })();
488
578
  }
489
579
  };
490
- return accessTokenCache;
491
580
  }
492
581
  return {
493
582
  loadZoomAccessTokenCache: loadZoomAccessTokenCache,
@@ -498,9 +587,33 @@ ZoomOAuthAccessTokenCacheService = __decorate([
498
587
  }
499
588
  // MARK: File System Access Token Cache
500
589
  var DEFAULT_FILE_ZOOM_ACCOUNTS_ACCESS_TOKEN_CACHE_SERVICE_PATH = '.tmp/zoom-access-tokens.json';
590
+ /**
591
+ * Reviver applied to the cached file payload on load so `expiresAt` is always a `Date`
592
+ * regardless of how it was serialized.
593
+ *
594
+ * @param raw - the raw JSON-parsed file payload
595
+ * @returns the revived ZoomAccessToken, or undefined when the payload is empty/invalid
596
+ */ function reviveZoomAccessTokenFile(raw) {
597
+ if (raw == null || (typeof raw === "undefined" ? "undefined" : _type_of(raw)) !== 'object') {
598
+ return undefined;
599
+ }
600
+ var wrapper = raw;
601
+ var token = wrapper.token;
602
+ if (token == null) {
603
+ return undefined;
604
+ }
605
+ var rawExpiresAt = token.expiresAt;
606
+ var expiresAt = rawExpiresAt != null && !_instanceof(rawExpiresAt, Date) ? new Date(rawExpiresAt) : rawExpiresAt;
607
+ return _object_spread_props$2(_object_spread$3({}, token), {
608
+ expiresAt: expiresAt
609
+ });
610
+ }
501
611
  /**
502
612
  * Creates a ZoomOAuthAccessTokenCacheService that reads and writes the access token to the file system.
503
613
  *
614
+ * Composes {@link createMemoizedJsonFileAsyncValueCache} (for the on-disk slot, with optional
615
+ * per-process memoization) so reads after the first hit memory.
616
+ *
504
617
  * Useful for testing.
505
618
  *
506
619
  * @param filename Path to the token cache file
@@ -508,165 +621,51 @@ var DEFAULT_FILE_ZOOM_ACCOUNTS_ACCESS_TOKEN_CACHE_SERVICE_PATH = '.tmp/zoom-acce
508
621
  * @returns A file-system-backed ZoomOAuthAccessTokenCacheService
509
622
  */ function fileZoomOAuthAccessTokenCacheService() {
510
623
  var filename = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : DEFAULT_FILE_ZOOM_ACCOUNTS_ACCESS_TOKEN_CACHE_SERVICE_PATH, useMemoryCache = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : true;
511
- var loadedToken = null;
512
- function loadTokenFile() {
513
- return _async_to_generator$2(function() {
514
- var token, _ref;
515
- return _ts_generator$2(this, function(_state) {
516
- switch(_state.label){
517
- case 0:
518
- token = undefined;
519
- if (!!loadedToken) return [
520
- 3,
521
- 2
522
- ];
523
- return [
524
- 4,
525
- readTokenFile()
526
- ];
527
- case 1:
528
- token = (_ref = _state.sent()) !== null && _ref !== void 0 ? _ref : {};
529
- return [
530
- 3,
531
- 3
532
- ];
533
- case 2:
534
- token = loadedToken;
535
- _state.label = 3;
536
- case 3:
537
- return [
538
- 2,
539
- token
540
- ];
541
- }
542
- });
543
- })();
544
- }
545
- function readTokenFile() {
546
- return new Promise(function(resolve) {
547
- mkdirSync(dirname(filename), {
548
- recursive: true
549
- }); // make the directory first
550
- readFile(filename, {}, function(x, data) {
551
- var result = undefined;
552
- if (!x) {
553
- try {
554
- result = JSON.parse(data.toString());
555
- if (result === null || result === void 0 ? void 0 : result.token) {
556
- result.token.expiresAt = new Date(result.token.expiresAt);
557
- }
558
- } catch (e) {
559
- console.error('Failed reading token file: ', e);
560
- }
561
- }
562
- resolve(result);
563
- });
564
- }).then(function(x) {
565
- // update loaded tokens
566
- if (useMemoryCache) {
567
- loadedToken = _object_spread$3({}, loadedToken, x);
568
- }
569
- return x;
570
- });
571
- }
572
- function writeTokenFile(tokens) {
573
- return _async_to_generator$2(function() {
574
- return _ts_generator$2(this, function(_state) {
575
- return [
576
- 2,
577
- new Promise(function(resolve, reject) {
578
- writeFile(filename, JSON.stringify(tokens), {}, function(x) {
579
- if (!x) {
580
- resolve();
581
- } else {
582
- reject(x);
583
- }
584
- });
585
- })
586
- ];
587
- });
588
- })();
589
- }
590
- function deleteTokenFile() {
591
- return _async_to_generator$2(function() {
592
- return _ts_generator$2(this, function(_state) {
593
- return [
594
- 2,
595
- new Promise(function(resolve, reject) {
596
- rm(filename, function(x) {
597
- if (!x) {
598
- resolve();
599
- } else {
600
- reject(x);
601
- }
602
- });
603
- })
604
- ];
605
- });
606
- })();
607
- }
624
+ var innerCacheInput = {
625
+ filePath: filename,
626
+ reviver: reviveZoomAccessTokenFile,
627
+ replacer: function replacer(token) {
628
+ return {
629
+ token: token
630
+ };
631
+ }
632
+ };
633
+ var cache = useMemoryCache ? createMemoizedJsonFileAsyncValueCache(innerCacheInput) : createJsonFileAsyncValueCache(innerCacheInput);
608
634
  function loadZoomAccessTokenCache() {
609
- var accessTokenCache = {
635
+ return {
610
636
  loadCachedToken: function loadCachedToken() {
611
- return _async_to_generator$2(function() {
612
- var tokens;
613
- return _ts_generator$2(this, function(_state) {
614
- switch(_state.label){
615
- case 0:
616
- return [
617
- 4,
618
- loadTokenFile()
619
- ];
620
- case 1:
621
- tokens = _state.sent();
622
- // console.log('retrieving access token from file: ', { token });
623
- return [
624
- 2,
625
- tokens.token
626
- ];
627
- }
628
- });
629
- })();
637
+ return cache.load();
630
638
  },
631
639
  updateCachedToken: function updateCachedToken(accessToken) {
632
640
  return _async_to_generator$2(function() {
633
- var tokenFile, e;
641
+ var e;
634
642
  return _ts_generator$2(this, function(_state) {
635
643
  switch(_state.label){
636
644
  case 0:
637
- return [
638
- 4,
639
- loadTokenFile()
640
- ];
641
- case 1:
642
- tokenFile = _state.sent();
643
- tokenFile.token = accessToken;
644
- _state.label = 2;
645
- case 2:
646
645
  _state.trys.push([
646
+ 0,
647
647
  2,
648
- 4,
649
648
  ,
650
- 5
649
+ 3
651
650
  ]);
652
651
  return [
653
652
  4,
654
- writeTokenFile(tokenFile)
653
+ cache.update(accessToken)
655
654
  ];
656
- case 3:
655
+ case 1:
657
656
  _state.sent();
658
657
  return [
659
658
  3,
660
- 5
659
+ 3
661
660
  ];
662
- case 4:
661
+ case 2:
663
662
  e = _state.sent();
664
663
  console.error('Failed updating access token in file: ', e);
665
664
  return [
666
665
  3,
667
- 5
666
+ 3
668
667
  ];
669
- case 5:
668
+ case 3:
670
669
  return [
671
670
  2
672
671
  ];
@@ -675,7 +674,92 @@ var DEFAULT_FILE_ZOOM_ACCOUNTS_ACCESS_TOKEN_CACHE_SERVICE_PATH = '.tmp/zoom-acce
675
674
  })();
676
675
  }
677
676
  };
678
- return accessTokenCache;
677
+ }
678
+ function readTokenFile() {
679
+ return _async_to_generator$2(function() {
680
+ var raw, token;
681
+ return _ts_generator$2(this, function(_state) {
682
+ switch(_state.label){
683
+ case 0:
684
+ return [
685
+ 4,
686
+ readJsonFile(filename)
687
+ ];
688
+ case 1:
689
+ raw = _state.sent();
690
+ if (raw == null) {
691
+ return [
692
+ 2,
693
+ undefined
694
+ ];
695
+ }
696
+ token = reviveZoomAccessTokenFile(raw);
697
+ return [
698
+ 2,
699
+ {
700
+ token: token
701
+ }
702
+ ];
703
+ }
704
+ });
705
+ })();
706
+ }
707
+ // Route the file-mutation helpers through the same `cache` instance used by
708
+ // loadZoomAccessTokenCache so the memoized in-memory layer (when useMemoryCache=true) stays
709
+ // consistent with disk. Direct writeJsonFile / removeFile would otherwise leave the memo
710
+ // holding a stale token that no future read could refresh.
711
+ function writeTokenFile(content) {
712
+ return _async_to_generator$2(function() {
713
+ return _ts_generator$2(this, function(_state) {
714
+ switch(_state.label){
715
+ case 0:
716
+ if (!(content.token == null)) return [
717
+ 3,
718
+ 2
719
+ ];
720
+ return [
721
+ 4,
722
+ cache.clear()
723
+ ];
724
+ case 1:
725
+ _state.sent();
726
+ return [
727
+ 3,
728
+ 4
729
+ ];
730
+ case 2:
731
+ return [
732
+ 4,
733
+ cache.update(content.token)
734
+ ];
735
+ case 3:
736
+ _state.sent();
737
+ _state.label = 4;
738
+ case 4:
739
+ return [
740
+ 2
741
+ ];
742
+ }
743
+ });
744
+ })();
745
+ }
746
+ function deleteTokenFile() {
747
+ return _async_to_generator$2(function() {
748
+ return _ts_generator$2(this, function(_state) {
749
+ switch(_state.label){
750
+ case 0:
751
+ return [
752
+ 4,
753
+ cache.clear()
754
+ ];
755
+ case 1:
756
+ _state.sent();
757
+ return [
758
+ 2
759
+ ];
760
+ }
761
+ });
762
+ })();
679
763
  }
680
764
  return {
681
765
  loadZoomAccessTokenCache: loadZoomAccessTokenCache,
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@dereekb/zoom/nestjs",
3
- "version": "13.10.9",
3
+ "version": "13.11.1",
4
4
  "peerDependencies": {
5
- "@dereekb/nestjs": "13.10.9",
6
- "@dereekb/rxjs": "13.10.9",
7
- "@dereekb/util": "13.10.9",
8
- "@dereekb/zoom": "13.10.9",
5
+ "@dereekb/nestjs": "13.11.1",
6
+ "@dereekb/rxjs": "13.11.1",
7
+ "@dereekb/util": "13.11.1",
8
+ "@dereekb/zoom": "13.11.1",
9
9
  "@nestjs/common": "^11.1.19",
10
10
  "@nestjs/config": "^4.0.4",
11
11
  "express": "^5.2.1"
@@ -32,6 +32,11 @@ export declare function logMergeZoomOAuthAccessTokenCacheServiceErrorFunction(fa
32
32
  *
33
33
  * When updating a cached token, it will update the token across all services.
34
34
  *
35
+ * Read fall-through is delegated to {@link mergeAsyncValueCaches} after wrapping each
36
+ * underlying cache with an {@link isExpired}-aware filter, so an expired cached token
37
+ * never short-circuits the lookup. Updates run across all services in parallel via
38
+ * `Promise.allSettled`, mirroring the previous behavior, with optional error logging.
39
+ *
35
40
  * @param inputServicesToMerge Must include at least one service. Empty arrays will throw an error.
36
41
  * @param logError Optional error logging configuration. Pass a function, true for default logging, or false to disable.
37
42
  * @returns A merged ZoomOAuthAccessTokenCacheService
@@ -40,6 +45,8 @@ export declare function mergeZoomOAuthAccessTokenCacheServices(inputServicesToMe
40
45
  /**
41
46
  * Creates a ZoomOAuthAccessTokenCacheService that uses in-memory storage.
42
47
  *
48
+ * Backed by {@link inMemoryAsyncValueCache} so all consumers share the same single token slot.
49
+ *
43
50
  * @param existingToken Optional initial token to seed the cache with
44
51
  * @param logAccessToConsole Whether to log token access to console
45
52
  * @returns A memory-backed ZoomOAuthAccessTokenCacheService
@@ -57,6 +64,9 @@ export type ZoomOAuthAccessTokenCacheFileContent = {
57
64
  /**
58
65
  * Creates a ZoomOAuthAccessTokenCacheService that reads and writes the access token to the file system.
59
66
  *
67
+ * Composes {@link createMemoizedJsonFileAsyncValueCache} (for the on-disk slot, with optional
68
+ * per-process memoization) so reads after the first hit memory.
69
+ *
60
70
  * Useful for testing.
61
71
  *
62
72
  * @param filename Path to the token cache file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/zoom",
3
- "version": "13.10.9",
3
+ "version": "13.11.1",
4
4
  "exports": {
5
5
  "./nestjs": {
6
6
  "module": "./nestjs/index.esm.js",
@@ -17,9 +17,9 @@
17
17
  }
18
18
  },
19
19
  "peerDependencies": {
20
- "@dereekb/nestjs": "13.10.9",
21
- "@dereekb/rxjs": "13.10.9",
22
- "@dereekb/util": "13.10.9",
20
+ "@dereekb/nestjs": "13.11.1",
21
+ "@dereekb/rxjs": "13.11.1",
22
+ "@dereekb/util": "13.11.1",
23
23
  "@nestjs/common": "^11.1.19",
24
24
  "@nestjs/config": "^4.0.4",
25
25
  "express": "^5.2.1",