@dereekb/zoho 11.0.12 → 11.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.cjs.js CHANGED
@@ -2911,6 +2911,43 @@ const ZOHO_DUPLICATE_DATA_ERROR_CODE = 'DUPLICATE_DATA';
2911
2911
  * Error when some passed data is invalid.
2912
2912
  */
2913
2913
  const ZOHO_INVALID_DATA_ERROR_CODE = 'INVALID_DATA';
2914
+ /**
2915
+ * Error when too many requests are made in a short period of time.
2916
+ */
2917
+ const ZOHO_TOO_MANY_REQUESTS_ERROR_CODE = 'TOO_MANY_REQUESTS';
2918
+ /**
2919
+ * The status code that Zoho uses to indicates that too many requests have been made in a short period of time.
2920
+ */
2921
+ const ZOHO_TOO_MANY_REQUESTS_HTTP_STATUS_CODE = 429;
2922
+ const ZOHO_RATE_LIMIT_LIMIT_HEADER = 'X-RATELIMIT-LIMIT';
2923
+ const ZOHO_RATE_LIMIT_REMAINING_HEADER = 'X-RATELIMIT-REMAINING';
2924
+ const ZOHO_RATE_LIMIT_RESET_HEADER = 'X-RATELIMIT-RESET';
2925
+ const DEFAULT_ZOHO_API_RATE_LIMIT = 100;
2926
+ const DEFAULT_ZOHO_API_RATE_LIMIT_RESET_PERIOD = util.MS_IN_MINUTE;
2927
+ function zohoRateLimitHeaderDetails(headers) {
2928
+ const limitHeader = headers.has(ZOHO_RATE_LIMIT_REMAINING_HEADER);
2929
+ const remainingHeader = headers.get(ZOHO_RATE_LIMIT_REMAINING_HEADER);
2930
+ const resetHeader = headers.get(ZOHO_RATE_LIMIT_RESET_HEADER);
2931
+ let result = null;
2932
+ if (limitHeader != null && remainingHeader != null && resetHeader != null) {
2933
+ const limit = Number(limitHeader);
2934
+ const remaining = Number(remainingHeader);
2935
+ const reset = Number(resetHeader);
2936
+ const resetAt = new Date(reset);
2937
+ result = {
2938
+ limit,
2939
+ remaining,
2940
+ reset,
2941
+ resetAt
2942
+ };
2943
+ }
2944
+ return result;
2945
+ }
2946
+ class ZohoTooManyRequestsError extends ZohoServerFetchResponseError {
2947
+ get headerDetails() {
2948
+ return zohoRateLimitHeaderDetails(this.responseError.response.headers);
2949
+ }
2950
+ }
2914
2951
  /**
2915
2952
  * Function that parses/transforms a ZohoServerErrorResponseData into a general ZohoServerError or other known error type.
2916
2953
  *
@@ -2933,6 +2970,9 @@ function parseZohoServerErrorResponseData(errorResponseData, responseError) {
2933
2970
  case ZOHO_INVALID_QUERY_ERROR_CODE:
2934
2971
  result = new ZohoInvalidQueryError(errorData, responseError);
2935
2972
  break;
2973
+ case ZOHO_TOO_MANY_REQUESTS_ERROR_CODE:
2974
+ result = new ZohoTooManyRequestsError(errorData, responseError);
2975
+ break;
2936
2976
  default:
2937
2977
  result = new ZohoServerFetchResponseError(errorData, responseError);
2938
2978
  break;
@@ -3370,6 +3410,63 @@ function zohoAccessTokenStringFactory(zohoAccessTokenFactory) {
3370
3410
  };
3371
3411
  }
3372
3412
 
3413
+ const DEFAULT_ZOHO_RATE_LIMITED_TOO_MANY_REQUETS_LOG_FUNCTION = headers => {
3414
+ console.warn(`zohoRateLimitedFetchHandler(): Too many requests made. The limit is ${headers.limit} requests per reset period. Will be reset at ${headers.resetAt}.`);
3415
+ };
3416
+ function zohoRateLimitedFetchHandler(config) {
3417
+ var _config$onTooManyRequ, _config$maxRateLimit, _config$resetPeriod;
3418
+ const onTooManyRequests = (config == null ? void 0 : config.onTooManyRequests) !== false ? (_config$onTooManyRequ = config == null ? void 0 : config.onTooManyRequests) != null ? _config$onTooManyRequ : DEFAULT_ZOHO_RATE_LIMITED_TOO_MANY_REQUETS_LOG_FUNCTION : undefined;
3419
+ const defaultLimit = (_config$maxRateLimit = config == null ? void 0 : config.maxRateLimit) != null ? _config$maxRateLimit : DEFAULT_ZOHO_API_RATE_LIMIT;
3420
+ const defaultResetPeriod = (_config$resetPeriod = config == null ? void 0 : config.resetPeriod) != null ? _config$resetPeriod : DEFAULT_ZOHO_API_RATE_LIMIT_RESET_PERIOD;
3421
+ function configForLimit(limit, resetAt) {
3422
+ return {
3423
+ limit: defaultLimit,
3424
+ startLimitAt: Math.ceil(limit / 20),
3425
+ cooldownRate: 1.1 * (limit / (defaultResetPeriod / util.MS_IN_SECOND)),
3426
+ exponentRate: 1.1,
3427
+ maxWaitTime: util.MS_IN_SECOND * 10,
3428
+ resetPeriod: defaultResetPeriod,
3429
+ resetAt
3430
+ };
3431
+ }
3432
+ const defaultConfig = configForLimit(defaultLimit);
3433
+ const rateLimiter = util.resetPeriodPromiseRateLimiter(defaultConfig);
3434
+ return fetch.rateLimitedFetchHandler({
3435
+ rateLimiter,
3436
+ updateWithResponse: function (response, fetchResponseError) {
3437
+ const hasLimitHeader = response.headers.has(ZOHO_RATE_LIMIT_REMAINING_HEADER);
3438
+ let shouldRetry = false;
3439
+ let enabled = false;
3440
+ if (hasLimitHeader) {
3441
+ const headerDetails = zohoRateLimitHeaderDetails(response.headers);
3442
+ if (headerDetails) {
3443
+ const {
3444
+ limit,
3445
+ resetAt,
3446
+ remaining
3447
+ } = headerDetails;
3448
+ if (limit !== defaultLimit) {
3449
+ const newConfig = configForLimit(limit, resetAt);
3450
+ rateLimiter.setConfig(newConfig, false);
3451
+ }
3452
+ rateLimiter.setRemainingLimit(remaining);
3453
+ rateLimiter.setNextResetAt(resetAt);
3454
+ enabled = true;
3455
+ // only retry if it's a TOO MANY REQUESTS error
3456
+ if (response.status === ZOHO_TOO_MANY_REQUESTS_HTTP_STATUS_CODE) {
3457
+ shouldRetry = true;
3458
+ try {
3459
+ onTooManyRequests == null || onTooManyRequests(headerDetails, response, fetchResponseError);
3460
+ } catch (e) {}
3461
+ }
3462
+ }
3463
+ }
3464
+ rateLimiter.setEnabled(enabled);
3465
+ return shouldRetry;
3466
+ }
3467
+ });
3468
+ }
3469
+
3373
3470
  function _call$1(body, then, direct) {
3374
3471
  if (direct) {
3375
3472
  return then ? then(body()) : body();
@@ -3386,9 +3483,10 @@ function zohoRecruitFactory(factoryConfig) {
3386
3483
  accountsContext
3387
3484
  } = factoryConfig;
3388
3485
  const accessTokenStringFactory = zohoAccessTokenStringFactory(accountsContext.loadAccessToken);
3486
+ const fetchHandler = zohoRateLimitedFetchHandler(factoryConfig.rateLimiterConfig);
3389
3487
  const {
3390
3488
  logZohoServerErrorFunction,
3391
- fetchFactory = input => fetch.nodeFetchService.makeFetch({
3489
+ fetchFactory = input => fetch.fetchApiFetchService.makeFetch({
3392
3490
  baseUrl: input.apiUrl,
3393
3491
  baseRequest: function () {
3394
3492
  return _call$1(accessTokenStringFactory, function (_accessTokenStringFac) {
@@ -3400,6 +3498,7 @@ function zohoRecruitFactory(factoryConfig) {
3400
3498
  };
3401
3499
  });
3402
3500
  },
3501
+ fetchHandler,
3403
3502
  timeout: 20 * 1000,
3404
3503
  requireOkResponse: true,
3405
3504
  useTimeout: true // use timeout
@@ -3423,7 +3522,8 @@ function zohoRecruitFactory(factoryConfig) {
3423
3522
  fetchJson,
3424
3523
  config: Object.assign({}, config, {
3425
3524
  apiUrl
3426
- })
3525
+ }),
3526
+ zohoRateLimiter: fetchHandler._rateLimiter
3427
3527
  };
3428
3528
  const zohoRecruit = {
3429
3529
  recruitContext
@@ -3540,15 +3640,17 @@ function _invoke(body, then) {
3540
3640
  return then(result);
3541
3641
  }
3542
3642
  function zohoAccountsFactory(factoryConfig) {
3643
+ const fetchHandler = zohoRateLimitedFetchHandler();
3543
3644
  const {
3544
3645
  logZohoServerErrorFunction,
3545
- fetchFactory = input => fetch.nodeFetchService.makeFetch({
3646
+ fetchFactory = input => fetch.fetchApiFetchService.makeFetch({
3546
3647
  baseUrl: input.apiUrl,
3547
3648
  baseRequest: {
3548
3649
  headers: {
3549
3650
  'Content-Type': 'application/json'
3550
3651
  }
3551
3652
  },
3653
+ fetchHandler,
3552
3654
  timeout: 20 * 1000,
3553
3655
  requireOkResponse: true,
3554
3656
  useTimeout: true // use timeout
@@ -3664,6 +3766,9 @@ function zohoAccountsZohoAccessTokenFactory(config) {
3664
3766
  });
3665
3767
  }
3666
3768
 
3769
+ exports.DEFAULT_ZOHO_API_RATE_LIMIT = DEFAULT_ZOHO_API_RATE_LIMIT;
3770
+ exports.DEFAULT_ZOHO_API_RATE_LIMIT_RESET_PERIOD = DEFAULT_ZOHO_API_RATE_LIMIT_RESET_PERIOD;
3771
+ exports.DEFAULT_ZOHO_RATE_LIMITED_TOO_MANY_REQUETS_LOG_FUNCTION = DEFAULT_ZOHO_RATE_LIMITED_TOO_MANY_REQUETS_LOG_FUNCTION;
3667
3772
  exports.ZOHO_ACCOUNTS_INVALID_CLIENT_ERROR_CODE = ZOHO_ACCOUNTS_INVALID_CLIENT_ERROR_CODE;
3668
3773
  exports.ZOHO_ACCOUNTS_INVALID_CODE_ERROR_CODE = ZOHO_ACCOUNTS_INVALID_CODE_ERROR_CODE;
3669
3774
  exports.ZOHO_ACCOUNTS_US_API_URL = ZOHO_ACCOUNTS_US_API_URL;
@@ -3673,9 +3778,14 @@ exports.ZOHO_INVALID_AUTHORIZATION_ERROR_CODE = ZOHO_INVALID_AUTHORIZATION_ERROR
3673
3778
  exports.ZOHO_INVALID_DATA_ERROR_CODE = ZOHO_INVALID_DATA_ERROR_CODE;
3674
3779
  exports.ZOHO_INVALID_QUERY_ERROR_CODE = ZOHO_INVALID_QUERY_ERROR_CODE;
3675
3780
  exports.ZOHO_MANDATORY_NOT_FOUND_ERROR_CODE = ZOHO_MANDATORY_NOT_FOUND_ERROR_CODE;
3781
+ exports.ZOHO_RATE_LIMIT_LIMIT_HEADER = ZOHO_RATE_LIMIT_LIMIT_HEADER;
3782
+ exports.ZOHO_RATE_LIMIT_REMAINING_HEADER = ZOHO_RATE_LIMIT_REMAINING_HEADER;
3783
+ exports.ZOHO_RATE_LIMIT_RESET_HEADER = ZOHO_RATE_LIMIT_RESET_HEADER;
3676
3784
  exports.ZOHO_RECRUIT_CANDIDATES_MODULE = ZOHO_RECRUIT_CANDIDATES_MODULE;
3677
3785
  exports.ZOHO_RECRUIT_SERVICE_NAME = ZOHO_RECRUIT_SERVICE_NAME;
3678
3786
  exports.ZOHO_SUCCESS_CODE = ZOHO_SUCCESS_CODE;
3787
+ exports.ZOHO_TOO_MANY_REQUESTS_ERROR_CODE = ZOHO_TOO_MANY_REQUESTS_ERROR_CODE;
3788
+ exports.ZOHO_TOO_MANY_REQUESTS_HTTP_STATUS_CODE = ZOHO_TOO_MANY_REQUESTS_HTTP_STATUS_CODE;
3679
3789
  exports.ZohoAccountsAccessTokenError = ZohoAccountsAccessTokenError;
3680
3790
  exports.ZohoAccountsAuthFailureError = ZohoAccountsAuthFailureError;
3681
3791
  exports.ZohoInternalError = ZohoInternalError;
@@ -3689,6 +3799,7 @@ exports.ZohoRecruitRecordCrudNoMatchingRecordError = ZohoRecruitRecordCrudNoMatc
3689
3799
  exports.ZohoRecruitRecordNoContentError = ZohoRecruitRecordNoContentError;
3690
3800
  exports.ZohoServerError = ZohoServerError;
3691
3801
  exports.ZohoServerFetchResponseError = ZohoServerFetchResponseError;
3802
+ exports.ZohoTooManyRequestsError = ZohoTooManyRequestsError;
3692
3803
  exports.accessToken = accessToken;
3693
3804
  exports.assertRecordDataArrayResultHasContent = assertRecordDataArrayResultHasContent;
3694
3805
  exports.createNotes = createNotes;
@@ -3726,6 +3837,8 @@ exports.zohoAccountsConfigApiUrl = zohoAccountsConfigApiUrl;
3726
3837
  exports.zohoAccountsFactory = zohoAccountsFactory;
3727
3838
  exports.zohoAccountsZohoAccessTokenFactory = zohoAccountsZohoAccessTokenFactory;
3728
3839
  exports.zohoFetchPageFactory = zohoFetchPageFactory;
3840
+ exports.zohoRateLimitHeaderDetails = zohoRateLimitHeaderDetails;
3841
+ exports.zohoRateLimitedFetchHandler = zohoRateLimitedFetchHandler;
3729
3842
  exports.zohoRecruitApiFetchJsonInput = zohoRecruitApiFetchJsonInput;
3730
3843
  exports.zohoRecruitConfigApiUrl = zohoRecruitConfigApiUrl;
3731
3844
  exports.zohoRecruitFactory = zohoRecruitFactory;
package/index.esm.js CHANGED
@@ -1,5 +1,5 @@
1
- import { getNextPageNumber, escapeStringCharactersFunction, isStandardInternetAccessibleWebsiteUrl, filterMaybeValues, asArray, MS_IN_MINUTE, MS_IN_SECOND } from '@dereekb/util';
2
- import { fetchPageFactory, FetchResponseError, makeUrlSearchParams, FetchRequestFactoryError, fetchJsonFunction, returnNullHandleFetchJsonParseErrorFunction, nodeFetchService } from '@dereekb/util/fetch';
1
+ import { getNextPageNumber, escapeStringCharactersFunction, isStandardInternetAccessibleWebsiteUrl, filterMaybeValues, asArray, MS_IN_MINUTE, resetPeriodPromiseRateLimiter, MS_IN_SECOND } from '@dereekb/util';
2
+ import { fetchPageFactory, FetchResponseError, makeUrlSearchParams, FetchRequestFactoryError, rateLimitedFetchHandler, fetchJsonFunction, returnNullHandleFetchJsonParseErrorFunction, fetchApiFetchService } from '@dereekb/util/fetch';
3
3
  import { BaseError } from 'make-error';
4
4
 
5
5
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@@ -3005,6 +3005,45 @@ const ZOHO_DUPLICATE_DATA_ERROR_CODE = 'DUPLICATE_DATA';
3005
3005
  */
