@dereekb/firebase-server 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.
Files changed (79) hide show
  1. package/calcom/index.cjs.default.js +1 -0
  2. package/calcom/index.cjs.js +1451 -0
  3. package/calcom/index.cjs.mjs +2 -0
  4. package/calcom/index.d.ts +1 -0
  5. package/calcom/index.esm.js +1437 -0
  6. package/calcom/package.json +29 -0
  7. package/calcom/src/index.d.ts +1 -0
  8. package/calcom/src/lib/calcom.oauth.connection.cache.d.ts +49 -0
  9. package/calcom/src/lib/calcom.oauth.connection.config.d.ts +75 -0
  10. package/calcom/src/lib/calcom.oauth.connection.context.d.ts +84 -0
  11. package/calcom/src/lib/calcom.oauth.connection.controller.d.ts +18 -0
  12. package/calcom/src/lib/calcom.oauth.connection.module.d.ts +55 -0
  13. package/calcom/src/lib/calcom.oauth.connection.service.d.ts +33 -0
  14. package/calcom/src/lib/index.d.ts +6 -0
  15. package/discord/index.cjs.default.js +1 -0
  16. package/discord/index.cjs.js +761 -0
  17. package/discord/index.cjs.mjs +2 -0
  18. package/discord/index.d.ts +1 -0
  19. package/discord/index.esm.js +753 -0
  20. package/discord/package.json +29 -0
  21. package/discord/src/index.d.ts +1 -0
  22. package/discord/src/lib/discord.oauth.connection.config.d.ts +69 -0
  23. package/discord/src/lib/discord.oauth.connection.controller.d.ts +18 -0
  24. package/discord/src/lib/discord.oauth.connection.module.d.ts +39 -0
  25. package/discord/src/lib/discord.oauth.connection.service.d.ts +43 -0
  26. package/discord/src/lib/index.d.ts +4 -0
  27. package/index.cjs.js +42 -9
  28. package/index.esm.js +42 -9
  29. package/mailgun/package.json +9 -9
  30. package/mcp/package.json +11 -11
  31. package/model/index.cjs.js +4243 -855
  32. package/model/index.esm.js +4183 -862
  33. package/model/package.json +10 -9
  34. package/model/src/lib/index.d.ts +2 -0
  35. package/model/src/lib/system/index.d.ts +2 -0
  36. package/model/src/lib/system/system.private.d.ts +63 -0
  37. package/model/src/lib/system/system.private.module.d.ts +70 -0
  38. package/model/src/lib/userexternalconnection/index.d.ts +8 -0
  39. package/model/src/lib/userexternalconnection/oauth/index.d.ts +7 -0
  40. package/model/src/lib/userexternalconnection/oauth/userexternalconnection.oauth.config.d.ts +110 -0
  41. package/model/src/lib/userexternalconnection/oauth/userexternalconnection.oauth.controller.d.ts +68 -0
  42. package/model/src/lib/userexternalconnection/oauth/userexternalconnection.oauth.error.d.ts +29 -0
  43. package/model/src/lib/userexternalconnection/oauth/userexternalconnection.oauth.refresh.d.ts +24 -0
  44. package/model/src/lib/userexternalconnection/oauth/userexternalconnection.oauth.registry.d.ts +54 -0
  45. package/model/src/lib/userexternalconnection/oauth/userexternalconnection.oauth.service.d.ts +216 -0
  46. package/model/src/lib/userexternalconnection/oauth/userexternalconnection.oauth.state.d.ts +114 -0
  47. package/model/src/lib/userexternalconnection/userexternalconnection.accessor.service.d.ts +111 -0
  48. package/model/src/lib/userexternalconnection/userexternalconnection.action.server.d.ts +172 -0
  49. package/model/src/lib/userexternalconnection/userexternalconnection.error.d.ts +44 -0
  50. package/model/src/lib/userexternalconnection/userexternalconnection.module.d.ts +129 -0
  51. package/model/src/lib/userexternalconnection/userexternalconnection.private.d.ts +192 -0
  52. package/model/src/lib/userexternalconnection/userexternalconnection.reader.service.d.ts +157 -0
  53. package/model/src/lib/userexternalconnection/userexternalconnection.refresh.service.d.ts +46 -0
  54. package/oidc/index.cjs.js +104 -78
  55. package/oidc/index.esm.js +104 -78
  56. package/oidc/package.json +10 -10
  57. package/package.json +24 -10
  58. package/src/lib/env/env.config.d.ts +15 -0
  59. package/src/lib/env/env.service.d.ts +7 -0
  60. package/src/lib/firestore/snapshot/snapshot.field.encrypt.d.ts +21 -2
  61. package/src/lib/nest/env/env.service.d.ts +1 -0
  62. package/test/index.cjs.js +14 -2
  63. package/test/index.esm.js +15 -3
  64. package/test/package.json +11 -11
  65. package/test/src/lib/firebase/firebase.admin.auth.d.ts +1 -1
  66. package/twilio/package.json +8 -8
  67. package/zoho/README.md +38 -0
  68. package/zoho/index.cjs.js +1418 -64
  69. package/zoho/index.esm.js +1401 -67
  70. package/zoho/package.json +13 -9
  71. package/zoho/src/lib/index.d.ts +6 -0
  72. package/zoho/src/lib/zoho.accounts.firebase.d.ts +10 -3
  73. package/zoho/src/lib/zoho.accounts.firebase.module.d.ts +51 -0
  74. package/zoho/src/lib/zoho.accounts.firebase.system.d.ts +51 -8
  75. package/zoho/src/lib/zoho.oauth.connection.cache.d.ts +45 -0
  76. package/zoho/src/lib/zoho.oauth.connection.config.d.ts +80 -0
  77. package/zoho/src/lib/zoho.oauth.connection.controller.d.ts +18 -0
  78. package/zoho/src/lib/zoho.oauth.connection.module.d.ts +43 -0
  79. package/zoho/src/lib/zoho.oauth.connection.service.d.ts +107 -0
package/zoho/index.esm.js CHANGED
@@ -1,48 +1,112 @@
1
- import { firestoreSubObject, firestoreDate, firestoreNumber, firestoreString, firestoreObjectArray } from '@dereekb/firebase';
2
- import { isPast, filterUniqueFunction } from '@dereekb/util';
1
+ import { firestoreSubObject, firestoreDate, firestoreNumber, firestoreString, firestoreObjectArray, ZOHO_USER_EXTERNAL_CONNECTION_PROVIDER_TYPE } from '@dereekb/firebase';
2
+ import { firestoreEncryptedField, FirebaseServerEnvService } from '@dereekb/firebase-server';
3
+ import { isPast, filterUniqueFunction, MS_IN_SECOND } from '@dereekb/util';
4
+ import { isValidAES256GCMEncryptionSecret } from '@dereekb/nestjs';
5
+ import { ZOHO_ACCOUNTS_PROFILE_READ_SCOPE, zohoAccountsConfigApiUrl, zohoAccountsAuthorizeUrlFactory, zohoOAuthScopesFromScopeString, zohoAccountsApiUrlKeyForApiUrl, ZOHO_ACCOUNTS_API_URLS, ZOHO_OAUTH_SCOPE_DELIMITER } from '@dereekb/zoho';
6
+ import { userExternalConnectionOAuthControllerPath, userExternalConnectionOAuthRoutesForGlobalRouteExclude, userExternalConnectionOAuthServiceConfigFactory, UserExternalConnectionOAuthServiceConfig, UserExternalConnectionStateCoder, UserExternalConnectionServerActions, UserExternalConnectionAccessor, AbstractUserExternalConnectionOAuthService, mergeRefreshedUserExternalConnectionCredentials, AbstractUserExternalConnectionOAuthController } from '@dereekb/firebase-server/model';
7
+ import { safeToJsDate } from '@dereekb/date';
8
+ import { Injectable, Inject, Controller } from '@nestjs/common';
9
+ import { ZohoAccountsOAuthApi } from '@dereekb/zoho/nestjs';
10
+ import { ConfigModule } from '@nestjs/config';
3
11
 
4
12
  /**
5
13
  * {@link SystemState} type identifier for storing Zoho access tokens in Firestore.
6
14
  */ var ZOHO_ACCESS_TOKEN_SYSTEM_STATE_TYPE = 'zoho_access_token';
