@dereekb/calcom 13.32.0 → 13.34.0

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.
@@ -1,5 +1,5 @@
1
- import { Injectable, Inject, Logger, Post, Res, Req, Controller, Module } from '@nestjs/common';
2
- import { calcomOAuthFactory, exchangeAuthorizationCode, calcomFactory, getMe, getSchedules, createBooking, getBooking, cancelBooking, getEventTypes, createEventType, updateEventType, deleteEventType, getCalendars, getBusyTimes, createWebhook, getWebhooks, getWebhook, updateWebhook, deleteWebhook, getAvailableSlots } from '@dereekb/calcom';
1
+ import { Logger, Injectable, Inject, Post, Res, Req, Controller, Module } from '@nestjs/common';
2
+ import { calcomOAuthFactory, calcomAuthCredentialFromValues, exchangeAuthorizationCode, calcomAccessTokenFromTokenResponse, calcomFactory, getMe, getSchedules, createBooking, getBooking, cancelBooking, getEventTypes, createEventType, updateEventType, deleteEventType, getCalendars, getBusyTimes, createWebhook, getWebhooks, getWebhook, updateWebhook, deleteWebhook, getAvailableSlots } from '@dereekb/calcom';
3
3
  import { inMemoryAsyncValueCache, inMemoryAsyncKeyedValueCache, mergeAsyncValueCaches, isExpired, filterMaybeArrayValues, cachedGetter, handlerFactory, handlerConfigurerFactory, handlerMappedSetFunctionFactory } from '@dereekb/util';
4
4
  import { createMemoizedJsonFileAsyncValueCache, RawBody } from '@dereekb/nestjs';
5
5
  import { createHash, createHmac } from 'node:crypto';
@@ -78,6 +78,8 @@ var CALCOM_API_KEY_CONFIG_KEY = 'CALCOM_API_KEY';
78
78
  if (!calcomOAuth) {
79
79
  throw new Error('CalcomOAuthServiceConfig.calcomOAuth is required');
80
80
  }
81
+ // mirrors the guard in calcomOAuthFactory(): an api key IS a token, anything else is an exchange
82
+ // the token endpoint authenticates with the client pair. The two must not drift
81
83
  var hasApiKey = !!calcomOAuth.apiKey;
82
84
  var hasOAuth = !!calcomOAuth.clientId && !!calcomOAuth.clientSecret;
83
85
  if (!hasApiKey && !hasOAuth) {
@@ -106,6 +108,12 @@ var CALCOM_API_KEY_CONFIG_KEY = 'CALCOM_API_KEY';
106
108
  apiKey: apiKey || undefined
107
109
  }
108
110
  };
111
+ // the api key wins for ambient calls because it does not expire, so a configured refresh token is
112
+ // silently unused. Warned here rather than in assertValidConfig, which tests call directly and
113
+ // which stays side-effect-free
114
+ if (apiKey && refreshToken) {
115
+ new Logger('CalcomOAuthServiceConfig').warn("Both ".concat(CALCOM_API_KEY_CONFIG_KEY, " and ").concat(CALCOM_REFRESH_TOKEN_CONFIG_KEY, " are set. The api key takes precedence for ambient calls and the refresh token is ignored — unset one to make the intent explicit."));
116
+ }
109
117
  CalcomOAuthServiceConfig.assertValidConfig(config);
110
118
  return config;
111
119
  }