3006
3006
  const ZOHO_INVALID_DATA_ERROR_CODE = 'INVALID_DATA';
3007
3007
 
3008
+ /**
3009
+ * Error when too many requests are made in a short period of time.
3010
+ */
3011
+ const ZOHO_TOO_MANY_REQUESTS_ERROR_CODE = 'TOO_MANY_REQUESTS';
3012
+
3013
+ /**
3014
+ * The status code that Zoho uses to indicates that too many requests have been made in a short period of time.
3015
+ */
3016
+ const ZOHO_TOO_MANY_REQUESTS_HTTP_STATUS_CODE = 429;
3017
+ const ZOHO_RATE_LIMIT_LIMIT_HEADER = 'X-RATELIMIT-LIMIT';
3018
+ const ZOHO_RATE_LIMIT_REMAINING_HEADER = 'X-RATELIMIT-REMAINING';
3019
+ const ZOHO_RATE_LIMIT_RESET_HEADER = 'X-RATELIMIT-RESET';
3020
+ const DEFAULT_ZOHO_API_RATE_LIMIT = 100;
3021
+ const DEFAULT_ZOHO_API_RATE_LIMIT_RESET_PERIOD = MS_IN_MINUTE;
3022
+ function zohoRateLimitHeaderDetails(headers) {
3023
+ const limitHeader = headers.has(ZOHO_RATE_LIMIT_REMAINING_HEADER);
3024
+ const remainingHeader = headers.get(ZOHO_RATE_LIMIT_REMAINING_HEADER);
3025
+ const resetHeader = headers.get(ZOHO_RATE_LIMIT_RESET_HEADER);
3026
+ let result = null;
3027
+ if (limitHeader != null && remainingHeader != null && resetHeader != null) {
3028
+ const limit = Number(limitHeader);
3029
+ const remaining = Number(remainingHeader);
3030
+ const reset = Number(resetHeader);
3031
+ const resetAt = new Date(reset);
3032
+ result = {
3033
+ limit,
3034
+ remaining,
3035
+ reset,
3036
+ resetAt
3037
+ };
3038
+ }
3039
+ return result;
3040
+ }
3041
+ class ZohoTooManyRequestsError extends ZohoServerFetchResponseError {
3042
+ get headerDetails() {
3043
+ return zohoRateLimitHeaderDetails(this.responseError.response.headers);
3044
+ }
3045
+ }
3046
+
3008
3047
  /**
3009
3048
  * Function that parses/transforms a ZohoServerErrorResponseData into a general ZohoServerError or other known error type.
3010
3049
  *
@@ -3027,6 +3066,9 @@ function parseZohoServerErrorResponseData(errorResponseData, responseError) {
3027
3066
  case ZOHO_INVALID_QUERY_ERROR_CODE:
3028
3067
  result = new ZohoInvalidQueryError(errorData, responseError);
3029
3068
  break;
3069
+ case ZOHO_TOO_MANY_REQUESTS_ERROR_CODE:
3070
+ result = new ZohoTooManyRequestsError(errorData, responseError);
3071
+ break;
3030
3072
  default:
3031
3073
  result = new ZohoServerFetchResponseError(errorData, responseError);
3032
3074
  break;
@@ -3500,14 +3542,80 @@ function zohoAccessTokenStringFactory(zohoAccessTokenFactory) {
3500
3542
  };
3501
3543
  }
3502
3544
 
3545
+ /**
3546
+ * Function to execute when too many requests is reached.
3547
+ *
3548
+ * Typically used for logging of some sort. Thrown errors are ignored.
3549
+ */
3550
+
3551
+ const DEFAULT_ZOHO_RATE_LIMITED_TOO_MANY_REQUETS_LOG_FUNCTION = headers => {
3552
+ console.warn(`zohoRateLimitedFetchHandler(): Too many requests made. The limit is ${headers.limit} requests per reset period. Will be reset at ${headers.resetAt}.`);
3553
+ };
3554
+ function zohoRateLimitedFetchHandler(config) {
3555
+ var _config$onTooManyRequ, _config$maxRateLimit, _config$resetPeriod;
3556
+ const onTooManyRequests = (config == null ? void 0 : config.onTooManyRequests) !== false ? (_config$onTooManyRequ = config == null ? void 0 : config.onTooManyRequests) != null ? _config$onTooManyRequ : DEFAULT_ZOHO_RATE_LIMITED_TOO_MANY_REQUETS_LOG_FUNCTION : undefined;
3557
+ const defaultLimit = (_config$maxRateLimit = config == null ? void 0 : config.maxRateLimit) != null ? _config$maxRateLimit : DEFAULT_ZOHO_API_RATE_LIMIT;
3558
+ const defaultResetPeriod = (_config$resetPeriod = config == null ? void 0 : config.resetPeriod) != null ? _config$resetPeriod : DEFAULT_ZOHO_API_RATE_LIMIT_RESET_PERIOD;
3559
+ function configForLimit(limit, resetAt) {
3560
+ return {
3561
+ limit: defaultLimit,
3562
+ startLimitAt: Math.ceil(limit / 20),
3563
+ // can do 5% of the requests of the limit before rate limiting begins
3564
+ cooldownRate: 1.1 * (limit / (defaultResetPeriod / MS_IN_SECOND)),
3565
+ exponentRate: 1.1,
3566
+ maxWaitTime: MS_IN_SECOND * 10,
3567
+ resetPeriod: defaultResetPeriod,
3568
+ resetAt
3569
+ };
3570
+ }
3571
+ const defaultConfig = configForLimit(defaultLimit);
3572
+ const rateLimiter = resetPeriodPromiseRateLimiter(defaultConfig);
3573
+ return rateLimitedFetchHandler({
3574
+ rateLimiter,
3575
+ updateWithResponse: function (response, fetchResponseError) {
3576
+ const hasLimitHeader = response.headers.has(ZOHO_RATE_LIMIT_REMAINING_HEADER);
3577
+ let shouldRetry = false;
3578
+ let enabled = false;
3579
+ if (hasLimitHeader) {
3580
+ const headerDetails = zohoRateLimitHeaderDetails(response.headers);
3581
+ if (headerDetails) {
3582
+ const {
3583
+ limit,
3584
+ resetAt,
3585
+ remaining
3586
+ } = headerDetails;
3587
+ if (limit !== defaultLimit) {
3588
+ const newConfig = configForLimit(limit, resetAt);
3589
+ rateLimiter.setConfig(newConfig, false);
3590
+ }
3591
+ rateLimiter.setRemainingLimit(remaining);
3592
+ rateLimiter.setNextResetAt(resetAt);
3593
+ enabled = true;
3594
+
3595
+ // only retry if it's a TOO MANY REQUESTS error
3596
+ if (response.status === ZOHO_TOO_MANY_REQUESTS_HTTP_STATUS_CODE) {
3597
+ shouldRetry = true;
3598
+ try {
3599
+ onTooManyRequests == null || onTooManyRequests(headerDetails, response, fetchResponseError);
3600
+ } catch (e) {}
3601
+ }
3602
+ }
3603
+ }
3604
+ rateLimiter.setEnabled(enabled);
3605
+ return shouldRetry;
3606
+ }
3607
+ });
3608
+ }
3609
+
3503
3610
  function zohoRecruitFactory(factoryConfig) {
3504
3611
  const {
3505
3612
  accountsContext
3506
3613
  } = factoryConfig;
3507
3614
  const accessTokenStringFactory = zohoAccessTokenStringFactory(accountsContext.loadAccessToken);
3615
+ const fetchHandler = zohoRateLimitedFetchHandler(factoryConfig.rateLimiterConfig);
3508
3616
  const {
3509
3617
  logZohoServerErrorFunction,
3510
- fetchFactory = input => nodeFetchService.makeFetch({
3618
+ fetchFactory = input => fetchApiFetchService.makeFetch({
3511
3619
  baseUrl: input.apiUrl,
3512
3620
  baseRequest: async () => ({
3513
3621
  headers: {
@@ -3515,6 +3623,7 @@ function zohoRecruitFactory(factoryConfig) {
3515
3623
  Authorization: `Bearer ${await accessTokenStringFactory()}`
3516
3624
  }
3517
3625
  }),
3626
+ fetchHandler,
3518
3627
  timeout: 20 * 1000,
3519
3628
  // 20 second timeout
3520
3629
  requireOkResponse: true,
@@ -3541,7 +3650,8 @@ function zohoRecruitFactory(factoryConfig) {
3541
3650
  fetchJson,
3542
3651
  config: Object.assign({}, config, {
3543
3652
  apiUrl
3544
- })
3653
+ }),
3654
+ zohoRateLimiter: fetchHandler._rateLimiter
3545
3655
  };
3546
3656
  const zohoRecruit = {
3547
3657
  recruitContext
@@ -3596,15 +3706,17 @@ function zohoAccountsConfigApiUrl(input) {
3596
3706
  */
3597
3707
 
3598
3708
  function zohoAccountsFactory(factoryConfig) {
3709
+ const fetchHandler = zohoRateLimitedFetchHandler();
3599
3710
  const {
3600
3711
  logZohoServerErrorFunction,
3601
- fetchFactory = input => nodeFetchService.makeFetch({
3712
+ fetchFactory = input => fetchApiFetchService.makeFetch({
3602
3713
  baseUrl: input.apiUrl,
3603
3714
  baseRequest: {
3604
3715
  headers: {
3605
3716
  'Content-Type': 'application/json'
3606
3717
  }
3607
3718
  },
3719
+ fetchHandler,
3608
3720
  timeout: 20 * 1000,
3609
3721
  // 20 second timeout
3610
3722
  requireOkResponse: true,
@@ -3721,4 +3833,4 @@ function zohoAccountsZohoAccessTokenFactory(config) {
3721
3833
  };
3722
3834
  }
3723
3835
 
3724
- export { ZOHO_ACCOUNTS_INVALID_CLIENT_ERROR_CODE, ZOHO_ACCOUNTS_INVALID_CODE_ERROR_CODE, ZOHO_ACCOUNTS_US_API_URL, ZOHO_DUPLICATE_DATA_ERROR_CODE, ZOHO_INTERNAL_ERROR_CODE, ZOHO_INVALID_AUTHORIZATION_ERROR_CODE, ZOHO_INVALID_DATA_ERROR_CODE, ZOHO_INVALID_QUERY_ERROR_CODE, ZOHO_MANDATORY_NOT_FOUND_ERROR_CODE, ZOHO_RECRUIT_CANDIDATES_MODULE, ZOHO_RECRUIT_SERVICE_NAME, ZOHO_SUCCESS_CODE, ZohoAccountsAccessTokenError, ZohoAccountsAuthFailureError, ZohoInternalError, ZohoInvalidAuthorizationError, ZohoInvalidQueryError, ZohoRecruitRecordCrudDuplicateDataError, ZohoRecruitRecordCrudError, ZohoRecruitRecordCrudInvalidDataError, ZohoRecruitRecordCrudMandatoryFieldNotFoundError, ZohoRecruitRecordCrudNoMatchingRecordError, ZohoRecruitRecordNoContentError, ZohoServerError, ZohoServerFetchResponseError, accessToken, assertRecordDataArrayResultHasContent, createNotes, createNotesForRecord, deleteNotes, escapeZohoFieldValueForCriteriaString, getNotesForRecord, getNotesForRecordPageFactory, getRecordById, getRecords, handleZohoAccountsErrorFetch, handleZohoErrorFetchFactory, handleZohoRecruitErrorFetch, insertRecord, interceptZohoAccountsErrorResponse, interceptZohoErrorResponseFactory, interceptZohoRecruitErrorResponse, isZohoRecruitValidUrl, logZohoAccountsErrorToConsole, logZohoRecruitErrorToConsole, logZohoServerErrorFunction, parseZohoAccountsError, parseZohoAccountsServerErrorResponseData, parseZohoRecruitError, parseZohoRecruitServerErrorResponseData, parseZohoServerErrorResponseData, searchRecords, searchRecordsPageFactory, tryFindZohoServerErrorData, updateRecord, upsertRecord, zohoAccessTokenStringFactory, zohoAccountsApiFetchJsonInput, zohoAccountsConfigApiUrl, zohoAccountsFactory, zohoAccountsZohoAccessTokenFactory, zohoFetchPageFactory, zohoRecruitApiFetchJsonInput, zohoRecruitConfigApiUrl, zohoRecruitFactory, zohoRecruitMultiRecordResult, zohoRecruitRecordCrudError, zohoRecruitSearchRecordsCriteriaEntryToCriteriaString, zohoRecruitSearchRecordsCriteriaString, zohoRecruitSearchRecordsCriteriaStringForTree, zohoRecruitUrlSearchParams, zohoRecruitUrlSearchParamsMinusIdAndModule, zohoRecruitUrlSearchParamsMinusModule, zohoServerErrorData };
3836
+ export { DEFAULT_ZOHO_API_RATE_LIMIT, DEFAULT_ZOHO_API_RATE_LIMIT_RESET_PERIOD, DEFAULT_ZOHO_RATE_LIMITED_TOO_MANY_REQUETS_LOG_FUNCTION, ZOHO_ACCOUNTS_INVALID_CLIENT_ERROR_CODE, ZOHO_ACCOUNTS_INVALID_CODE_ERROR_CODE, ZOHO_ACCOUNTS_US_API_URL, ZOHO_DUPLICATE_DATA_ERROR_CODE, ZOHO_INTERNAL_ERROR_CODE, ZOHO_INVALID_AUTHORIZATION_ERROR_CODE, ZOHO_INVALID_DATA_ERROR_CODE, ZOHO_INVALID_QUERY_ERROR_CODE, ZOHO_MANDATORY_NOT_FOUND_ERROR_CODE, ZOHO_RATE_LIMIT_LIMIT_HEADER, ZOHO_RATE_LIMIT_REMAINING_HEADER, ZOHO_RATE_LIMIT_RESET_HEADER, ZOHO_RECRUIT_CANDIDATES_MODULE, ZOHO_RECRUIT_SERVICE_NAME, ZOHO_SUCCESS_CODE, ZOHO_TOO_MANY_REQUESTS_ERROR_CODE, ZOHO_TOO_MANY_REQUESTS_HTTP_STATUS_CODE, ZohoAccountsAccessTokenError, ZohoAccountsAuthFailureError, ZohoInternalError, ZohoInvalidAuthorizationError, ZohoInvalidQueryError, ZohoRecruitRecordCrudDuplicateDataError, ZohoRecruitRecordCrudError, ZohoRecruitRecordCrudInvalidDataError, ZohoRecruitRecordCrudMandatoryFieldNotFoundError, ZohoRecruitRecordCrudNoMatchingRecordError, ZohoRecruitRecordNoContentError, ZohoServerError, ZohoServerFetchResponseError, ZohoTooManyRequestsError, accessToken, assertRecordDataArrayResultHasContent, createNotes, createNotesForRecord, deleteNotes, escapeZohoFieldValueForCriteriaString, getNotesForRecord, getNotesForRecordPageFactory, getRecordById, getRecords, handleZohoAccountsErrorFetch, handleZohoErrorFetchFactory, handleZohoRecruitErrorFetch, insertRecord, interceptZohoAccountsErrorResponse, interceptZohoErrorResponseFactory, interceptZohoRecruitErrorResponse, isZohoRecruitValidUrl, logZohoAccountsErrorToConsole, logZohoRecruitErrorToConsole, logZohoServerErrorFunction, parseZohoAccountsError, parseZohoAccountsServerErrorResponseData, parseZohoRecruitError, parseZohoRecruitServerErrorResponseData, parseZohoServerErrorResponseData, searchRecords, searchRecordsPageFactory, tryFindZohoServerErrorData, updateRecord, upsertRecord, zohoAccessTokenStringFactory, zohoAccountsApiFetchJsonInput, zohoAccountsConfigApiUrl, zohoAccountsFactory, zohoAccountsZohoAccessTokenFactory, zohoFetchPageFactory, zohoRateLimitHeaderDetails, zohoRateLimitedFetchHandler, zohoRecruitApiFetchJsonInput, zohoRecruitConfigApiUrl, zohoRecruitFactory, zohoRecruitMultiRecordResult, zohoRecruitRecordCrudError, zohoRecruitSearchRecordsCriteriaEntryToCriteriaString, zohoRecruitSearchRecordsCriteriaString, zohoRecruitSearchRecordsCriteriaStringForTree, zohoRecruitUrlSearchParams, zohoRecruitUrlSearchParamsMinusIdAndModule, zohoRecruitUrlSearchParamsMinusModule, zohoServerErrorData };
@@ -2,6 +2,14 @@
2
2
 
3
3
  This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
4
4
 
5
+ ## [11.0.14](https://github.com/dereekb/dbx-components/compare/v11.0.13-dev...v11.0.14) (2024-11-27)
6
+
7
+
8
+
9
+ ## [11.0.13](https://github.com/dereekb/dbx-components/compare/v11.0.12-dev...v11.0.13) (2024-11-27)
10
+
11
+
12
+
5
13
  ## [11.0.12](https://github.com/dereekb/dbx-components/compare/v11.0.11-dev...v11.0.12) (2024-11-24)
6
14
 
7
15
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/zoho/nestjs",
3
- "version": "11.0.12",
3
+ "version": "11.0.14",
4
4
  "type": "commonjs",
5
5
  "main": "./src/index.js"
6
6
  }
@@ -6,6 +6,7 @@ export declare class ZohoRecruitApi {
6
6
  readonly zohoAccountsApi: ZohoAccountsApi;
7
7
  readonly zohoRecruit: ZohoRecruit;
8
8
  get recruitContext(): ZohoRecruitContext;
9
+ get zohoRateLimiter(): import("../../../../../../dist/packages/util/src").ResetPeriodPromiseRateLimiter;
9
10
  constructor(config: ZohoRecruitServiceConfig, zohoAccountsApi: ZohoAccountsApi);
10
11
  get insertRecord(): import("@dereekb/zoho").ZohoRecruitCreateRecordLikeFunction;
11
12
  get upsertRecord(): import("@dereekb/zoho").ZohoRecruitUpsertRecordLikeFunction;
@@ -13,6 +13,9 @@ let ZohoRecruitApi = exports.ZohoRecruitApi = class ZohoRecruitApi {
13
13
  get recruitContext() {
14
14
  return this.zohoRecruit.recruitContext;
15
15
  }
16
+ get zohoRateLimiter() {
17
+ return this.zohoRecruit.recruitContext.zohoRateLimiter;
18
+ }
16
19
  constructor(config, zohoAccountsApi) {
17
20
  this.config = config;
18
21
  this.zohoAccountsApi = zohoAccountsApi;
@@ -1 +1 @@
1
- {"version":3,"file":"recruit.api.js","sourceRoot":"","sources":["../../../../../../../packages/zoho/nestjs/src/lib/recruit/recruit.api.ts"],"names":[],"mappings":";;;;AAAA,2CAAoD;AACpD,wCAAqQ;AACrQ,qDAA4D;AAC5D,2DAA2D;AAGpD,IAAM,cAAc,4BAApB,MAAM,cAAc;IAO8B;IAAoE;IANlH,WAAW,CAAc;IAElC,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC;IACzC,CAAC;IAED,YAAuD,MAAgC,EAAoC,eAAgC;QAApG,WAAM,GAAN,MAAM,CAA0B;QAAoC,oBAAe,GAAf,eAAe,CAAiB;QACzJ,IAAI,CAAC,WAAW,GAAG,IAAA,yBAAkB,EAAC;YACpC,GAAG,MAAM,CAAC,aAAa;YACvB,eAAe,EAAE,eAAe,CAAC,eAAe;SACjD,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACzB,CAAC;IAED,kBAAkB;IAClB,IAAI,YAAY;QACd,OAAO,IAAA,mBAAY,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,YAAY;QACd,OAAO,IAAA,mBAAY,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,YAAY;QACd,OAAO,IAAA,mBAAY,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,aAAa;QACf,OAAO,IAAA,oBAAa,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC5C,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAA,iBAAU,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACzC,CAAC;IAED,IAAI,aAAa;QACf,OAAO,IAAA,oBAAa,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC5C,CAAC;IAED,IAAI,wBAAwB;QAC1B,OAAO,IAAA,+BAAwB,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACvD,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAA,kBAAW,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1C,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAA,kBAAW,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1C,CAAC;IAED,IAAI,oBAAoB;QACtB,OAAO,IAAA,2BAAoB,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACnD,CAAC;IAED,IAAI,iBAAiB;QACnB,OAAO,IAAA,wBAAiB,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAChD,CAAC;CACF,CAAA;yBA1DY,cAAc;IAD1B,IAAA,mBAAU,GAAE;IAQE,mBAAA,IAAA,eAAM,EAAC,yCAAwB,CAAC,CAAA;IAA6C,mBAAA,IAAA,eAAM,EAAC,8BAAe,CAAC,CAAA;6CAAlD,yCAAwB,EAAqD,8BAAe;GAPhJ,cAAc,CA0D1B"}
1
+ {"version":3,"file":"recruit.api.js","sourceRoot":"","sources":["../../../../../../../packages/zoho/nestjs/src/lib/recruit/recruit.api.ts"],"names":[],"mappings":";;;;AAAA,2CAAoD;AACpD,wCAAqQ;AACrQ,qDAA4D;AAC5D,2DAA2D;AAGpD,IAAM,cAAc,4BAApB,MAAM,cAAc;IAW8B;IAAoE;IAVlH,WAAW,CAAc;IAElC,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC;IACzC,CAAC;IAED,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,eAAe,CAAC;IACzD,CAAC;IAED,YAAuD,MAAgC,EAAoC,eAAgC;QAApG,WAAM,GAAN,MAAM,CAA0B;QAAoC,oBAAe,GAAf,eAAe,CAAiB;QACzJ,IAAI,CAAC,WAAW,GAAG,IAAA,yBAAkB,EAAC;YACpC,GAAG,MAAM,CAAC,aAAa;YACvB,eAAe,EAAE,eAAe,CAAC,eAAe;SACjD,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACzB,CAAC;IAED,kBAAkB;IAClB,IAAI,YAAY;QACd,OAAO,IAAA,mBAAY,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,YAAY;QACd,OAAO,IAAA,mBAAY,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,YAAY;QACd,OAAO,IAAA,mBAAY,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,aAAa;QACf,OAAO,IAAA,oBAAa,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC5C,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAA,iBAAU,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACzC,CAAC;IAED,IAAI,aAAa;QACf,OAAO,IAAA,oBAAa,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC5C,CAAC;IAED,IAAI,wBAAwB;QAC1B,OAAO,IAAA,+BAAwB,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACvD,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAA,kBAAW,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1C,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAA,kBAAW,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1C,CAAC;IAED,IAAI,oBAAoB;QACtB,OAAO,IAAA,2BAAoB,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACnD,CAAC;IAED,IAAI,iBAAiB;QACnB,OAAO,IAAA,wBAAiB,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAChD,CAAC;CACF,CAAA;yBA9DY,cAAc;IAD1B,IAAA,mBAAU,GAAE;IAYE,mBAAA,IAAA,eAAM,EAAC,yCAAwB,CAAC,CAAA;IAA6C,mBAAA,IAAA,eAAM,EAAC,8BAAe,CAAC,CAAA;6CAAlD,yCAAwB,EAAqD,8BAAe;GAXhJ,cAAc,CA8D1B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/zoho",
3
- "version": "11.0.12",
3
+ "version": "11.0.14",
4
4
  "exports": {
5
5
  ".": {
6
6
  "types": "./src/index.d.ts",
@@ -3,4 +3,5 @@ export * from './accounts';
3
3
  export * from './zoho.error.api';
4
4
  export * from './zoho.api.page';
5
5
  export * from './zoho.config';
6
+ export * from './zoho.limit';
6
7
  export * from './zoho.type';
@@ -2,6 +2,7 @@ import { FactoryWithRequiredInput } from '@dereekb/util';
2
2
  import { ConfiguredFetch, FetchJsonFunction } from '@dereekb/util/fetch';
3
3
  import { ZohoApiUrl, ZohoRefreshToken, ZohoApiUrlKey, ZohoConfig, ZohoApiServiceName } from '../zoho.config';
4
4
  import { ZohoServiceAccessTokenKey } from '../accounts';
5
+ import { ZohoRateLimiterRef } from '../zoho.limit';
5
6
  export declare const ZOHO_RECRUIT_SERVICE_NAME: ZohoApiServiceName | ZohoServiceAccessTokenKey;
6
7
  export type ZohoRecruitApiUrl = ZohoApiUrl;
7
8
  export type ZohoRecruitApiKey = ZohoRefreshToken;
@@ -13,7 +14,7 @@ export interface ZohoRecruitFetchFactoryInput {
13
14
  readonly apiUrl: ZohoRecruitApiUrl;
14
15
  }
15
16
  export type ZohoRecruitFetchFactory = FactoryWithRequiredInput<ConfiguredFetch, ZohoRecruitFetchFactoryInput>;
16
- export interface ZohoRecruitContext {
17
+ export interface ZohoRecruitContext extends ZohoRateLimiterRef {
17
18
  readonly fetch: ConfiguredFetch;
18
19
  readonly fetchJson: FetchJsonFunction;
19
20
  readonly config: ZohoRecruitConfig;
@@ -136,7 +136,7 @@ export interface ZohoRecruitSearchRecordsCriteriaTree<T = any> {
136
136
  */
137
137
  readonly or?: Maybe<ZohoRecruitSearchRecordsCriteriaTreeElement<T>[]>;
138
138
  }
139
- export type ZohoRecruitSearchRecordsCriteriaTreeElement<T = any> = ZohoRecruitSearchRecordsCriteriaEntryArray<T> | ZohoRecruitSearchRecordsCriteriaTree | ZohoRecruitSearchRecordsCriteriaString;
139
+ export type ZohoRecruitSearchRecordsCriteriaTreeElement<T = any> = ZohoRecruitSearchRecordsCriteriaEntryArray<T> | ZohoRecruitSearchRecordsCriteriaTree<T> | ZohoRecruitSearchRecordsCriteriaString;
140
140
  export type ZohoRecruitSearchRecordsCriteriaFilterType = 'starts_with' | 'equals' | 'contains';
141
141
  export type ZohoRecruitSearchRecordsCriteriaEntryArray<T = any> = ZohoRecruitSearchRecordsCriteriaEntry<T>[];
142
142
  export interface ZohoRecruitSearchRecordsCriteriaEntry<T = any> {
@@ -1,8 +1,14 @@
1
1
  import { ZohoRecruitConfig, ZohoRecruitContextRef, ZohoRecruitFetchFactory } from './recruit.config';
2
2
  import { LogZohoServerErrorFunction } from '../zoho.error.api';
3
3
  import { ZohoAccountsContextRef } from '../accounts/accounts.config';
4
+ import { ZohoRateLimitedFetchHandlerConfig } from '../zoho.limit';
5
+ import { Maybe } from '@dereekb/util';
4
6
  export type ZohoRecruit = ZohoRecruitContextRef;
5
7
  export interface ZohoRecruitFactoryConfig extends ZohoAccountsContextRef {
8
+ /**
9
+ * Custom ZohoRateLimitedFetchHandlerConfig
10
+ */
11
+ rateLimiterConfig?: Maybe<ZohoRateLimitedFetchHandlerConfig>;
6
12
  /**
7
13
  * Creates a new fetch instance to use when making calls.
8
14
  */
@@ -1,4 +1,4 @@
1
- import { Maybe } from '@dereekb/util';
1
+ import { Maybe, UnixDateTimeNumber } from '@dereekb/util';
2
2
  import { ConfiguredFetch, FetchJsonInterceptJsonResponseFunction, FetchRequestFactoryError, FetchResponseError } from '@dereekb/util/fetch';
3
3
  import { BaseError } from 'make-error';
4
4
  export type ZohoServerErrorResponseDataError = ZohoServerErrorData | ZohoServerErrorCode;
@@ -125,6 +125,41 @@ export declare const ZOHO_DUPLICATE_DATA_ERROR_CODE = "DUPLICATE_DATA";
125
125
  * Error when some passed data is invalid.
126
126
  */
127
127
  export declare const ZOHO_INVALID_DATA_ERROR_CODE = "INVALID_DATA";
128
+ /**
129
+ * Error when too many requests are made in a short period of time.
130
+ */
131
+ export declare const ZOHO_TOO_MANY_REQUESTS_ERROR_CODE = "TOO_MANY_REQUESTS";
132
+ /**
133
+ * The status code that Zoho uses to indicates that too many requests have been made in a short period of time.
134
+ */
135
+ export declare const ZOHO_TOO_MANY_REQUESTS_HTTP_STATUS_CODE = 429;
136
+ export declare const ZOHO_RATE_LIMIT_LIMIT_HEADER = "X-RATELIMIT-LIMIT";
137
+ export declare const ZOHO_RATE_LIMIT_REMAINING_HEADER = "X-RATELIMIT-REMAINING";
138
+ export declare const ZOHO_RATE_LIMIT_RESET_HEADER = "X-RATELIMIT-RESET";
139
+ export declare const DEFAULT_ZOHO_API_RATE_LIMIT = 100;
140
+ export declare const DEFAULT_ZOHO_API_RATE_LIMIT_RESET_PERIOD: number;
141
+ export interface ZohoRateLimitHeaderDetails {
142
+ /**
143
+ * Total limit in a given period.
144
+ */
145
+ readonly limit: number;
146
+ /**
147
+ * Total number of remaining allowed requests.
148
+ */
149
+ readonly remaining: number;
150
+ /**
151
+ * The time at which the rate limit will reset.
152
+ */
153
+ readonly reset: UnixDateTimeNumber;
154
+ /**
155
+ * The time at which the rate limit will reset.
156
+ */
157
+ readonly resetAt: Date;
158
+ }
159
+ export declare function zohoRateLimitHeaderDetails(headers: Headers): Maybe<ZohoRateLimitHeaderDetails>;
160
+ export declare class ZohoTooManyRequestsError extends ZohoServerFetchResponseError {
161
+ get headerDetails(): Maybe<ZohoRateLimitHeaderDetails>;
162
+ }
128
163
  /**
129
164
  * Function that parses/transforms a ZohoServerErrorResponseData into a general ZohoServerError or other known error type.
130
165
  *
@@ -0,0 +1,37 @@
1
+ import { Maybe, Milliseconds, PromiseOrValue, ResetPeriodPromiseRateLimiter } from '@dereekb/util';
2
+ import { FetchResponseError, RateLimitedFetchHandler } from '@dereekb/util/fetch';
3
+ import { ZohoRateLimitHeaderDetails } from './zoho.error.api';
4
+ export interface ZohoRateLimiterRef {
5
+ readonly zohoRateLimiter: ResetPeriodPromiseRateLimiter;
6
+ }
7
+ /**
8
+ * Function to execute when too many requests is reached.
9
+ *
10
+ * Typically used for logging of some sort. Thrown errors are ignored.
11
+ */
12
+ export type ZohoRateLimitedTooManyRequestsLogFunction = (headers: ZohoRateLimitHeaderDetails, response: Response, fetchResponseError?: FetchResponseError) => PromiseOrValue<void>;
13
+ export declare const DEFAULT_ZOHO_RATE_LIMITED_TOO_MANY_REQUETS_LOG_FUNCTION: (headers: ZohoRateLimitHeaderDetails) => void;
14
+ export interface ZohoRateLimitedFetchHandlerConfig {
15
+ /**
16
+ * Custom max rate limit.
17
+ *
18
+ * Rate limits are different between account types and are described here:
19
+ *
20
+ * https://help.zoho.com/portal/en/community/topic/key-changes-in-api-limits-26-9-2018#:~:text=X%2DRATELIMIT%2DREMAINING%20%2D%20Represents,time%20of%20the%20current%20window.&text=Please%20note%20that%20these%20Rate,API%20limit%20changes%20are%20implemented.
21
+ */
22
+ readonly maxRateLimit?: number;
23
+ /**
24
+ * Custom reset period for the rate limiter.
25
+ *
26
+ * Defaults to 1 minute in milliseconds.
27
+ */
28
+ readonly resetPeriod?: Milliseconds;
29
+ /**
30
+ * Optional function to execute when too many requests is reached.t
31
+ *
32
+ * Defaults to the default logging function, unless false is passed.
33
+ */
34
+ readonly onTooManyRequests?: ZohoRateLimitedTooManyRequestsLogFunction | false;
35
+ }
36
+ export type ZohoRateLimitedFetchHandler = RateLimitedFetchHandler<ResetPeriodPromiseRateLimiter>;
37
+ export declare function zohoRateLimitedFetchHandler(config?: Maybe<ZohoRateLimitedFetchHandlerConfig>): ZohoRateLimitedFetchHandler;