7
- var zohoAccessTokenSystemStateEmbeddedTokenConverter = firestoreSubObject({
8
- objectField: {
9
- fields: {
10
- key: firestoreString(),
11
- accessToken: firestoreString(),
12
- scope: firestoreString(),
13
- apiDomain: firestoreString(),
14
- expiresIn: firestoreNumber({
15
- default: 3600
16
- }),
17
- expiresAt: firestoreDate()
15
+ /**
16
+ * Creates the embedded-token converter, encrypting the `accessToken` at rest.
17
+ *
18
+ * This is a factory rather than a module-level const because `firestoreEncryptedField` resolves and
19
+ * validates the encryption key eagerly at construction — the secret must be known at runtime.
20
+ *
21
+ * ONLY `accessToken` is encrypted, deliberately. `firestoreEncryptedField` round-trips through
22
+ * `JSON.stringify`/`JSON.parse`, so anything placed inside the encrypted blob loses its type — and
23
+ * `expiresAt` is a `Date`. Encrypting the token string alone keeps every date outside the blob,
24
+ * which is what lets {@link zohoAccessTokenSystemStateDataConverterFactory} keep filtering expired
25
+ * entries without having to decrypt them first. Do not "improve" this by encrypting the whole
26
+ * token object or the `tokens` array.
27
+ *
28
+ * Accepted trade-off: `key`, `scope`, `apiDomain`, `expiresIn` and `expiresAt` remain plaintext at
29
+ * rest. None of them is a credential.
30
+ *
31
+ * @param config - The encryption configuration.
32
+ * @returns The embedded token field converter.
33
+ */ function zohoAccessTokenSystemStateEmbeddedTokenConverterFactory(config) {
34
+ return firestoreSubObject({
35
+ objectField: {
36
+ fields: {
37
+ key: firestoreString(),
38
+ accessToken: firestoreEncryptedField({
39
+ secret: config.encryptionSecret,
40
+ default: '',
41
+ // This is a cache of ~1h tokens, so an undecryptable entry is a cache MISS, not an error.
42
+ // The empty sentinel is dropped by the `tokens` filter, and the next Zoho call re-mints.
43
+ // This is also what makes a rotated secret survivable here (unlike uecp/jwks).
44
+ onDecodeFailure: function onDecodeFailure() {
45
+ return '';
46
+ }
47
+ }),
48
+ scope: firestoreString(),
49
+ apiDomain: firestoreString(),
50
+ expiresIn: firestoreNumber({
51
+ default: 3600
52
+ }),
53
+ expiresAt: firestoreDate()
54
+ }
18
55
  }
19
- }
20
- });
56
+ });
57
+ }
21
58
  /**
22
59
  * Firestore field converter for {@link ZohoAccessTokenSystemStateData}.
23
60
  *
24
61
  * Automatically filters out expired tokens on read and enforces uniqueness by service key.
25
62
  * Must be registered in the app's {@link SystemStateStoredDataConverterMap} under
26
63
  * the {@link ZOHO_ACCESS_TOKEN_SYSTEM_STATE_TYPE} key.
27
- */ var zohoAccessTokenSystemStateDataConverter = firestoreSubObject({
28
- objectField: {
29
- fields: {
30
- tokens: firestoreObjectArray({
31
- firestoreField: zohoAccessTokenSystemStateEmbeddedTokenConverter,
32
- filterUnique: filterUniqueFunction(function(x) {
33
- return x.key;
64
+ */ /**
65
+ * Builds the {@link ZohoAccessTokenSystemStateData} converter around a given embedded-token converter.
66
+ *
67
+ * Shared by the encrypted factory and the deprecated plaintext const so the array's expiry filter and
68
+ * per-key dedup behavior can only ever be defined once.
69
+ *
70
+ * @param embeddedTokenConverter - The converter for each entry in the `tokens` array.
71
+ * @returns The stored-data field converter.
72
+ */ function zohoAccessTokenSystemStateDataConverterForEmbeddedTokenConverter(embeddedTokenConverter) {
73
+ return firestoreSubObject({
74
+ objectField: {
75
+ fields: {
76
+ tokens: firestoreObjectArray({
77
+ firestoreField: embeddedTokenConverter,
78
+ filterUnique: filterUniqueFunction(function(x) {
79
+ return x.key;
80
+ }),
81
+ // `firestoreObjectArray` maps BEFORE it filters, so this runs on already-decoded entries.
82
+ // The `accessToken` check is what drops an entry whose decryption failed (onDecodeFailure
83
+ // leaves an empty string behind) — without it such an entry would surface as a token with
84
+ // an empty secret rather than as a cache miss.
85
+ filter: function filter(x) {
86
+ return Boolean(x === null || x === void 0 ? void 0 : x.accessToken) && ((x === null || x === void 0 ? void 0 : x.expiresAt) ? !isPast(x.expiresAt) : true // filter out empty/expired values
87
+ );
88
+ }
34
89
  }),
35
- filter: function filter(x) {
36
- return (x === null || x === void 0 ? void 0 : x.expiresAt) ? !isPast(x.expiresAt) : true // filter out expired values or values that have no expiration
37
- ;
38
- }
39
- }),
40
- lat: firestoreDate({
41
- saveDefaultAsNow: true
42
- })
90
+ lat: firestoreDate({
91
+ saveDefaultAsNow: true
92
+ })
93
+ }
43
94
  }
44
- }
45
- });
95
+ });
96
+ }
97
+ /**
98
+ * Creates the {@link ZohoAccessTokenSystemStateData} converter, encrypting each token's
99
+ * `accessToken` at rest.
100
+ *
101
+ * Register the result in a SERVER-ONLY converter map under {@link ZOHO_ACCESS_TOKEN_SYSTEM_STATE_TYPE} —
102
+ * see `systemStatePrivateFirestoreCollection()` in `@dereekb/firebase-server/model`. It must never be
103
+ * registered in an app's client-shared `SystemStateStoredDataConverterMap`.
104
+ *
105
+ * @param config - The encryption configuration.
106
+ * @returns The stored-data field converter.
107
+ */ function zohoAccessTokenSystemStateDataConverterFactory(config) {
108
+ return zohoAccessTokenSystemStateDataConverterForEmbeddedTokenConverter(zohoAccessTokenSystemStateEmbeddedTokenConverterFactory(config));
109
+ }
46
110
  /**
47
111
  * Loads the {@link SystemStateDocument} that stores {@link ZohoAccessTokenSystemStateData},
48
112
  * using {@link ZOHO_ACCESS_TOKEN_SYSTEM_STATE_TYPE} as the document ID.
@@ -58,16 +122,38 @@ var zohoAccessTokenSystemStateEmbeddedTokenConverter = firestoreSubObject({
58
122
  */ function loadZohoAccessTokenSystemState(accessor) {
59
123
  return accessor.loadDocumentForId(ZOHO_ACCESS_TOKEN_SYSTEM_STATE_TYPE);
60
124
  }
125
+ // COMPAT: Deprecated aliases
126
+ /**
127
+ * @deprecated stores the access token in PLAINTEXT. Use
128
+ * {@link zohoAccessTokenSystemStateEmbeddedTokenConverterFactory} instead, which encrypts it at rest.
129
+ */ var zohoAccessTokenSystemStateEmbeddedTokenConverter = firestoreSubObject({
130
+ objectField: {
131
+ fields: {
132
+ key: firestoreString(),
133
+ accessToken: firestoreString(),
134
+ scope: firestoreString(),
135
+ apiDomain: firestoreString(),
136
+ expiresIn: firestoreNumber({
137
+ default: 3600
138
+ }),
139
+ expiresAt: firestoreDate()
140
+ }
141
+ }
142
+ });
143
+ /**
144
+ * @deprecated stores access tokens in PLAINTEXT. Use {@link zohoAccessTokenSystemStateDataConverterFactory}
145
+ * instead, and register it on a server-only SystemStatePrivate collection.
146
+ */ var zohoAccessTokenSystemStateDataConverter = zohoAccessTokenSystemStateDataConverterForEmbeddedTokenConverter(zohoAccessTokenSystemStateEmbeddedTokenConverter);
61
147
 
62
- function _array_like_to_array(arr, len) {
148
+ function _array_like_to_array$1(arr, len) {
63
149
  if (len == null || len > arr.length) len = arr.length;
64
150
  for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
65
151
  return arr2;
66
152
  }
67
- function _array_without_holes(arr) {
68
- if (Array.isArray(arr)) return _array_like_to_array(arr);
153
+ function _array_without_holes$1(arr) {
154
+ if (Array.isArray(arr)) return _array_like_to_array$1(arr);
69
155
  }
70
- function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
156
+ function asyncGeneratorStep$2(gen, resolve, reject, _next, _throw, key, arg) {
71
157
  try {
72
158
  var info = gen[key](arg);
73
159
  var value = info.value;
@@ -81,22 +167,22 @@ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
81
167
  Promise.resolve(value).then(_next, _throw);
82
168
  }
83
169
  }
84
- function _async_to_generator(fn) {
170
+ function _async_to_generator$2(fn) {
85
171
  return function() {
86
172
  var self = this, args = arguments;
87
173
  return new Promise(function(resolve, reject) {
88
174
  var gen = fn.apply(self, args);
89
175
  function _next(value) {
90
- asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
176
+ asyncGeneratorStep$2(gen, resolve, reject, _next, _throw, "next", value);
91
177
  }
92
178
  function _throw(err) {
93
- asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
179
+ asyncGeneratorStep$2(gen, resolve, reject, _next, _throw, "throw", err);
94
180
  }
95
181
  _next(undefined);
96
182
  });
97
183
  };
98
184
  }
99
- function _define_property(obj, key, value) {
185
+ function _define_property$5(obj, key, value) {
100
186
  if (key in obj) {
101
187
  Object.defineProperty(obj, key, {
102
188
  value: value,
@@ -109,13 +195,13 @@ function _define_property(obj, key, value) {
109
195
  }
110
196
  return obj;
111
197
  }
112
- function _iterable_to_array(iter) {
198
+ function _iterable_to_array$1(iter) {
113
199
  if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
114
200
  }
115
- function _non_iterable_spread() {
201
+ function _non_iterable_spread$1() {
116
202
  throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
117
203
  }
118
- function _object_spread(target) {
204
+ function _object_spread$2(target) {
119
205
  for(var i = 1; i < arguments.length; i++){
120
206
  var source = arguments[i] != null ? arguments[i] : {};
121
207
  var ownKeys = Object.keys(source);
@@ -125,12 +211,12 @@ function _object_spread(target) {
125
211
  }));
126
212
  }
127
213
  ownKeys.forEach(function(key) {
128
- _define_property(target, key, source[key]);
214
+ _define_property$5(target, key, source[key]);
129
215
  });
130
216
  }
131
217
  return target;
132
218
  }
133
- function ownKeys(object, enumerableOnly) {
219
+ function ownKeys$2(object, enumerableOnly) {
134
220
  var keys = Object.keys(object);
135
221
  if (Object.getOwnPropertySymbols) {
136
222
  var symbols = Object.getOwnPropertySymbols(object);
@@ -138,29 +224,29 @@ function ownKeys(object, enumerableOnly) {
138
224
  }
139
225
  return keys;
140
226
  }
141
- function _object_spread_props(target, source) {
227
+ function _object_spread_props$2(target, source) {
142
228
  source = source != null ? source : {};
143
229
  if (Object.getOwnPropertyDescriptors) {
144
230
  Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
145
231
  } else {
146
- ownKeys(Object(source)).forEach(function(key) {
232
+ ownKeys$2(Object(source)).forEach(function(key) {
147
233
  Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
148
234
  });
149
235
  }
150
236
  return target;
151
237
  }
152
- function _to_consumable_array(arr) {
153
- return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
238
+ function _to_consumable_array$1(arr) {
239
+ return _array_without_holes$1(arr) || _iterable_to_array$1(arr) || _unsupported_iterable_to_array$1(arr) || _non_iterable_spread$1();
154
240
  }
155
- function _unsupported_iterable_to_array(o, minLen) {
241
+ function _unsupported_iterable_to_array$1(o, minLen) {
156
242
  if (!o) return;
157
- if (typeof o === "string") return _array_like_to_array(o, minLen);
243
+ if (typeof o === "string") return _array_like_to_array$1(o, minLen);
158
244
  var n = Object.prototype.toString.call(o).slice(8, -1);
159
245
  if (n === "Object" && o.constructor) n = o.constructor.name;
160
246
  if (n === "Map" || n === "Set") return Array.from(n);
161
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
247
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$1(o, minLen);
162
248
  }
163
- function _ts_generator(thisArg, body) {
249
+ function _ts_generator$2(thisArg, body) {
164
250
  var f, y, t, _ = {
165
251
  label: 0,
166
252
  sent: function() {
@@ -266,12 +352,19 @@ function _ts_generator(thisArg, body) {
266
352
  * Tokens are stored in a single {@link SystemState} document (type {@link ZOHO_ACCESS_TOKEN_SYSTEM_STATE_TYPE})
267
353
  * and token updates/clears use Firestore transactions for concurrency safety.
268
354
  *
355
+ * The access token is a credential, so pass a SERVER-ONLY collection — a
356
+ * `systemStatePrivateFirestoreCollection()` from `@dereekb/firebase-server/model`, whose converter
357
+ * map registers {@link zohoAccessTokenSystemStateDataConverterFactory} and encrypts the token at
358
+ * rest. Passing an app's client-shared `systemStateCollection` still type-checks (for backwards
359
+ * compatibility) but requires the converter to be registered in the client-shared map, which drags
360
+ * `@dereekb/firebase-server` into browser builds.
361
+ *
269
362
  * @param systemStateCollection - The Firestore collection for system state documents.
270
363
  * @returns A cache service backed by Firestore system state documents.
271
364
  *
272
365
  * @example
273
366
  * ```ts
274
- * const cacheService = firebaseZohoAccountsAccessTokenCacheService(systemStateCollection);
367
+ * const cacheService = firebaseZohoAccountsAccessTokenCacheService(systemStatePrivateCollection);
275
368
  * const cache = cacheService.loadZohoAccessTokenCache('my-zoho-service');
276
369
  * const token = await cache.loadCachedToken();
277
370
  * ```
@@ -281,9 +374,9 @@ function _ts_generator(thisArg, body) {
281
374
  loadZohoAccessTokenCache: function loadZohoAccessTokenCache(serviceKey) {
282
375
  var cache = {
283
376
  loadCachedToken: function loadCachedToken() {
284
- return _async_to_generator(function() {
377
+ return _async_to_generator$2(function() {
285
378
  var document, existingData, result, tokensArray;
286
- return _ts_generator(this, function(_state) {
379
+ return _ts_generator$2(this, function(_state) {
287
380
  switch(_state.label){
288
381
  case 0:
289
382
  document = loadZohoAccessTokenSystemState(systemStateDocumentAccessor);
@@ -309,17 +402,17 @@ function _ts_generator(thisArg, body) {
309
402
  })();
310
403
  },
311
404
  updateCachedToken: function updateCachedToken(accessToken) {
312
- return _async_to_generator(function() {
313
- return _ts_generator(this, function(_state) {
405
+ return _async_to_generator$2(function() {
406
+ return _ts_generator$2(this, function(_state) {
314
407
  switch(_state.label){
315
408
  case 0:
316
409
  // run in a transaction
317
410
  return [
318
411
  4,
319
412
  systemStateCollection.firestoreContext.runTransaction(function(transaction) {
320
- return _async_to_generator(function() {
413
+ return _async_to_generator$2(function() {
321
414
  var _ref, documentInTransaction, existingData, existingTokens, tokens, templateOrUpdate;
322
- return _ts_generator(this, function(_state) {
415
+ return _ts_generator$2(this, function(_state) {
323
416
  switch(_state.label){
324
417
  case 0:
325
418
  documentInTransaction = loadZohoAccessTokenSystemState(systemStateCollection.documentAccessorForTransaction(transaction));
@@ -331,11 +424,11 @@ function _ts_generator(thisArg, body) {
331
424
  existingData = _state.sent();
332
425
  existingTokens = (_ref = existingData === null || existingData === void 0 ? void 0 : existingData.data.tokens) !== null && _ref !== void 0 ? _ref : [];
333
426
  tokens = // filter any potential old token for this service key
334
- _to_consumable_array(existingTokens.filter(function(x) {
427
+ _to_consumable_array$1(existingTokens.filter(function(x) {
335
428
  return x.key !== serviceKey;
336
429
  })).concat([
337
430
  // add the new token
338
- _object_spread_props(_object_spread({}, accessToken), {
431
+ _object_spread_props$2(_object_spread$2({}, accessToken), {
339
432
  key: serviceKey
340
433
  })
341
434
  ]);
@@ -386,16 +479,16 @@ function _ts_generator(thisArg, body) {
386
479
  })();
387
480
  },
388
481
  clearCachedToken: function clearCachedToken() {
389
- return _async_to_generator(function() {
390
- return _ts_generator(this, function(_state) {
482
+ return _async_to_generator$2(function() {
483
+ return _ts_generator$2(this, function(_state) {
391
484
  switch(_state.label){
392
485
  case 0:
393
486
  return [
394
487
  4,
395
488
  systemStateCollection.firestoreContext.runTransaction(function(transaction) {
396
- return _async_to_generator(function() {
489
+ return _async_to_generator$2(function() {
397
490
  var documentInTransaction, existingData, templateOrUpdate;
398
- return _ts_generator(this, function(_state) {
491
+ return _ts_generator$2(this, function(_state) {
399
492
  switch(_state.label){
400
493
  case 0:
401
494
  documentInTransaction = loadZohoAccessTokenSystemState(systemStateCollection.documentAccessorForTransaction(transaction));
@@ -447,4 +540,1245 @@ function _ts_generator(thisArg, body) {
447
540
  return service;
448
541
  }
449
542
 
450
- export { ZOHO_ACCESS_TOKEN_SYSTEM_STATE_TYPE, firebaseZohoAccountsAccessTokenCacheService, loadZohoAccessTokenSystemState, zohoAccessTokenSystemStateDataConverter, zohoAccessTokenSystemStateEmbeddedTokenConverter };
543
+ function _define_property$4(obj, key, value) {
544
+ if (key in obj) {
545
+ Object.defineProperty(obj, key, {
546
+ value: value,
547
+ enumerable: true,
548
+ configurable: true,
549
+ writable: true
550
+ });
551
+ } else {
552
+ obj[key] = value;
553
+ }
554
+ return obj;
555
+ }
556
+ // MARK: Environment Variable Keys
557
+ /**
558
+ * Environment variable name for the Zoho access token cache encryption secret
559
+ * (hex-encoded AES-256 key).
560
+ *
561
+ * There is NO key rotation — `firestoreEncryptedField` resolves and validates the key once at
562
+ * converter construction and closes over it. Unlike the `uecp` and `oidcJwksKey` secrets, however,
563
+ * rotating this one is SURVIVABLE: the Zoho converter supplies an `onDecodeFailure` handler, so
564
+ * every entry written under the old key simply degrades to a cache miss and the next Zoho call
565
+ * re-mints a token. Rotation costs one extra token request per service key, not an outage.
566
+ */ var ZOHO_ACCESS_TOKEN_ENCRYPTION_SECRET_ENV_KEY = 'ZOHO_ACCESS_TOKEN_ENCRYPTION_SECRET';
567
+ /**
568
+ * Deterministic secret used when running in a testing environment and no real secret is configured,
569
+ * so specs never need a live credential.
570
+ *
571
+ * Deliberately distinct from the OIDC JWKS and UserExternalConnection testing secrets so a leaked
572
+ * emulator blob is attributable. ("Zoho Access Token Cache Test Key", hex-encoded.)
573
+ */ var TESTING_ZOHO_ACCESS_TOKEN_ENCRYPTION_SECRET = '5a6f686f2041636365737320546f6b656e2043616368652054657374204b6579';
574
+ // MARK: Config
575
+ /**
576
+ * Reads the Zoho access token encryption secret from the environment.
577
+ *
578
+ * @param configService - The Nest config service used to read the encryption secret.
579
+ * @param envService - Used to detect a testing environment for the secret fallback.
580
+ * @returns The validated encryption secret.
581
+ * @throws {Error} When the configured secret is invalid outside a testing environment.
582
+ */ function zohoAccessTokenEncryptionSecretFactory(configService, envService) {
583
+ var _configService_get;
584
+ var encryptionSecret = (_configService_get = configService.get(ZOHO_ACCESS_TOKEN_ENCRYPTION_SECRET_ENV_KEY)) !== null && _configService_get !== void 0 ? _configService_get : '';
585
+ if (!isValidAES256GCMEncryptionSecret(encryptionSecret)) {
586
+ if (envService.isTestingEnv) {
587
+ encryptionSecret = TESTING_ZOHO_ACCESS_TOKEN_ENCRYPTION_SECRET;
588
+ } else {
589
+ throw new Error("zohoAccessTokenEncryptionSecretFactory: The secret provided by ".concat(ZOHO_ACCESS_TOKEN_ENCRYPTION_SECRET_ENV_KEY, " is not valid. Expected a 64-character hexadecimal string."));
590
+ }
591
+ }
592
+ return encryptionSecret;
593
+ }
594
+ // MARK: Converter Map Entry
595
+ /**
596
+ * Builds the converter map entry for the Zoho access token cache, for use in a SERVER-ONLY
597
+ * SystemState converter map.
598
+ *
599
+ * @param config - The encryption configuration.
600
+ * @returns A partial converter map containing only the Zoho access token entry.
601
+ *
602
+ * @example
603
+ * ```typescript
604
+ * const collections = systemStatePrivateFirestoreCollection({
605
+ * firestoreContext,
606
+ * converters: {
607
+ * ...zohoAccessTokenSystemStatePrivateConverterEntry({ encryptionSecret })
608
+ * }
609
+ * });
610
+ * ```
611
+ */ function zohoAccessTokenSystemStatePrivateConverterEntry(config) {
612
+ return _define_property$4({}, ZOHO_ACCESS_TOKEN_SYSTEM_STATE_TYPE, zohoAccessTokenSystemStateDataConverterFactory(config));
613
+ }
614
+
615
+ function _type_of$3(obj) {
616
+ "@swc/helpers - typeof";
617
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
618
+ }
619
+ function __decorate(decorators, target, key, desc) {
620
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
621
+ if ((typeof Reflect === "undefined" ? "undefined" : _type_of$3(Reflect)) === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
622
+ 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;
623
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
624
+ }
625
+ function __param(paramIndex, decorator) {
626
+ return function(target, key) {
627
+ decorator(target, key, paramIndex);
628
+ };
629
+ }
630
+ typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
631
+ var e = new Error(message);
632
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
633
+ };
634
+
635
+ function _assert_this_initialized$2(self) {
636
+ if (self === void 0) {
637
+ throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
638
+ }
639
+ return self;
640
+ }
641
+ function _call_super$2(_this, derived, args) {
642
+ derived = _get_prototype_of$2(derived);
643
+ return _possible_constructor_return$2(_this, _is_native_reflect_construct$2() ? Reflect.construct(derived, args || [], _get_prototype_of$2(_this).constructor) : derived.apply(_this, args));
644
+ }
645
+ function _class_call_check$2(instance, Constructor) {
646
+ if (!(instance instanceof Constructor)) {
647
+ throw new TypeError("Cannot call a class as a function");
648
+ }
649
+ }
650
+ function _define_property$3(obj, key, value) {
651
+ if (key in obj) {
652
+ Object.defineProperty(obj, key, {
653
+ value: value,
654
+ enumerable: true,
655
+ configurable: true,
656
+ writable: true
657
+ });
658
+ } else {
659
+ obj[key] = value;
660
+ }
661
+ return obj;
662
+ }
663
+ function _get_prototype_of$2(o) {
664
+ _get_prototype_of$2 = Object.setPrototypeOf ? Object.getPrototypeOf : function getPrototypeOf(o) {
665
+ return o.__proto__ || Object.getPrototypeOf(o);
666
+ };
667
+ return _get_prototype_of$2(o);
668
+ }
669
+ function _inherits$2(subClass, superClass) {
670
+ if (typeof superClass !== "function" && superClass !== null) {
671
+ throw new TypeError("Super expression must either be null or a function");
672
+ }
673
+ subClass.prototype = Object.create(superClass && superClass.prototype, {
674
+ constructor: {
675
+ value: subClass,
676
+ writable: true,
677
+ configurable: true
678
+ }
679
+ });
680
+ if (superClass) _set_prototype_of$2(subClass, superClass);
681
+ }
682
+ function _object_spread$1(target) {
683
+ for(var i = 1; i < arguments.length; i++){
684
+ var source = arguments[i] != null ? arguments[i] : {};
685
+ var ownKeys = Object.keys(source);
686
+ if (typeof Object.getOwnPropertySymbols === "function") {
687
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
688
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
689
+ }));
690
+ }
691
+ ownKeys.forEach(function(key) {
692
+ _define_property$3(target, key, source[key]);
693
+ });
694
+ }
695
+ return target;
696
+ }
697
+ function ownKeys$1(object, enumerableOnly) {
698
+ var keys = Object.keys(object);
699
+ if (Object.getOwnPropertySymbols) {
700
+ var symbols = Object.getOwnPropertySymbols(object);
701
+ keys.push.apply(keys, symbols);
702
+ }
703
+ return keys;
704
+ }
705
+ function _object_spread_props$1(target, source) {
706
+ source = source != null ? source : {};
707
+ if (Object.getOwnPropertyDescriptors) {
708
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
709
+ } else {
710
+ ownKeys$1(Object(source)).forEach(function(key) {
711
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
712
+ });
713
+ }
714
+ return target;
715
+ }
716
+ function _possible_constructor_return$2(self, call) {
717
+ if (call && (_type_of$2(call) === "object" || typeof call === "function")) {
718
+ return call;
719
+ }
720
+ return _assert_this_initialized$2(self);
721
+ }
722
+ function _set_prototype_of$2(o, p) {
723
+ _set_prototype_of$2 = Object.setPrototypeOf || function setPrototypeOf(o, p) {
724
+ o.__proto__ = p;
725
+ return o;
726
+ };
727
+ return _set_prototype_of$2(o, p);
728
+ }
729
+ function _type_of$2(obj) {
730
+ "@swc/helpers - typeof";
731
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
732
+ }
733
+ function _is_native_reflect_construct$2() {
734
+ try {
735
+ var result = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {}));
736
+ } catch (_) {}
737
+ return (_is_native_reflect_construct$2 = function() {
738
+ return !!result;
739
+ })();
740
+ }
741
+ /**
742
+ * Controller path the Zoho external-connection OAuth endpoints are mounted at.
743
+ *
744
+ * Derived from the framework's path factory, the same expression the redirect URI and the
745
+ * global-prefix exclusion are built from, so the three cannot drift apart.
746
+ */ var ZOHO_USER_EXTERNAL_CONNECTION_OAUTH_CONTROLLER_PATH = userExternalConnectionOAuthControllerPath(ZOHO_USER_EXTERNAL_CONNECTION_PROVIDER_TYPE);
747
+ /**
748
+ * Routes to exclude from an app's global API route prefix so the Zoho callback controller stays
749
+ * mounted at `/oauth/zoho/*`.
750
+ *
751
+ * Spread this into the `exclude` list of the app's `globalApiRoutePrefix` config, alongside
752
+ * `FIREBASE_SERVER_OIDC_ROUTES_FOR_GLOBAL_ROUTE_EXCLUDE`.
753
+ */ var ZOHO_USER_EXTERNAL_CONNECTION_OAUTH_ROUTES_FOR_GLOBAL_ROUTE_EXCLUDE = userExternalConnectionOAuthRoutesForGlobalRouteExclude(ZOHO_USER_EXTERNAL_CONNECTION_PROVIDER_TYPE);
754
+ /**
755
+ * The scopes requested when an app does not declare its own.
756
+ *
757
+ * Declared in code, deliberately NOT read from the environment: the set to request follows from what
758
+ * the integration actually does, so it belongs where it is reviewable.
759
+ *
760
+ * Least privilege for a connect that proves the handoff and labels the connection: read the
761
+ * authorizing user's Zoho identity, and nothing else. No `ZohoCRM.*` / `ZohoRecruit.*` scope is
762
+ * requested because the default integration makes no product API call — requesting one would be
763
+ * privilege the code never uses, which is the same error as under-requesting, in the other
764
+ * direction. An app that actually calls a Zoho product declares its own set on the module metadata,
765
+ * in code.
766
+ *
767
+ * Unlike Cal.com, Zoho does not pre-register scopes on the OAuth client, so nothing has to be
768
+ * registered in the API console to request this.
769
+ */ var DEFAULT_ZOHO_OAUTH_SCOPES = [
770
+ ZOHO_ACCOUNTS_PROFILE_READ_SCOPE
771
+ ];
772
+ /**
773
+ * Configuration for the {@link ZohoUserExternalConnectionOAuthService}.
774
+ *
775
+ * Extends the framework config with what is Zoho's own: which scopes to request, and which
776
+ * datacenter to authorize against.
777
+ */ var ZohoUserExternalConnectionOAuthServiceConfig = /*#__PURE__*/ function(UserExternalConnectionOAuthServiceConfig) {
778
+ _inherits$2(ZohoUserExternalConnectionOAuthServiceConfig, UserExternalConnectionOAuthServiceConfig);
779
+ function ZohoUserExternalConnectionOAuthServiceConfig() {
780
+ _class_call_check$2(this, ZohoUserExternalConnectionOAuthServiceConfig);
781
+ var _this;
782
+ _this = _call_super$2(this, ZohoUserExternalConnectionOAuthServiceConfig, arguments), _define_property$3(_this, "scopes", void 0), /**
783
+ * Datacenter to authorize against. Defaults to the api's configured one.
784
+ */ _define_property$3(_this, "accountsApiUrl", void 0);
785
+ return _this;
786
+ }
787
+ return ZohoUserExternalConnectionOAuthServiceConfig;
788
+ }(UserExternalConnectionOAuthServiceConfig);
789
+ /**
790
+ * Builds the Zoho connect flow's configuration from the app's configured origins.
791
+ *
792
+ * Nothing here is read from the environment as a value: the redirect URI is derived from the app's
793
+ * OAuth origin plus the mounted controller path, and the return URLs from the app URL plus
794
+ * code-declared paths. Registering Zoho therefore adds no deployment configuration beyond the client
795
+ * credentials the OAuth api already reads.
796
+ *
797
+ * @param config - The env service, the return paths, and the optional scope/datacenter overrides.
798
+ * @returns The validated service configuration.
799
+ */ function zohoUserExternalConnectionOAuthServiceConfigFactory(config) {
800
+ var envService = config.envService, successPath = config.successPath, failurePath = config.failurePath, scopes = config.scopes, accountsApiUrl = config.accountsApiUrl;
801
+ var baseConfig = userExternalConnectionOAuthServiceConfigFactory({
802
+ envService: envService,
803
+ providerType: ZOHO_USER_EXTERNAL_CONNECTION_PROVIDER_TYPE,
804
+ successPath: successPath,
805
+ failurePath: failurePath
806
+ });
807
+ return _object_spread_props$1(_object_spread$1({}, baseConfig), {
808
+ scopes: scopes !== null && scopes !== void 0 ? scopes : DEFAULT_ZOHO_OAUTH_SCOPES,
809
+ accountsApiUrl: accountsApiUrl
810
+ });
811
+ }
812
+
813
+ function _assert_this_initialized$1(self) {
814
+ if (self === void 0) {
815
+ throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
816
+ }
817
+ return self;
818
+ }
819
+ function asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, key, arg) {
820
+ try {
821
+ var info = gen[key](arg);
822
+ var value = info.value;
823
+ } catch (error) {
824
+ reject(error);
825
+ return;
826
+ }
827
+ if (info.done) {
828
+ resolve(value);
829
+ } else {
830
+ Promise.resolve(value).then(_next, _throw);
831
+ }
832
+ }
833
+ function _async_to_generator$1(fn) {
834
+ return function() {
835
+ var self = this, args = arguments;
836
+ return new Promise(function(resolve, reject) {
837
+ var gen = fn.apply(self, args);
838
+ function _next(value) {
839
+ asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, "next", value);
840
+ }
841
+ function _throw(err) {
842
+ asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, "throw", err);
843
+ }
844
+ _next(undefined);
845
+ });
846
+ };
847
+ }
848
+ function _call_super$1(_this, derived, args) {
849
+ derived = _get_prototype_of$1(derived);
850
+ return _possible_constructor_return$1(_this, _is_native_reflect_construct$1() ? Reflect.construct(derived, [], _get_prototype_of$1(_this).constructor) : derived.apply(_this, args));
851
+ }
852
+ function _class_call_check$1(instance, Constructor) {
853
+ if (!(instance instanceof Constructor)) {
854
+ throw new TypeError("Cannot call a class as a function");
855
+ }
856
+ }
857
+ function _defineProperties(target, props) {
858
+ for(var i = 0; i < props.length; i++){
859
+ var descriptor = props[i];
860
+ descriptor.enumerable = descriptor.enumerable || false;
861
+ descriptor.configurable = true;
862
+ if ("value" in descriptor) descriptor.writable = true;
863
+ Object.defineProperty(target, descriptor.key, descriptor);
864
+ }
865
+ }
866
+ function _create_class(Constructor, protoProps, staticProps) {
867
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
868
+ return Constructor;
869
+ }
870
+ function _define_property$2(obj, key, value) {
871
+ if (key in obj) {
872
+ Object.defineProperty(obj, key, {
873
+ value: value,
874
+ enumerable: true,
875
+ configurable: true,
876
+ writable: true
877
+ });
878
+ } else {
879
+ obj[key] = value;
880
+ }
881
+ return obj;
882
+ }
883
+ function _get_prototype_of$1(o) {
884
+ _get_prototype_of$1 = Object.setPrototypeOf ? Object.getPrototypeOf : function getPrototypeOf(o) {
885
+ return o.__proto__ || Object.getPrototypeOf(o);
886
+ };
887
+ return _get_prototype_of$1(o);
888
+ }
889
+ function _inherits$1(subClass, superClass) {
890
+ if (typeof superClass !== "function" && superClass !== null) {
891
+ throw new TypeError("Super expression must either be null or a function");
892
+ }
893
+ subClass.prototype = Object.create(superClass && superClass.prototype, {
894
+ constructor: {
895
+ value: subClass,
896
+ writable: true,
897
+ configurable: true
898
+ }
899
+ });
900
+ if (superClass) _set_prototype_of$1(subClass, superClass);
901
+ }
902
+ function _possible_constructor_return$1(self, call) {
903
+ if (call && (_type_of$1(call) === "object" || typeof call === "function")) {
904
+ return call;
905
+ }
906
+ return _assert_this_initialized$1(self);
907
+ }
908
+ function _set_prototype_of$1(o, p) {
909
+ _set_prototype_of$1 = Object.setPrototypeOf || function setPrototypeOf(o, p) {
910
+ o.__proto__ = p;
911
+ return o;
912
+ };
913
+ return _set_prototype_of$1(o, p);
914
+ }
915
+ function _type_of$1(obj) {
916
+ "@swc/helpers - typeof";
917
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
918
+ }
919
+ function _is_native_reflect_construct$1() {
920
+ try {
921
+ var result = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {}));
922
+ } catch (_) {}
923
+ return (_is_native_reflect_construct$1 = function() {
924
+ return !!result;
925
+ })();
926
+ }
927
+ function _ts_generator$1(thisArg, body) {
928
+ var f, y, t, _ = {
929
+ label: 0,
930
+ sent: function() {
931
+ if (t[0] & 1) throw t[1];
932
+ return t[1];
933
+ },
934
+ trys: [],
935
+ ops: []
936
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
937
+ return d(g, "next", {
938
+ value: verb(0)
939
+ }), d(g, "throw", {
940
+ value: verb(1)
941
+ }), d(g, "return", {
942
+ value: verb(2)
943
+ }), typeof Symbol === "function" && d(g, Symbol.iterator, {
944
+ value: function() {
945
+ return this;
946
+ }
947
+ }), g;
948
+ function verb(n) {
949
+ return function(v) {
950
+ return step([
951
+ n,
952
+ v
953
+ ]);
954
+ };
955
+ }
956
+ function step(op) {
957
+ if (f) throw new TypeError("Generator is already executing.");
958
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
959
+ 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;
960
+ if (y = 0, t) op = [
961
+ op[0] & 2,
962
+ t.value
963
+ ];
964
+ switch(op[0]){
965
+ case 0:
966
+ case 1:
967
+ t = op;
968
+ break;
969
+ case 4:
970
+ _.label++;
971
+ return {
972
+ value: op[1],
973
+ done: false
974
+ };
975
+ case 5:
976
+ _.label++;
977
+ y = op[1];
978
+ op = [
979
+ 0
980
+ ];
981
+ continue;
982
+ case 7:
983
+ op = _.ops.pop();
984
+ _.trys.pop();
985
+ continue;
986
+ default:
987
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
988
+ _ = 0;
989
+ continue;
990
+ }
991
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
992
+ _.label = op[1];
993
+ break;
994
+ }
995
+ if (op[0] === 6 && _.label < t[1]) {
996
+ _.label = t[1];
997
+ t = op;
998
+ break;
999
+ }
1000
+ if (t && _.label < t[2]) {
1001
+ _.label = t[2];
1002
+ _.ops.push(op);
1003
+ break;
1004
+ }
1005
+ if (t[2]) _.ops.pop();
1006
+ _.trys.pop();
1007
+ continue;
1008
+ }
1009
+ op = body.call(thisArg, _);
1010
+ } catch (e) {
1011
+ op = [
1012
+ 6,
1013
+ e
1014
+ ];
1015
+ y = 0;
1016
+ } finally{
1017
+ f = t = 0;
1018
+ }
1019
+ if (op[0] & 5) throw op[1];
1020
+ return {
1021
+ value: op[0] ? op[1] : void 0,
1022
+ done: true
1023
+ };
1024
+ }
1025
+ }
1026
+ /**
1027
+ * The callback parameter naming the datacenter whose accounts server issued the code.
1028
+ */ var ZOHO_OAUTH_CALLBACK_ACCOUNTS_SERVER_PARAM = 'accounts-server';
1029
+ /**
1030
+ * The callback parameter naming the datacenter's short location code, e.g. `us`.
1031
+ */ var ZOHO_OAUTH_CALLBACK_LOCATION_PARAM = 'location';
1032
+ /**
1033
+ * `extra` key holding the api domain a Zoho access token is usable against.
1034
+ *
1035
+ * Named constants because these keys are written on connect and read back on refresh — a literal in
1036
+ * one place and a typo in the other would silently send the refresh to the wrong datacenter.
1037
+ */ var ZOHO_EXTRA_API_DOMAIN_KEY = 'apiDomain';
1038
+ /**
1039
+ * `extra` key holding the accounts host a later refresh must be sent to.
1040
+ */ var ZOHO_EXTRA_ACCOUNTS_SERVER_KEY = 'accountsServer';
1041
+ /**
1042
+ * `extra` key holding Zoho's short location code for the datacenter.
1043
+ */ var ZOHO_EXTRA_LOCATION_KEY = 'location';
1044
+ /**
1045
+ * Maps an exchanged Zoho token response to the credentials stored on the private connection document.
1046
+ *
1047
+ * Two things differ from Cal.com's mapper. Zoho does not rotate its refresh token, so there is
1048
+ * nothing to prefer over the token we already hold — and `refresh_token` can be ABSENT entirely on a
1049
+ * re-consent, which is why it is passed through as `Maybe` rather than asserted (the framework's
1050
+ * `credentialsRetainingStoredRefreshToken` is what keeps that from destroying a working token). And
1051
+ * `api_domain` / `accountsServer` / `location` are retained in `extra`: a Zoho access token is only
1052
+ * usable against the api domain it was issued for, and a later refresh must go back to the same
1053
+ * datacenter's accounts server, so dropping them would leave the stored credentials unusable.
1054
+ *
1055
+ * @param input - The token response, the host it came from, and the identity when one was read.
1056
+ * @returns The credentials to store.
1057
+ */ function zohoUserExternalConnectionCredentials(input) {
1058
+ var _ref, _ref1;
1059
+ var response = input.response, accountsApiUrl = input.accountsApiUrl, location = input.location, userInfo = input.userInfo;
1060
+ var access_token = response.access_token, refresh_token = response.refresh_token, expires_in = response.expires_in, scope = response.scope, api_domain = response.api_domain;
1061
+ var now = Date.now();
1062
+ var zuid = userInfo === null || userInfo === void 0 ? void 0 : userInfo.ZUID;
1063
+ var _obj;
1064
+ return {
1065
+ accessToken: access_token,
1066
+ // Maybe on purpose — absent on a re-consent that did not force the consent screen
1067
+ refreshToken: refresh_token,
1068
+ tokenType: 'Bearer',
1069
+ issuedAt: new Date(now).toISOString(),
1070
+ expiresAt: expires_in == null ? undefined : new Date(now + expires_in * MS_IN_SECOND).toISOString(),
1071
+ scopes: zohoOAuthScopesFromScopeString(scope),
1072
+ externalAccountId: zuid == null ? undefined : String(zuid),
1073
+ label: (_ref = (_ref1 = userInfo === null || userInfo === void 0 ? void 0 : userInfo.Email) !== null && _ref1 !== void 0 ? _ref1 : userInfo === null || userInfo === void 0 ? void 0 : userInfo.Display_Name) !== null && _ref !== void 0 ? _ref : undefined,
1074
+ extra: (_obj = {}, _define_property$2(_obj, ZOHO_EXTRA_API_DOMAIN_KEY, api_domain), _define_property$2(_obj, ZOHO_EXTRA_ACCOUNTS_SERVER_KEY, accountsApiUrl), _define_property$2(_obj, ZOHO_EXTRA_LOCATION_KEY, location), _obj)
1075
+ };
1076
+ }
1077
+ /**
1078
+ * Zoho's half of the external-connection authorization-code handoff.
1079
+ *
1080
+ * Everything else — resolving who is connecting, surfacing a refusal, retaining a refresh token the
1081
+ * exchange did not return, persisting the credentials, choosing the redirect — is the framework's.
1082
+ */ var ZohoUserExternalConnectionOAuthService = /*#__PURE__*/ function(AbstractUserExternalConnectionOAuthService) {
1083
+ _inherits$1(ZohoUserExternalConnectionOAuthService, AbstractUserExternalConnectionOAuthService);
1084
+ function ZohoUserExternalConnectionOAuthService(config, stateCoder, userExternalConnectionActions, userExternalConnectionAccessor, oauthApi) {
1085
+ _class_call_check$1(this, ZohoUserExternalConnectionOAuthService);
1086
+ var _this;
1087
+ _this = _call_super$1(this, ZohoUserExternalConnectionOAuthService), _define_property$2(_this, "config", void 0), _define_property$2(_this, "stateCoder", void 0), _define_property$2(_this, "userExternalConnectionActions", void 0), _define_property$2(_this, "userExternalConnectionAccessor", void 0), _define_property$2(_this, "oauthApi", void 0), _define_property$2(_this, "authorizeUrlFactory", void 0), /**
1088
+ * The accounts host this app authorizes against, and the fallback for an exchange whose callback
1089
+ * named no usable one.
1090
+ */ _define_property$2(_this, "accountsApiUrl", void 0);
1091
+ _this.config = config;
1092
+ _this.stateCoder = stateCoder;
1093
+ _this.userExternalConnectionActions = userExternalConnectionActions;
1094
+ _this.userExternalConnectionAccessor = userExternalConnectionAccessor;
1095
+ _this.oauthApi = oauthApi;
1096
+ var scopes = config.scopes, accountsApiUrl = config.accountsApiUrl, userExternalConnectionOAuth = config.userExternalConnectionOAuth;
1097
+ // read through the api rather than injecting ZohoAccountsOAuthServiceConfig directly, which the
1098
+ // OAuth module does not export to its dependents
1099
+ _this.accountsApiUrl = accountsApiUrl == null ? oauthApi.apiUrl : zohoAccountsConfigApiUrl(accountsApiUrl);
1100
+ _this.authorizeUrlFactory = zohoAccountsAuthorizeUrlFactory({
1101
+ clientId: oauthApi.clientId,
1102
+ redirectUri: userExternalConnectionOAuth.redirectUri,
1103
+ scopes: scopes,
1104
+ accountsApiUrl: _this.accountsApiUrl
1105
+ });
1106
+ return _this;
1107
+ }
1108
+ _create_class(ZohoUserExternalConnectionOAuthService, [
1109
+ {
1110
+ key: "authorizeUrlForState",
1111
+ value: function authorizeUrlForState(state) {
1112
+ return this.authorizeUrlFactory({
1113
+ state: state
1114
+ });
1115
+ }
1116
+ },
1117
+ {
1118
+ key: "credentialsForAuthorizationCode",
1119
+ value: function credentialsForAuthorizationCode(input) {
1120
+ return _async_to_generator$1(function() {
1121
+ var _this_accountsApiUrlForCallbackQuery, code, redirectUri, query, accountsApiUrl, response, userInfo, e;
1122
+ return _ts_generator$1(this, function(_state) {
1123
+ switch(_state.label){
1124
+ case 0:
1125
+ code = input.code, redirectUri = input.redirectUri, query = input.query;
1126
+ accountsApiUrl = (_this_accountsApiUrlForCallbackQuery = this.accountsApiUrlForCallbackQuery(query)) !== null && _this_accountsApiUrlForCallbackQuery !== void 0 ? _this_accountsApiUrlForCallbackQuery : this.accountsApiUrl;
1127
+ return [
1128
+ 4,
1129
+ this.oauthApi.exchangeAuthorizationCode({
1130
+ code: code,
1131
+ redirectUri: redirectUri,
1132
+ accountsApiUrl: accountsApiUrl
1133
+ })
1134
+ ];
1135
+ case 1:
1136
+ response = _state.sent();
1137
+ _state.label = 2;
1138
+ case 2:
1139
+ _state.trys.push([
1140
+ 2,
1141
+ 4,
1142
+ ,
1143
+ 5
1144
+ ]);
1145
+ return [
1146
+ 4,
1147
+ this.oauthApi.userInfo({
1148
+ accessToken: response.access_token,
1149
+ accountsApiUrl: accountsApiUrl
1150
+ })
1151
+ ];
1152
+ case 3:
1153
+ userInfo = _state.sent();
1154
+ return [
1155
+ 3,
1156
+ 5
1157
+ ];
1158
+ case 4:
1159
+ e = _state.sent();
1160
+ this.logger.warn('Connected Zoho but could not read the identity to label the connection: ', e);
1161
+ return [
1162
+ 3,
1163
+ 5
1164
+ ];
1165
+ case 5:
1166
+ return [
1167
+ 2,
1168
+ zohoUserExternalConnectionCredentials({
1169
+ response: response,
1170
+ accountsApiUrl: accountsApiUrl,
1171
+ location: query === null || query === void 0 ? void 0 : query[ZOHO_OAUTH_CALLBACK_LOCATION_PARAM],
1172
+ userInfo: userInfo
1173
+ })
1174
+ ];
1175
+ }
1176
+ });
1177
+ }).call(this);
1178
+ }
1179
+ },
1180
+ {
1181
+ key: "refreshCredentials",
1182
+ value: function refreshCredentials(input) {
1183
+ return _async_to_generator$1(function() {
1184
+ var _this_allowlistedAccountsApiUrl, credentials, refreshToken, extra, storedAccountsServer, accountsApiUrl, response, location;
1185
+ return _ts_generator$1(this, function(_state) {
1186
+ switch(_state.label){
1187
+ case 0:
1188
+ credentials = input.credentials;
1189
+ refreshToken = credentials.refreshToken, extra = credentials.extra;
1190
+ if (!refreshToken) {
1191
+ throw new Error('ZohoUserExternalConnectionOAuthService.refreshCredentials: the stored credentials carry no refresh token.');
1192
+ }
1193
+ // the grant lives at ONE datacenter — a refresh token issued by `accounts.zoho.eu` is not honored
1194
+ // by `accounts.zoho.com` — so the stored accounts server is what the refresh must be sent to. It is
1195
+ // re-resolved through the allowlist rather than used verbatim: the value originally arrived on a
1196
+ // browser redirect, and it is the POST target the client secret travels to.
1197
+ storedAccountsServer = extra === null || extra === void 0 ? void 0 : extra[ZOHO_EXTRA_ACCOUNTS_SERVER_KEY];
1198
+ accountsApiUrl = (_this_allowlistedAccountsApiUrl = this.allowlistedAccountsApiUrl(storedAccountsServer == null ? undefined : String(storedAccountsServer))) !== null && _this_allowlistedAccountsApiUrl !== void 0 ? _this_allowlistedAccountsApiUrl : this.accountsApiUrl;
1199
+ return [
1200
+ 4,
1201
+ this.oauthApi.refreshUserAccessToken({
1202
+ refreshToken: refreshToken,
1203
+ accountsApiUrl: accountsApiUrl
1204
+ })
1205
+ ];
1206
+ case 1:
1207
+ response = _state.sent();
1208
+ // `location` is carried forward from the stored credentials rather than re-derived: it only ever
1209
+ // arrives on the callback, and the framework's merge would otherwise see an undefined value.
1210
+ location = extra === null || extra === void 0 ? void 0 : extra[ZOHO_EXTRA_LOCATION_KEY];
1211
+ // the response has no `refresh_token`, which the framework's merge retains — and `api_domain` may
1212
+ // legitimately differ from the one issued on connect, so it is taken from the response
1213
+ return [
1214
+ 2,
1215
+ zohoUserExternalConnectionCredentials({
1216
+ response: response,
1217
+ accountsApiUrl: accountsApiUrl,
1218
+ location: location == null ? undefined : String(location)
1219
+ })
1220
+ ];
1221
+ }
1222
+ });
1223
+ }).call(this);
1224
+ }
1225
+ },
1226
+ {
1227
+ /**
1228
+ * The accounts host to exchange against, taken from Zoho's `accounts-server` callback parameter.
1229
+ *
1230
+ * @param query - The raw callback query.
1231
+ * @returns The allowlisted accounts host the callback named, if any.
1232
+ */ key: "accountsApiUrlForCallbackQuery",
1233
+ value: function accountsApiUrlForCallbackQuery(query) {
1234
+ return this.allowlistedAccountsApiUrl(query === null || query === void 0 ? void 0 : query[ZOHO_OAUTH_CALLBACK_ACCOUNTS_SERVER_PARAM]);
1235
+ }
1236
+ },
1237
+ {
1238
+ /**
1239
+ * Resolves an untrusted accounts-host string back to one of the canonical Zoho hosts.
1240
+ *
1241
+ * Only an allowlisted Zoho host is honored. Every value passed here originated on a redirect an
1242
+ * attacker can compose — either the live callback query or a value persisted from an earlier one —
1243
+ * and it becomes the POST target the CLIENT SECRET is sent to, so an unchecked value would hand out
1244
+ * the secret. Resolving through the allowlist rather than comparing to it also guarantees the host
1245
+ * used is a canonical constant and never a caller-shaped variant of one. An unrecognized value is
1246
+ * dropped (and logged) rather than trusted.
1247
+ *
1248
+ * @param accountsServer - The untrusted host string, if any.
1249
+ * @returns The allowlisted accounts host, or null when there was none or it was not recognized.
1250
+ */ key: "allowlistedAccountsApiUrl",
1251
+ value: function allowlistedAccountsApiUrl(accountsServer) {
1252
+ var result;
1253
+ if (accountsServer) {
1254
+ var key = zohoAccountsApiUrlKeyForApiUrl(accountsServer);
1255
+ if (key == null) {
1256
+ this.logger.warn('Ignored an unrecognized Zoho accounts host of "'.concat(accountsServer, '"; using the configured host instead.'));
1257
+ } else {
1258
+ result = ZOHO_ACCOUNTS_API_URLS[key];
1259
+ }
1260
+ }
1261
+ return result;
1262
+ }
1263
+ }
1264
+ ]);
1265
+ return ZohoUserExternalConnectionOAuthService;
1266
+ }(AbstractUserExternalConnectionOAuthService);
1267
+ ZohoUserExternalConnectionOAuthService = __decorate([
1268
+ Injectable(),
1269
+ __param(0, Inject(ZohoUserExternalConnectionOAuthServiceConfig)),
1270
+ __param(1, Inject(UserExternalConnectionStateCoder)),
1271
+ __param(2, Inject(UserExternalConnectionServerActions)),
1272
+ __param(3, Inject(UserExternalConnectionAccessor)),
1273
+ __param(4, Inject(ZohoAccountsOAuthApi))
1274
+ ], ZohoUserExternalConnectionOAuthService);
1275
+
1276
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
1277
+ try {
1278
+ var info = gen[key](arg);
1279
+ var value = info.value;
1280
+ } catch (error) {
1281
+ reject(error);
1282
+ return;
1283
+ }
1284
+ if (info.done) {
1285
+ resolve(value);
1286
+ } else {
1287
+ Promise.resolve(value).then(_next, _throw);
1288
+ }
1289
+ }
1290
+ function _async_to_generator(fn) {
1291
+ return function() {
1292
+ var self = this, args = arguments;
1293
+ return new Promise(function(resolve, reject) {
1294
+ var gen = fn.apply(self, args);
1295
+ function _next(value) {
1296
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
1297
+ }
1298
+ function _throw(err) {
1299
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
1300
+ }
1301
+ _next(undefined);
1302
+ });
1303
+ };
1304
+ }
1305
+ function _define_property$1(obj, key, value) {
1306
+ if (key in obj) {
1307
+ Object.defineProperty(obj, key, {
1308
+ value: value,
1309
+ enumerable: true,
1310
+ configurable: true,
1311
+ writable: true
1312
+ });
1313
+ } else {
1314
+ obj[key] = value;
1315
+ }
1316
+ return obj;
1317
+ }
1318
+ function _object_spread(target) {
1319
+ for(var i = 1; i < arguments.length; i++){
1320
+ var source = arguments[i] != null ? arguments[i] : {};
1321
+ var ownKeys = Object.keys(source);
1322
+ if (typeof Object.getOwnPropertySymbols === "function") {
1323
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
1324
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
1325
+ }));
1326
+ }
1327
+ ownKeys.forEach(function(key) {
1328
+ _define_property$1(target, key, source[key]);
1329
+ });
1330
+ }
1331
+ return target;
1332
+ }
1333
+ function ownKeys(object, enumerableOnly) {
1334
+ var keys = Object.keys(object);
1335
+ if (Object.getOwnPropertySymbols) {
1336
+ var symbols = Object.getOwnPropertySymbols(object);
1337
+ keys.push.apply(keys, symbols);
1338
+ }
1339
+ return keys;
1340
+ }
1341
+ function _object_spread_props(target, source) {
1342
+ source = source != null ? source : {};
1343
+ if (Object.getOwnPropertyDescriptors) {
1344
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
1345
+ } else {
1346
+ ownKeys(Object(source)).forEach(function(key) {
1347
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
1348
+ });
1349
+ }
1350
+ return target;
1351
+ }
1352
+ function _ts_generator(thisArg, body) {
1353
+ var f, y, t, _ = {
1354
+ label: 0,
1355
+ sent: function() {
1356
+ if (t[0] & 1) throw t[1];
1357
+ return t[1];
1358
+ },
1359
+ trys: [],
1360
+ ops: []
1361
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
1362
+ return d(g, "next", {
1363
+ value: verb(0)
1364
+ }), d(g, "throw", {
1365
+ value: verb(1)
1366
+ }), d(g, "return", {
1367
+ value: verb(2)
1368
+ }), typeof Symbol === "function" && d(g, Symbol.iterator, {
1369
+ value: function() {
1370
+ return this;
1371
+ }
1372
+ }), g;
1373
+ function verb(n) {
1374
+ return function(v) {
1375
+ return step([
1376
+ n,
1377
+ v
1378
+ ]);
1379
+ };
1380
+ }
1381
+ function step(op) {
1382
+ if (f) throw new TypeError("Generator is already executing.");
1383
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
1384
+ 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;
1385
+ if (y = 0, t) op = [
1386
+ op[0] & 2,
1387
+ t.value
1388
+ ];
1389
+ switch(op[0]){
1390
+ case 0:
1391
+ case 1:
1392
+ t = op;
1393
+ break;
1394
+ case 4:
1395
+ _.label++;
1396
+ return {
1397
+ value: op[1],
1398
+ done: false
1399
+ };
1400
+ case 5:
1401
+ _.label++;
1402
+ y = op[1];
1403
+ op = [
1404
+ 0
1405
+ ];
1406
+ continue;
1407
+ case 7:
1408
+ op = _.ops.pop();
1409
+ _.trys.pop();
1410
+ continue;
1411
+ default:
1412
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
1413
+ _ = 0;
1414
+ continue;
1415
+ }
1416
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
1417
+ _.label = op[1];
1418
+ break;
1419
+ }
1420
+ if (op[0] === 6 && _.label < t[1]) {
1421
+ _.label = t[1];
1422
+ t = op;
1423
+ break;
1424
+ }
1425
+ if (t && _.label < t[2]) {
1426
+ _.label = t[2];
1427
+ _.ops.push(op);
1428
+ break;
1429
+ }
1430
+ if (t[2]) _.ops.pop();
1431
+ _.trys.pop();
1432
+ continue;
1433
+ }
1434
+ op = body.call(thisArg, _);
1435
+ } catch (e) {
1436
+ op = [
1437
+ 6,
1438
+ e
1439
+ ];
1440
+ y = 0;
1441
+ } finally{
1442
+ f = t = 0;
1443
+ }
1444
+ if (op[0] & 5) throw op[1];
1445
+ return {
1446
+ value: op[0] ? op[1] : void 0,
1447
+ done: true
1448
+ };
1449
+ }
1450
+ }
1451
+ /**
1452
+ * Maps stored connection credentials to a {@link ZohoAccessToken}.
1453
+ *
1454
+ * @param credentials - The credentials stored for the `zoho` provider.
1455
+ * @returns The equivalent Zoho access token, or null when the credentials cannot form one.
1456
+ */ function zohoAccessTokenFromUserExternalConnectionCredentials(credentials) {
1457
+ var _credentials_extra;
1458
+ var expiresAt = safeToJsDate(credentials === null || credentials === void 0 ? void 0 : credentials.expiresAt);
1459
+ var apiDomain = credentials === null || credentials === void 0 ? void 0 : (_credentials_extra = credentials.extra) === null || _credentials_extra === void 0 ? void 0 : _credentials_extra[ZOHO_EXTRA_API_DOMAIN_KEY];
1460
+ var result;
1461
+ // the api domain is required, not incidental: a Zoho access token is only usable against the domain
1462
+ // it was issued for, so a token synthesized without one would be sent to the wrong host
1463
+ if (credentials != null && expiresAt != null && apiDomain != null) {
1464
+ var _ref, _credentials_scopes;
1465
+ var issuedAt = safeToJsDate(credentials.issuedAt);
1466
+ var expiresIn = Math.round((expiresAt.getTime() - ((_ref = issuedAt === null || issuedAt === void 0 ? void 0 : issuedAt.getTime()) !== null && _ref !== void 0 ? _ref : Date.now())) / MS_IN_SECOND);
1467
+ result = {
1468
+ accessToken: credentials.accessToken,
1469
+ // joined on the same delimiter `zohoOAuthScopesFromScopeString` split them with
1470
+ scope: ((_credentials_scopes = credentials.scopes) !== null && _credentials_scopes !== void 0 ? _credentials_scopes : []).join(ZOHO_OAUTH_SCOPE_DELIMITER),
1471
+ apiDomain: String(apiDomain),
1472
+ expiresIn: expiresIn,
1473
+ expiresAt: expiresAt
1474
+ };
1475
+ }
1476
+ return result;
1477
+ }
1478
+ /**
1479
+ * Creates a {@link ZohoAccessTokenCache} backed by a user's UserExternalConnection pair.
1480
+ *
1481
+ * The Zoho counterpart of `userExternalConnectionCalcomAccessTokenCache`, and the per-user counterpart
1482
+ * of `firebaseZohoAccountsAccessTokenCacheService` — which caches the APP's token in a `SystemState`
1483
+ * document and has no notion of a user.
1484
+ *
1485
+ * Zoho does not rotate refresh tokens, so unlike Cal.com there is no token here that is destroyed by
1486
+ * being used. What this buys instead is that a renewed access token is shared: without it every Cloud
1487
+ * Function instance holds its own in-memory token and refreshes independently, so a user's grant is
1488
+ * exercised once per instance per hour rather than once per hour.
1489
+ *
1490
+ * @param config - The accessor, the actions, and the user the cache is for.
1491
+ * @returns A ZohoAccessTokenCache reading and writing the user's connection pair.
1492
+ */ function userExternalConnectionZohoAccessTokenCache(config) {
1493
+ var accessor = config.accessor, actions = config.actions, uid = config.uid;
1494
+ var providerType = ZOHO_USER_EXTERNAL_CONNECTION_PROVIDER_TYPE;
1495
+ var connection = accessor.accessorForUser({
1496
+ uid: uid
1497
+ })(providerType);
1498
+ function loadCachedToken() {
1499
+ return _async_to_generator(function() {
1500
+ var credentials;
1501
+ return _ts_generator(this, function(_state) {
1502
+ switch(_state.label){
1503
+ case 0:
1504
+ return [
1505
+ 4,
1506
+ connection.readUserExternalConnectionCredentials()
1507
+ ];
1508
+ case 1:
1509
+ credentials = _state.sent();
1510
+ return [
1511
+ 2,
1512
+ zohoAccessTokenFromUserExternalConnectionCredentials(credentials)
1513
+ ];
1514
+ }
1515
+ });
1516
+ })();
1517
+ }
1518
+ function updateCachedToken(accessToken) {
1519
+ return _async_to_generator(function() {
1520
+ var previous, now, refreshed;
1521
+ return _ts_generator(this, function(_state) {
1522
+ switch(_state.label){
1523
+ case 0:
1524
+ return [
1525
+ 4,
1526
+ connection.readUserExternalConnectionCredentials()
1527
+ ];
1528
+ case 1:
1529
+ previous = _state.sent();
1530
+ if (previous == null) {
1531
+ // nothing to merge onto, and a Zoho access token carries no refresh token — writing it alone
1532
+ // would store credentials that can never be renewed
1533
+ return [
1534
+ 2
1535
+ ];
1536
+ }
1537
+ now = new Date();
1538
+ refreshed = _object_spread_props(_object_spread({}, previous), {
1539
+ accessToken: accessToken.accessToken,
1540
+ issuedAt: now.toISOString(),
1541
+ expiresAt: accessToken.expiresAt.toISOString(),
1542
+ extra: _object_spread_props(_object_spread({}, previous.extra), _define_property$1({}, ZOHO_EXTRA_API_DOMAIN_KEY, accessToken.apiDomain))
1543
+ });
1544
+ return [
1545
+ 4,
1546
+ actions.refreshUserExternalConnectionCredentials({
1547
+ uid: uid,
1548
+ providerType: providerType,
1549
+ credentials: mergeRefreshedUserExternalConnectionCredentials({
1550
+ previous: previous,
1551
+ refreshed: refreshed
1552
+ })
1553
+ })
1554
+ ];
1555
+ case 2:
1556
+ _state.sent();
1557
+ return [
1558
+ 2
1559
+ ];
1560
+ }
1561
+ });
1562
+ })();
1563
+ }
1564
+ function clearCachedToken() {
1565
+ return _async_to_generator(function() {
1566
+ var previous;
1567
+ return _ts_generator(this, function(_state) {
1568
+ switch(_state.label){
1569
+ case 0:
1570
+ return [
1571
+ 4,
1572
+ connection.readUserExternalConnectionCredentials()
1573
+ ];
1574
+ case 1:
1575
+ previous = _state.sent();
1576
+ if (previous == null) {
1577
+ return [
1578
+ 2
1579
+ ];
1580
+ }
1581
+ // deliberately NOT a disconnect. Zoho's factory clears the cache to force its next call to refresh,
1582
+ // which is a statement about the ACCESS token only — dropping the refresh token here would turn a
1583
+ // routine cache invalidation into a connection the user has to re-authorize.
1584
+ return [
1585
+ 4,
1586
+ actions.refreshUserExternalConnectionCredentials({
1587
+ uid: uid,
1588
+ providerType: providerType,
1589
+ credentials: _object_spread_props(_object_spread({}, previous), {
1590
+ accessToken: '',
1591
+ expiresAt: new Date(0).toISOString()
1592
+ })
1593
+ })
1594
+ ];
1595
+ case 2:
1596
+ _state.sent();
1597
+ return [
1598
+ 2
1599
+ ];
1600
+ }
1601
+ });
1602
+ })();
1603
+ }
1604
+ return {
1605
+ loadCachedToken: loadCachedToken,
1606
+ updateCachedToken: updateCachedToken,
1607
+ clearCachedToken: clearCachedToken
1608
+ };
1609
+ }
1610
+
1611
+ function _assert_this_initialized(self) {
1612
+ if (self === void 0) {
1613
+ throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
1614
+ }
1615
+ return self;
1616
+ }
1617
+ function _call_super(_this, derived, args) {
1618
+ derived = _get_prototype_of(derived);
1619
+ return _possible_constructor_return(_this, _is_native_reflect_construct() ? Reflect.construct(derived, [], _get_prototype_of(_this).constructor) : derived.apply(_this, args));
1620
+ }
1621
+ function _class_call_check(instance, Constructor) {
1622
+ if (!(instance instanceof Constructor)) {
1623
+ throw new TypeError("Cannot call a class as a function");
1624
+ }
1625
+ }
1626
+ function _define_property(obj, key, value) {
1627
+ if (key in obj) {
1628
+ Object.defineProperty(obj, key, {
1629
+ value: value,
1630
+ enumerable: true,
1631
+ configurable: true,
1632
+ writable: true
1633
+ });
1634
+ } else {
1635
+ obj[key] = value;
1636
+ }
1637
+ return obj;
1638
+ }
1639
+ function _get_prototype_of(o) {
1640
+ _get_prototype_of = Object.setPrototypeOf ? Object.getPrototypeOf : function getPrototypeOf(o) {
1641
+ return o.__proto__ || Object.getPrototypeOf(o);
1642
+ };
1643
+ return _get_prototype_of(o);
1644
+ }
1645
+ function _inherits(subClass, superClass) {
1646
+ if (typeof superClass !== "function" && superClass !== null) {
1647
+ throw new TypeError("Super expression must either be null or a function");
1648
+ }
1649
+ subClass.prototype = Object.create(superClass && superClass.prototype, {
1650
+ constructor: {
1651
+ value: subClass,
1652
+ writable: true,
1653
+ configurable: true
1654
+ }
1655
+ });
1656
+ if (superClass) _set_prototype_of(subClass, superClass);
1657
+ }
1658
+ function _possible_constructor_return(self, call) {
1659
+ if (call && (_type_of(call) === "object" || typeof call === "function")) {
1660
+ return call;
1661
+ }
1662
+ return _assert_this_initialized(self);
1663
+ }
1664
+ function _set_prototype_of(o, p) {
1665
+ _set_prototype_of = Object.setPrototypeOf || function setPrototypeOf(o, p) {
1666
+ o.__proto__ = p;
1667
+ return o;
1668
+ };
1669
+ return _set_prototype_of(o, p);
1670
+ }
1671
+ function _type_of(obj) {
1672
+ "@swc/helpers - typeof";
1673
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
1674
+ }
1675
+ function _is_native_reflect_construct() {
1676
+ try {
1677
+ var result = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {}));
1678
+ } catch (_) {}
1679
+ return (_is_native_reflect_construct = function() {
1680
+ return !!result;
1681
+ })();
1682
+ }
1683
+ /**
1684
+ * Endpoints for the Zoho external-connection authorization-code handoff.
1685
+ *
1686
+ * Mounted at `/oauth/zoho`, matching the Angular registry's default authorize path of
1687
+ * `/oauth/<providerType>/authorize`. Hosting rewrites do not strip the path, so this prefix is the
1688
+ * public path — but an app with a global API route prefix must ALSO exclude these routes from it via
1689
+ * {@link ZOHO_USER_EXTERNAL_CONNECTION_OAUTH_ROUTES_FOR_GLOBAL_ROUTE_EXCLUDE}, or they land under
1690
+ * that prefix instead and no longer match the redirect URI registered with Zoho.
1691
+ *
1692
+ * The `authorize` and `callback` routes come from the base class, so this declares only where they
1693
+ * mount and which service serves them.
1694
+ */ var ZohoUserExternalConnectionOAuthController = /*#__PURE__*/ function(AbstractUserExternalConnectionOAuthController) {
1695
+ _inherits(ZohoUserExternalConnectionOAuthController, AbstractUserExternalConnectionOAuthController);
1696
+ function ZohoUserExternalConnectionOAuthController(oauthService) {
1697
+ _class_call_check(this, ZohoUserExternalConnectionOAuthController);
1698
+ var _this;
1699
+ _this = _call_super(this, ZohoUserExternalConnectionOAuthController), _define_property(_this, "oauthService", void 0);
1700
+ _this.oauthService = oauthService;
1701
+ return _this;
1702
+ }
1703
+ return ZohoUserExternalConnectionOAuthController;
1704
+ }(AbstractUserExternalConnectionOAuthController);
1705
+ ZohoUserExternalConnectionOAuthController = __decorate([
1706
+ Controller(ZOHO_USER_EXTERNAL_CONNECTION_OAUTH_CONTROLLER_PATH),
1707
+ __param(0, Inject(ZohoUserExternalConnectionOAuthService))
1708
+ ], ZohoUserExternalConnectionOAuthController);
1709
+
1710
+ function _array_like_to_array(arr, len) {
1711
+ if (len == null || len > arr.length) len = arr.length;
1712
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
1713
+ return arr2;
1714
+ }
1715
+ function _array_without_holes(arr) {
1716
+ if (Array.isArray(arr)) return _array_like_to_array(arr);
1717
+ }
1718
+ function _iterable_to_array(iter) {
1719
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
1720
+ }
1721
+ function _non_iterable_spread() {
1722
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
1723
+ }
1724
+ function _to_consumable_array(arr) {
1725
+ return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
1726
+ }
1727
+ function _unsupported_iterable_to_array(o, minLen) {
1728
+ if (!o) return;
1729
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
1730
+ var n = Object.prototype.toString.call(o).slice(8, -1);
1731
+ if (n === "Object" && o.constructor) n = o.constructor.name;
1732
+ if (n === "Map" || n === "Set") return Array.from(n);
1733
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
1734
+ }
1735
+ /**
1736
+ * Convenience function used to generate ModuleMetadata for an app's Zoho external-connection OAuth
1737
+ * module.
1738
+ *
1739
+ * Opt-in: importing the Zoho OAuth module alone never mounts HTTP routes, so an app that only makes
1740
+ * outbound Zoho calls exposes no endpoints.
1741
+ *
1742
+ * The importing module must also supply `UserExternalConnectionServerActions` and
1743
+ * `UserExternalConnectionStateCoder` — both exported by `appUserExternalConnectionModuleMetadata`,
1744
+ * so pass that module in `imports`.
1745
+ *
1746
+ * @param config - The module metadata configuration.
1747
+ * @returns NestJS ModuleMetadata mounting the Zoho connect endpoints.
1748
+ */ function appZohoUserExternalConnectionOAuthModuleMetadata(config) {
1749
+ var dependencyModule = config.dependencyModule, successPath = config.successPath, failurePath = config.failurePath, scopes = config.scopes, accountsApiUrl = config.accountsApiUrl, imports = config.imports, exports = config.exports, providers = config.providers;
1750
+ var dependencyModuleImport = dependencyModule ? [
1751
+ dependencyModule
1752
+ ] : [];
1753
+ return {
1754
+ imports: [
1755
+ ConfigModule
1756
+ ].concat(_to_consumable_array(dependencyModuleImport), _to_consumable_array(imports !== null && imports !== void 0 ? imports : [])),
1757
+ controllers: [
1758
+ ZohoUserExternalConnectionOAuthController
1759
+ ],
1760
+ exports: [
1761
+ ZohoUserExternalConnectionOAuthService
1762
+ ].concat(_to_consumable_array(exports !== null && exports !== void 0 ? exports : [])),
1763
+ providers: [
1764
+ {
1765
+ provide: ZohoUserExternalConnectionOAuthServiceConfig,
1766
+ inject: [
1767
+ FirebaseServerEnvService
1768
+ ],
1769
+ useFactory: function useFactory(envService) {
1770
+ return zohoUserExternalConnectionOAuthServiceConfigFactory({
1771
+ envService: envService,
1772
+ successPath: successPath,
1773
+ failurePath: failurePath,
1774
+ scopes: scopes,
1775
+ accountsApiUrl: accountsApiUrl
1776
+ });
1777
+ }
1778
+ },
1779
+ ZohoUserExternalConnectionOAuthService
1780
+ ].concat(_to_consumable_array(providers !== null && providers !== void 0 ? providers : []))
1781
+ };
1782
+ }
1783
+
1784
+ export { DEFAULT_ZOHO_OAUTH_SCOPES, TESTING_ZOHO_ACCESS_TOKEN_ENCRYPTION_SECRET, ZOHO_ACCESS_TOKEN_ENCRYPTION_SECRET_ENV_KEY, ZOHO_ACCESS_TOKEN_SYSTEM_STATE_TYPE, ZOHO_EXTRA_ACCOUNTS_SERVER_KEY, ZOHO_EXTRA_API_DOMAIN_KEY, ZOHO_EXTRA_LOCATION_KEY, ZOHO_OAUTH_CALLBACK_ACCOUNTS_SERVER_PARAM, ZOHO_OAUTH_CALLBACK_LOCATION_PARAM, ZOHO_USER_EXTERNAL_CONNECTION_OAUTH_CONTROLLER_PATH, ZOHO_USER_EXTERNAL_CONNECTION_OAUTH_ROUTES_FOR_GLOBAL_ROUTE_EXCLUDE, ZohoUserExternalConnectionOAuthController, ZohoUserExternalConnectionOAuthService, ZohoUserExternalConnectionOAuthServiceConfig, appZohoUserExternalConnectionOAuthModuleMetadata, firebaseZohoAccountsAccessTokenCacheService, loadZohoAccessTokenSystemState, userExternalConnectionZohoAccessTokenCache, zohoAccessTokenEncryptionSecretFactory, zohoAccessTokenFromUserExternalConnectionCredentials, zohoAccessTokenSystemStateDataConverter, zohoAccessTokenSystemStateDataConverterFactory, zohoAccessTokenSystemStateEmbeddedTokenConverter, zohoAccessTokenSystemStateEmbeddedTokenConverterFactory, zohoAccessTokenSystemStatePrivateConverterEntry, zohoUserExternalConnectionCredentials, zohoUserExternalConnectionOAuthServiceConfigFactory };