@@ -121,7 +129,7 @@ function _array_with_holes(arr) {
121
129
  function _array_without_holes$3(arr) {
122
130
  if (Array.isArray(arr)) return _array_like_to_array$3(arr);
123
131
  }
124
- function asyncGeneratorStep$2(gen, resolve, reject, _next, _throw, key, arg) {
132
+ function asyncGeneratorStep$3(gen, resolve, reject, _next, _throw, key, arg) {
125
133
  try {
126
134
  var info = gen[key](arg);
127
135
  var value = info.value;
@@ -135,16 +143,16 @@ function asyncGeneratorStep$2(gen, resolve, reject, _next, _throw, key, arg) {
135
143
  Promise.resolve(value).then(_next, _throw);
136
144
  }
137
145
  }
138
- function _async_to_generator$2(fn) {
146
+ function _async_to_generator$3(fn) {
139
147
  return function() {
140
148
  var self = this, args = arguments;
141
149
  return new Promise(function(resolve, reject) {
142
150
  var gen = fn.apply(self, args);
143
151
  function _next(value) {
144
- asyncGeneratorStep$2(gen, resolve, reject, _next, _throw, "next", value);
152
+ asyncGeneratorStep$3(gen, resolve, reject, _next, _throw, "next", value);
145
153
  }
146
154
  function _throw(err) {
147
- asyncGeneratorStep$2(gen, resolve, reject, _next, _throw, "throw", err);
155
+ asyncGeneratorStep$3(gen, resolve, reject, _next, _throw, "throw", err);
148
156
  }
149
157
  _next(undefined);
150
158
  });
@@ -261,7 +269,7 @@ function _unsupported_iterable_to_array$3(o, minLen) {
261
269
  if (n === "Map" || n === "Set") return Array.from(n);
262
270
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$3(o, minLen);
263
271
  }
264
- function _ts_generator$2(thisArg, body) {
272
+ function _ts_generator$3(thisArg, body) {
265
273
  var f, y, t, _ = {
266
274
  label: 0,
267
275
  sent: function() {
@@ -365,7 +373,8 @@ function _ts_generator$2(thisArg, body) {
365
373
  *
366
374
  * Implementations store and retrieve OAuth access tokens (and the rotated refresh tokens
367
375
  * embedded in them). The service supports both a server-level cache and per-user caches
368
- * keyed by the user's initial refresh token.
376
+ * keyed either by a caller-owned key ({@link cacheForKey}) or by the user's refresh token
377
+ * ({@link cacheForRefreshToken}).
369
378
  */ var CalcomOAuthAccessTokenCacheService = function CalcomOAuthAccessTokenCacheService() {
370
379
  _class_call_check$7(this, CalcomOAuthAccessTokenCacheService);
371
380
  };
@@ -382,13 +391,29 @@ CalcomOAuthAccessTokenCacheService = __decorate([
382
391
  */ function calcomRefreshTokenCacheKey(refreshToken) {
383
392
  return createHash('sha256').update(refreshToken).digest('hex').substring(0, 16);
384
393
  }
394
+ /**
395
+ * Matches any character that is unsafe in a filesystem path segment.
396
+ */ var UNSAFE_CALCOM_CACHE_FILE_KEY_CHARACTERS_REGEX = /[^a-zA-Z0-9_-]/g;
397
+ /**
398
+ * Converts a cache key into a filesystem-safe path segment.
399
+ *
400
+ * A key that is already safe (such as the hex output of {@link calcomRefreshTokenCacheKey}) is
401
+ * returned unchanged. Otherwise the unsafe characters are replaced and a hash of the original key
402
+ * is appended, so two different keys can never collapse onto the same file.
403
+ *
404
+ * @param key - The cache key to convert.
405
+ * @returns A filesystem-safe path segment for the key.
406
+ */ function calcomAccessTokenCacheFileKey(key) {
407
+ var safeKey = key.replaceAll(UNSAFE_CALCOM_CACHE_FILE_KEY_CHARACTERS_REGEX, '_');
408
+ return safeKey === key ? key : "".concat(safeKey, "-").concat(createHash('sha256').update(key).digest('hex').substring(0, 8));
409
+ }
385
410
  // MARK: Merge
386
411
  function buildCalcomReadAdapter(cache) {
387
412
  return {
388
413
  load: function load() {
389
- return _async_to_generator$2(function() {
414
+ return _async_to_generator$3(function() {
390
415
  var value;
391
- return _ts_generator$2(this, function(_state) {
416
+ return _ts_generator$3(this, function(_state) {
392
417
  switch(_state.label){
393
418
  case 0:
394
419
  return [
@@ -411,8 +436,8 @@ function buildCalcomReadAdapter(cache) {
411
436
  return cache.updateCachedToken(token);
412
437
  },
413
438
  clear: function clear() {
414
- return _async_to_generator$2(function() {
415
- return _ts_generator$2(this, function(_state) {
439
+ return _async_to_generator$3(function() {
440
+ return _ts_generator$3(this, function(_state) {
416
441
  return [
417
442
  2
418
443
  ];
@@ -473,9 +498,9 @@ function updateCalcomCacheCapturingError(cache, accessToken) {
473
498
  return merged.load();
474
499
  },
475
500
  updateCachedToken: function updateCachedToken(accessToken) {
476
- return _async_to_generator$2(function() {
501
+ return _async_to_generator$3(function() {
477
502
  var settled, failedUpdates;
478
- return _ts_generator$2(this, function(_state) {
503
+ return _ts_generator$3(this, function(_state) {
479
504
  switch(_state.label){
480
505
  case 0:
481
506
  return [
@@ -509,16 +534,26 @@ function updateCalcomCacheCapturingError(cache, accessToken) {
509
534
  var allServicesWithCacheForRefreshToken = allServices.filter(function(x) {
510
535
  return x.cacheForRefreshToken != null;
511
536
  });
537
+ var allServicesWithCacheForKey = allServices.filter(function(x) {
538
+ return x.cacheForKey != null;
539
+ });
512
540
  var cacheForRefreshToken = allServicesWithCacheForRefreshToken.length > 0 ? function(refreshToken) {
513
541
  var allCaches = allServicesWithCacheForRefreshToken.map(function(x) {
514
542
  return x.cacheForRefreshToken(refreshToken);
515
543
  });
516
544
  return mergeCachesForService(allCaches);
517
545
  } : undefined;
546
+ var cacheForKey = allServicesWithCacheForKey.length > 0 ? function(key) {
547
+ var allCaches = allServicesWithCacheForKey.map(function(x) {
548
+ return x.cacheForKey(key);
549
+ });
550
+ return mergeCachesForService(allCaches);
551
+ } : undefined;
518
552
  var service = {
519
553
  loadCalcomAccessTokenCache: function loadCalcomAccessTokenCache() {
520
554
  return mergeCachesForService(allServiceAccessTokenCaches);
521
555
  },
556
+ cacheForKey: cacheForKey,
522
557
  cacheForRefreshToken: cacheForRefreshToken
523
558
  };
524
559
  return service;
@@ -533,9 +568,9 @@ function updateCalcomCacheCapturingError(cache, accessToken) {
533
568
  */ function calcomAccessTokenCacheFromAsyncValueCache(cache, logAccessToConsole) {
534
569
  return {
535
570
  loadCachedToken: function loadCachedToken() {
536
- return _async_to_generator$2(function() {
571
+ return _async_to_generator$3(function() {
537
572
  var token;
538
- return _ts_generator$2(this, function(_state) {
573
+ return _ts_generator$3(this, function(_state) {
539
574
  switch(_state.label){
540
575
  case 0:
541
576
  return [
@@ -559,8 +594,8 @@ function updateCalcomCacheCapturingError(cache, accessToken) {
559
594
  })();
560
595
  },
561
596
  updateCachedToken: function updateCachedToken(accessToken) {
562
- return _async_to_generator$2(function() {
563
- return _ts_generator$2(this, function(_state) {
597
+ return _async_to_generator$3(function() {
598
+ return _ts_generator$3(this, function(_state) {
564
599
  switch(_state.label){
565
600
  case 0:
566
601
  return [
@@ -609,13 +644,16 @@ function updateCalcomCacheCapturingError(cache, accessToken) {
609
644
  }
610
645
  };
611
646
  }
647
+ function cacheForKey(key) {
648
+ return calcomAccessTokenCacheFromAsyncValueCache(userCacheView(key), logAccessToConsole);
649
+ }
612
650
  return {
613
651
  loadCalcomAccessTokenCache: function loadCalcomAccessTokenCache() {
614
652
  return calcomAccessTokenCacheFromAsyncValueCache(serverCache, logAccessToConsole);
615
653
  },
654
+ cacheForKey: cacheForKey,
616
655
  cacheForRefreshToken: function cacheForRefreshToken(refreshToken) {
617
- var key = calcomRefreshTokenCacheKey(refreshToken);
618
- return calcomAccessTokenCacheFromAsyncValueCache(userCacheView(key), logAccessToConsole);
656
+ return cacheForKey(calcomRefreshTokenCacheKey(refreshToken));
619
657
  }
620
658
  };
621
659
  }
@@ -689,9 +727,9 @@ var CALCOM_SERVER_TOKEN_FILE_KEY = 'server';
689
727
  return cache.load();
690
728
  },
691
729
  updateCachedToken: function updateCachedToken(accessToken) {
692
- return _async_to_generator$2(function() {
730
+ return _async_to_generator$3(function() {
693
731
  var e;
694
- return _ts_generator$2(this, function(_state) {
732
+ return _ts_generator$3(this, function(_state) {
695
733
  switch(_state.label){
696
734
  case 0:
697
735
  _state.trys.push([
@@ -724,17 +762,50 @@ var CALCOM_SERVER_TOKEN_FILE_KEY = 'server';
724
762
  }
725
763
  };
726
764
  }
765
+ function cacheForCallerKey(key) {
766
+ return makeCacheForKey("user-".concat(calcomAccessTokenCacheFileKey(key)));
767
+ }
727
768
  return {
728
769
  cacheDir: cacheDir,
729
770
  loadCalcomAccessTokenCache: function loadCalcomAccessTokenCache() {
730
771
  return makeCacheForKey(CALCOM_SERVER_TOKEN_FILE_KEY);
731
772
  },
773
+ cacheForKey: cacheForCallerKey,
732
774
  cacheForRefreshToken: function cacheForRefreshToken(refreshToken) {
733
- return makeCacheForKey("user-".concat(calcomRefreshTokenCacheKey(refreshToken)));
775
+ return cacheForCallerKey(calcomRefreshTokenCacheKey(refreshToken));
734
776
  }
735
777
  };
736
778
  }
737
779
 
780
+ function asyncGeneratorStep$2(gen, resolve, reject, _next, _throw, key, arg) {
781
+ try {
782
+ var info = gen[key](arg);
783
+ var value = info.value;
784
+ } catch (error) {
785
+ reject(error);
786
+ return;
787
+ }
788
+ if (info.done) {
789
+ resolve(value);
790
+ } else {
791
+ Promise.resolve(value).then(_next, _throw);
792
+ }
793
+ }
794
+ function _async_to_generator$2(fn) {
795
+ return function() {
796
+ var self = this, args = arguments;
797
+ return new Promise(function(resolve, reject) {
798
+ var gen = fn.apply(self, args);
799
+ function _next(value) {
800
+ asyncGeneratorStep$2(gen, resolve, reject, _next, _throw, "next", value);
801
+ }
802
+ function _throw(err) {
803
+ asyncGeneratorStep$2(gen, resolve, reject, _next, _throw, "throw", err);
804
+ }
805
+ _next(undefined);
806
+ });
807
+ };
808
+ }
738
809
  function _class_call_check$6(instance, Constructor) {
739
810
  if (!(instance instanceof Constructor)) {
740
811
  throw new TypeError("Cannot call a class as a function");
@@ -766,6 +837,105 @@ function _define_property$6(obj, key, value) {
766
837
  }
767
838
  return obj;
768
839
  }
840
+ function _ts_generator$2(thisArg, body) {
841
+ var f, y, t, _ = {
842
+ label: 0,
843
+ sent: function() {
844
+ if (t[0] & 1) throw t[1];
845
+ return t[1];
846
+ },
847
+ trys: [],
848
+ ops: []
849
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
850
+ return d(g, "next", {
851
+ value: verb(0)
852
+ }), d(g, "throw", {
853
+ value: verb(1)
854
+ }), d(g, "return", {
855
+ value: verb(2)
856
+ }), typeof Symbol === "function" && d(g, Symbol.iterator, {
857
+ value: function() {
858
+ return this;
859
+ }
860
+ }), g;
861
+ function verb(n) {
862
+ return function(v) {
863
+ return step([
864
+ n,
865
+ v
866
+ ]);
867
+ };
868
+ }
869
+ function step(op) {
870
+ if (f) throw new TypeError("Generator is already executing.");
871
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
872
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
873
+ if (y = 0, t) op = [
874
+ op[0] & 2,
875
+ t.value
876
+ ];
877
+ switch(op[0]){
878
+ case 0:
879
+ case 1:
880
+ t = op;
881
+ break;
882
+ case 4:
883
+ _.label++;
884
+ return {
885
+ value: op[1],
886
+ done: false
887
+ };
888
+ case 5:
889
+ _.label++;
890
+ y = op[1];
891
+ op = [
892
+ 0
893
+ ];
894
+ continue;
895
+ case 7:
896
+ op = _.ops.pop();
897
+ _.trys.pop();
898
+ continue;
899
+ default:
900
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
901
+ _ = 0;
902
+ continue;
903
+ }
904
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
905
+ _.label = op[1];
906
+ break;
907
+ }
908
+ if (op[0] === 6 && _.label < t[1]) {
909
+ _.label = t[1];
910
+ t = op;
911
+ break;
912
+ }
913
+ if (t && _.label < t[2]) {
914
+ _.label = t[2];
915
+ _.ops.push(op);
916
+ break;
917
+ }
918
+ if (t[2]) _.ops.pop();
919
+ _.trys.pop();
920
+ continue;
921
+ }
922
+ op = body.call(thisArg, _);
923
+ } catch (e) {
924
+ op = [
925
+ 6,
926
+ e
927
+ ];
928
+ y = 0;
929
+ } finally{
930
+ f = t = 0;
931
+ }
932
+ if (op[0] & 5) throw op[1];
933
+ return {
934
+ value: op[0] ? op[1] : void 0,
935
+ done: true
936
+ };
937
+ }
938
+ }
769
939
  var CalcomOAuthApi = /*#__PURE__*/ function() {
770
940
  function CalcomOAuthApi(config, cacheService) {
771
941
  _class_call_check$6(this, CalcomOAuthApi);
@@ -777,12 +947,20 @@ var CalcomOAuthApi = /*#__PURE__*/ function() {
777
947
  this.cacheService = cacheService;
778
948
  var accessTokenCache = cacheService.loadCalcomAccessTokenCache();
779
949
  var _config_calcomOAuth = config.calcomOAuth, clientId = _config_calcomOAuth.clientId, clientSecret = _config_calcomOAuth.clientSecret, refreshToken = _config_calcomOAuth.refreshToken, apiKey = _config_calcomOAuth.apiKey;
950
+ // the environment-facing config stays flat, mirroring the CALCOM_* variables it is read from.
951
+ // `client` is the app's OAuth registration, sent on every exchange; `defaultAuth` is the one
952
+ // credential the ambient loadAccessToken() resolves. The client is taken as a pair or not at all,
953
+ // which replaces the empty-string sentinels this used to pass for a config with no OAuth client
780
954
  this.calcomOAuth = calcomOAuthFactory((_config_factoryConfig = config.factoryConfig) !== null && _config_factoryConfig !== void 0 ? _config_factoryConfig : {})({
781
- accessTokenCache: accessTokenCache,
782
- clientId: clientId !== null && clientId !== void 0 ? clientId : '',
783
- clientSecret: clientSecret !== null && clientSecret !== void 0 ? clientSecret : '',
784
- refreshToken: refreshToken,
785
- apiKey: apiKey
955
+ client: clientId && clientSecret ? {
956
+ clientId: clientId,
957
+ clientSecret: clientSecret
958
+ } : undefined,
959
+ defaultAuth: calcomAuthCredentialFromValues({
960
+ apiKey: apiKey,
961
+ refreshToken: refreshToken,
962
+ accessTokenCache: accessTokenCache
963
+ })
786
964
  });
787
965
  }
788
966
  _create_class$5(CalcomOAuthApi, [
@@ -803,23 +981,80 @@ var CalcomOAuthApi = /*#__PURE__*/ function() {
803
981
  return exchangeAuthorizationCode(this.oauthContext);
804
982
  }
805
983
  },
984
+ {
985
+ key: "exchangeAuthorizationCodeToAccessToken",
986
+ value: /**
987
+ * Exchanges an OAuth authorization code and maps the response to a {@link CalcomAccessToken}.
988
+ *
989
+ * The returned `refreshToken` is the one to persist: Cal.com rotates refresh tokens on every use.
990
+ *
991
+ * @param input - The authorization code and the exact redirect URI it was issued for.
992
+ * @returns The exchanged access token.
993
+ */ function exchangeAuthorizationCodeToAccessToken(input) {
994
+ return _async_to_generator$2(function() {
995
+ var response;
996
+ return _ts_generator$2(this, function(_state) {
997
+ switch(_state.label){
998
+ case 0:
999
+ return [
1000
+ 4,
1001
+ this.exchangeAuthorizationCode(input)
1002
+ ];
1003
+ case 1:
1004
+ response = _state.sent();
1005
+ return [
1006
+ 2,
1007
+ calcomAccessTokenFromTokenResponse(response)
1008
+ ];
1009
+ }
1010
+ });
1011
+ }).call(this);
1012
+ }
1013
+ },
806
1014
  {
807
1015
  /**
808
1016
  * Retrieves an access token for a specific user using their refresh token.
809
1017
  *
810
- * @param input - Contains the user's refresh token and optional access token cache.
811
- * @param input.refreshToken - The user's OAuth refresh token.
812
- * @param input.userAccessTokenCache - Optional cache to store/retrieve the user's access token.
1018
+ * @param credential - The user's refresh token credential, with the cache scoped to that grant.
813
1019
  * @returns Promise resolving to the user's CalcomAccessToken.
814
1020
  */ key: "userAccessToken",
815
- value: function userAccessToken(input) {
816
- var factory = this.oauthContext.makeUserAccessTokenFactory(input);
817
- return factory();
1021
+ value: function userAccessToken(credential) {
1022
+ return this.userAccessTokenFactory(credential)();
1023
+ }
1024
+ },
1025
+ {
1026
+ /**
1027
+ * Returns the CalcomAccessTokenFactory for a user's credential.
1028
+ *
1029
+ * A fresh factory on every call: its in-memory tier lives only as long as the returned factory, so
1030
+ * one caller's tokens are never visible to the next. Durable sharing is the access token cache's
1031
+ * job — see {@link cacheForKey}.
1032
+ *
1033
+ * @param credential - The user's refresh token credential.
1034
+ * @returns The CalcomAccessTokenFactory for that credential.
1035
+ */ key: "userAccessTokenFactory",
1036
+ value: function userAccessTokenFactory(credential) {
1037
+ return this.oauthContext.makeAccessTokenFactory(credential);
818
1038
  }
819
1039
  },
820
1040
  {
821
1041
  /**
822
- * Returns a per-user CalcomAccessTokenCache derived from the refresh token (md5 hashed as the file key).
1042
+ * Returns a per-user CalcomAccessTokenCache for a stable, caller-owned key.
1043
+ * Returns undefined if the cache service does not support keyed caching.
1044
+ *
1045
+ * Preferred over {@link cacheForRefreshToken}, whose key changes as Cal.com rotates the token.
1046
+ *
1047
+ * @param key - A stable key identifying the user, such as their user or profile id.
1048
+ * @returns A per-user access token cache, or undefined if not supported.
1049
+ */ key: "cacheForKey",
1050
+ value: function cacheForKey(key) {
1051
+ var _this_cacheService_cacheForKey, _this_cacheService;
1052
+ return (_this_cacheService_cacheForKey = (_this_cacheService = this.cacheService).cacheForKey) === null || _this_cacheService_cacheForKey === void 0 ? void 0 : _this_cacheService_cacheForKey.call(_this_cacheService, key);
1053
+ }
1054
+ },
1055
+ {
1056
+ /**
1057
+ * Returns a per-user CalcomAccessTokenCache derived from a hash of the refresh token.
823
1058
  * Returns undefined if the cache service does not support per-user caching.
824
1059
  *
825
1060
  * @param refreshToken - The user's OAuth refresh token used to derive the cache key.
@@ -1088,7 +1323,7 @@ function _object_spread_props$1(target, source) {
1088
1323
  * resolved from the cache service using an md5 hash of the refresh token as the key.
1089
1324
  * This ensures tokens persist across requests and server restarts without collisions.
1090
1325
  *
1091
- * @param input - The user context factory input containing the refresh token and optional cache.
1326
+ * @param credential - The user's refresh token credential, with an optional cache scoped to that grant.
1092
1327
  * @returns A new CalcomApiContextInstance scoped to the user.
1093
1328
  *
1094
1329
  * @example
@@ -1105,16 +1340,13 @@ function _object_spread_props$1(target, source) {
1105
1340
  * });
1106
1341
  * ```
1107
1342
  */ key: "makeUserContextInstance",
1108
- value: function makeUserContextInstance(input) {
1109
- var contextInput = _object_spread$1({}, input);
1110
- // Auto-resolve per-user cache from the refresh token if no explicit cache was given
1111
- if (!contextInput.accessTokenCache && contextInput.refreshToken) {
1112
- var userCache = this.calcomOAuthApi.cacheForRefreshToken(contextInput.refreshToken);
1113
- if (userCache) {
1114
- contextInput.accessTokenCache = userCache;
1115
- }
1116
- }
1117
- var userContext = this.calcom.calcomServerContext.makeUserContext(contextInput);
1343
+ value: function makeUserContextInstance(credential) {
1344
+ var _credential_accessTokenCache;
1345
+ // auto-resolve a per-user cache from the refresh token when none was given
1346
+ var accessTokenCache = (_credential_accessTokenCache = credential.accessTokenCache) !== null && _credential_accessTokenCache !== void 0 ? _credential_accessTokenCache : this.calcomOAuthApi.cacheForRefreshToken(credential.refreshToken);
1347
+ var userContext = this.calcom.calcomServerContext.makeUserContext(_object_spread_props$1(_object_spread$1({}, credential), {
1348
+ accessTokenCache: accessTokenCache
1349
+ }));
1118
1350
  return this.makeContextInstance(userContext);
1119
1351
  }
1120
1352
  },
@@ -1134,11 +1366,11 @@ function _object_spread_props$1(target, source) {
1134
1366
  * Creates a raw {@link CalcomUserContext} from a refresh token, without wrapping in a {@link CalcomApiContextInstance}.
1135
1367
  * Prefer {@link makeUserContextInstance} unless you need direct context access.
1136
1368
  *
1137
- * @param input - The user context factory input containing the refresh token and optional cache.
1369
+ * @param credential - The user's refresh token credential, with the cache scoped to that grant.
1138
1370
  * @returns A CalcomUserContext for the given user.
1139
1371
  */ key: "makeUserContext",
1140
- value: function makeUserContext(input) {
1141
- return this.calcom.calcomServerContext.makeUserContext(input);
1372
+ value: function makeUserContext(credential) {
1373
+ return this.calcom.calcomServerContext.makeUserContext(credential);
1142
1374
  }
1143
1375
  }
1144
1376
  ]);
@@ -2137,4 +2369,4 @@ CalcomWebhookModule = __decorate([
2137
2369
  };
2138
2370
  }
2139
2371
 
2140
- export { CALCOM_API_KEY_CONFIG_KEY, CALCOM_CLIENT_ID_CONFIG_KEY, CALCOM_CLIENT_SECRET_CONFIG_KEY, CALCOM_REFRESH_TOKEN_CONFIG_KEY, CALCOM_SERVER_TOKEN_FILE_KEY, CALCOM_SERVICE_NAME, CALCOM_WEBHOOK_BOOKING_CANCELLED, CALCOM_WEBHOOK_BOOKING_CONFIRMED, CALCOM_WEBHOOK_BOOKING_CREATED, CALCOM_WEBHOOK_BOOKING_RESCHEDULED, CALCOM_WEBHOOK_SECRET_CONFIG_KEY, CalcomApi, CalcomApiContextInstance, CalcomOAuthAccessTokenCacheService, CalcomOAuthApi, CalcomOAuthServiceConfig, CalcomServiceConfig, CalcomWebhookController, CalcomWebhookModule, CalcomWebhookService, CalcomWebhookServiceConfig, DEFAULT_FILE_CALCOM_ACCESS_TOKEN_CACHE_DIR, appCalcomModuleMetadata, appCalcomOAuthModuleMetadata, appCalcomWebhookModuleMetadata, calcomEventHandlerConfigurerFactory, calcomEventHandlerFactory, calcomOAuthServiceConfigFactory, calcomRefreshTokenCacheKey, calcomServiceConfigFactory, calcomWebhookEvent, calcomWebhookEventVerifier, calcomWebhookServiceConfigFactory, fileCalcomOAuthAccessTokenCacheService, logMergeCalcomOAuthAccessTokenCacheServiceErrorFunction, memoryCalcomOAuthAccessTokenCacheService, mergeCalcomOAuthAccessTokenCacheServices };
2372
+ export { CALCOM_API_KEY_CONFIG_KEY, CALCOM_CLIENT_ID_CONFIG_KEY, CALCOM_CLIENT_SECRET_CONFIG_KEY, CALCOM_REFRESH_TOKEN_CONFIG_KEY, CALCOM_SERVER_TOKEN_FILE_KEY, CALCOM_SERVICE_NAME, CALCOM_WEBHOOK_BOOKING_CANCELLED, CALCOM_WEBHOOK_BOOKING_CONFIRMED, CALCOM_WEBHOOK_BOOKING_CREATED, CALCOM_WEBHOOK_BOOKING_RESCHEDULED, CALCOM_WEBHOOK_SECRET_CONFIG_KEY, CalcomApi, CalcomApiContextInstance, CalcomOAuthAccessTokenCacheService, CalcomOAuthApi, CalcomOAuthServiceConfig, CalcomServiceConfig, CalcomWebhookController, CalcomWebhookModule, CalcomWebhookService, CalcomWebhookServiceConfig, DEFAULT_FILE_CALCOM_ACCESS_TOKEN_CACHE_DIR, appCalcomModuleMetadata, appCalcomOAuthModuleMetadata, appCalcomWebhookModuleMetadata, calcomAccessTokenCacheFileKey, calcomEventHandlerConfigurerFactory, calcomEventHandlerFactory, calcomOAuthServiceConfigFactory, calcomRefreshTokenCacheKey, calcomServiceConfigFactory, calcomWebhookEvent, calcomWebhookEventVerifier, calcomWebhookServiceConfigFactory, fileCalcomOAuthAccessTokenCacheService, logMergeCalcomOAuthAccessTokenCacheServiceErrorFunction, memoryCalcomOAuthAccessTokenCacheService, mergeCalcomOAuthAccessTokenCacheServices };
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@dereekb/calcom/nestjs",
3
- "version": "13.32.0",
3
+ "version": "13.34.0",
4
4
  "peerDependencies": {
5
- "@dereekb/nestjs": "13.32.0",
6
- "@dereekb/rxjs": "13.32.0",
7
- "@dereekb/util": "13.32.0",
8
- "@dereekb/calcom": "13.32.0",
5
+ "@dereekb/nestjs": "13.34.0",
6
+ "@dereekb/rxjs": "13.34.0",
7
+ "@dereekb/util": "13.34.0",
8
+ "@dereekb/calcom": "13.34.0",
9
9
  "@nestjs/common": "^11.1.19",
10
10
  "@nestjs/config": "^4.0.4",
11
11
  "express": "^5.2.1"
@@ -1,5 +1,5 @@
1
1
  import { CalcomServiceConfig } from './calcom.config';
2
- import { type Calcom, type CalcomContext, type CalcomServerContext, type CalcomUserContext, type CalcomUserContextFactoryInput } from '@dereekb/calcom';
2
+ import { type Calcom, type CalcomContext, type CalcomServerContext, type CalcomUserContext, type CalcomRefreshTokenCredential } from '@dereekb/calcom';
3
3
  import { CalcomOAuthApi } from '../oauth';
4
4
  /**
5
5
  * Injectable NestJS service that provides access to the Cal.com API.
@@ -50,7 +50,7 @@ export declare class CalcomApi {
50
50
  * resolved from the cache service using an md5 hash of the refresh token as the key.
51
51
  * This ensures tokens persist across requests and server restarts without collisions.
52
52
  *
53
- * @param input - The user context factory input containing the refresh token and optional cache.
53
+ * @param credential - The user's refresh token credential, with an optional cache scoped to that grant.
54
54
  * @returns A new CalcomApiContextInstance scoped to the user.
55
55
  *
56
56
  * @example
@@ -67,7 +67,7 @@ export declare class CalcomApi {
67
67
  * });
68
68
  * ```
69
69
  */
70
- makeUserContextInstance(input: CalcomUserContextFactoryInput): CalcomApiContextInstance;
70
+ makeUserContextInstance(credential: CalcomRefreshTokenCredential): CalcomApiContextInstance;
71
71
  /**
72
72
  * Creates a {@link CalcomApiContextInstance} from any {@link CalcomContext}.
73
73
  *
@@ -79,10 +79,10 @@ export declare class CalcomApi {
79
79
  * Creates a raw {@link CalcomUserContext} from a refresh token, without wrapping in a {@link CalcomApiContextInstance}.
80
80
  * Prefer {@link makeUserContextInstance} unless you need direct context access.
81
81
  *
82
- * @param input - The user context factory input containing the refresh token and optional cache.
82
+ * @param credential - The user's refresh token credential, with the cache scoped to that grant.
83
83
  * @returns A CalcomUserContext for the given user.
84
84
  */
85
- makeUserContext(input: CalcomUserContextFactoryInput): CalcomUserContext;
85
+ makeUserContext(credential: CalcomRefreshTokenCredential): CalcomUserContext;
86
86
  }
87
87
  /**
88
88
  * Wraps a {@link CalcomContext} (server or user) and exposes all authenticated Cal.com API
@@ -1,4 +1,4 @@
1
- import { type CalcomAccessTokenCache, type CalcomOAuth, type CalcomOAuthContext, type CalcomRefreshToken } from '@dereekb/calcom';
1
+ import { type CalcomAccessToken, type CalcomAccessTokenCache, type CalcomAccessTokenCacheKey, type CalcomAccessTokenFactory, type CalcomOAuth, type CalcomOAuthContext, type CalcomOAuthExchangeAuthorizationCodeInput, type CalcomRefreshToken, type CalcomRefreshTokenCredential } from '@dereekb/calcom';
2
2
  import { type Maybe } from '@dereekb/util';
3
3
  import { CalcomOAuthServiceConfig } from './oauth.config';
4
4
  import { CalcomOAuthAccessTokenCacheService } from './oauth.service';
@@ -13,21 +13,46 @@ export declare class CalcomOAuthApi {
13
13
  *
14
14
  * @returns Function to exchange an OAuth authorization code for tokens.
15
15
  */
16
- get exchangeAuthorizationCode(): (input: import("@dereekb/calcom").CalcomOAuthExchangeAuthorizationCodeInput) => Promise<import("@dereekb/calcom").CalcomOAuthTokenResponse>;
16
+ get exchangeAuthorizationCode(): (input: CalcomOAuthExchangeAuthorizationCodeInput) => Promise<import("@dereekb/calcom").CalcomOAuthTokenResponse>;
17
+ /**
18
+ * Exchanges an OAuth authorization code and maps the response to a {@link CalcomAccessToken}.
19
+ *
20
+ * The returned `refreshToken` is the one to persist: Cal.com rotates refresh tokens on every use.
21
+ *
22
+ * @param input - The authorization code and the exact redirect URI it was issued for.
23
+ * @returns The exchanged access token.
24
+ */
25
+ exchangeAuthorizationCodeToAccessToken(input: CalcomOAuthExchangeAuthorizationCodeInput): Promise<CalcomAccessToken>;
17
26
  /**
18
27
  * Retrieves an access token for a specific user using their refresh token.
19
28
  *
20
- * @param input - Contains the user's refresh token and optional access token cache.
21
- * @param input.refreshToken - The user's OAuth refresh token.
22
- * @param input.userAccessTokenCache - Optional cache to store/retrieve the user's access token.
29
+ * @param credential - The user's refresh token credential, with the cache scoped to that grant.
23
30
  * @returns Promise resolving to the user's CalcomAccessToken.
24
31
  */
25
- userAccessToken(input: {
26
- refreshToken: string;
27
- userAccessTokenCache?: Maybe<CalcomAccessTokenCache>;
28
- }): Promise<import("@dereekb/calcom").CalcomAccessToken>;
32
+ userAccessToken(credential: CalcomRefreshTokenCredential): Promise<CalcomAccessToken>;
33
+ /**
34
+ * Returns the CalcomAccessTokenFactory for a user's credential.
35
+ *
36
+ * A fresh factory on every call: its in-memory tier lives only as long as the returned factory, so
37
+ * one caller's tokens are never visible to the next. Durable sharing is the access token cache's
38
+ * job — see {@link cacheForKey}.
39
+ *
40
+ * @param credential - The user's refresh token credential.
41
+ * @returns The CalcomAccessTokenFactory for that credential.
42
+ */
43
+ userAccessTokenFactory(credential: CalcomRefreshTokenCredential): CalcomAccessTokenFactory;
44
+ /**
45
+ * Returns a per-user CalcomAccessTokenCache for a stable, caller-owned key.
46
+ * Returns undefined if the cache service does not support keyed caching.
47
+ *
48
+ * Preferred over {@link cacheForRefreshToken}, whose key changes as Cal.com rotates the token.
49
+ *
50
+ * @param key - A stable key identifying the user, such as their user or profile id.
51
+ * @returns A per-user access token cache, or undefined if not supported.
52
+ */
53
+ cacheForKey(key: CalcomAccessTokenCacheKey): Maybe<CalcomAccessTokenCache>;
29
54
  /**
30
- * Returns a per-user CalcomAccessTokenCache derived from the refresh token (md5 hashed as the file key).
55
+ * Returns a per-user CalcomAccessTokenCache derived from a hash of the refresh token.
31
56
  * Returns undefined if the cache service does not support per-user caching.
32
57
  *
33
58
  * @param refreshToken - The user's OAuth refresh token used to derive the cache key.