@chriscdn/promise-retry 2.0.6 → 3.0.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.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 Christopher Meyer
3
+ Copyright (c) 2023-2025 Christopher Meyer
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -16,58 +16,62 @@ Using yarn:
16
16
  yarn add @chriscdn/promise-retry
17
17
  ```
18
18
 
19
- ## Example 1 - Promises
19
+ ## Upgrading to v3
20
+
21
+ The import has changed from
20
22
 
21
23
  ```js
22
24
  import promiseRetry from "@chriscdn/promise-retry";
25
+ ```
23
26
 
24
- function myFunction(attempt) {
25
- return new Promise((resolve, reject) => {
26
- // ... do something
27
+ to
27
28
 
28
- if (allIsFine) {
29
- resolve(/* <value> */);
30
- } else {
31
- reject(/* <err> */);
32
- }
33
- });
34
- }
29
+ ```js
30
+ import { promiseRetry } from "@chriscdn/promise-retry";
31
+ ```
32
+
33
+ ## Example 1 - Async/Await
35
34
 
36
- const options = {
37
- maxAttempts: 10,
38
- retryDelay: 0,
39
- onError: (err, attempt) => {},
35
+ ```js
36
+ import { promiseRetry, type RetryOptions } from "@chriscdn/promise-retry";
37
+
38
+ // all options are optional, defaults below
39
+ const options: RetryOptions = {
40
+ maxAttempts: 10, // Maximum retry attempts (default: 10)
41
+ retryDelay: 0, // Delay between retries (in ms)
42
+ onError: (err, attempt) => {
43
+ // log the error
44
+ },
40
45
  };
41
46
 
42
- // Call myFunction until a resolved promise is returned, but not more than 10 times (default is 10)
43
- promiseRetry((attempt) => myFunction(attempt), options)
44
- .then((value) => {
45
- // myFunction resolved within 10 attempts
46
- // value is from the myFunction resolve call
47
- })
48
- .catch((err) => {
49
- // myFunction failed to return a resolved promise within 10 attempts
50
- // err is the reject value from the last attempt
51
- });
47
+ const results = await promiseRetry(async (attempt) => {
48
+ // do something async in here
49
+ }, options);
52
50
  ```
53
51
 
54
- ## Example 2 - Async/Await
52
+ ## Example 2 - Retryify
53
+
54
+ `Retryify` wraps an asynchronous function and returns a new function with the same interface. If the original function fails (i.e., rejects its promise), it will automatically retry the function up to the specified number of times before rejecting.
55
55
 
56
56
  ```js
57
- import promiseRetry from "@chriscdn/promise-retry";
57
+ import { Retryify } from "@chriscdn/promise-retry";
58
58
 
59
- const results = await promiseRetry(
60
- async (attempt) => {
61
- // do something async in here
62
- },
63
- {
64
- maxAttempts: 10,
65
- retryDelay: 0,
66
- onError: (err, attempt) => {
67
- // log the error
68
- },
59
+ const myAsyncFunctionRandomFails = async (a, b) => {
60
+ if (Math.random() < 0.2) {
61
+ return a + b;
62
+ } else {
63
+ throw new Error("Random failure");
69
64
  }
70
- );
65
+ };
66
+
67
+ const myAsyncFunctionRetry = Retryify(myAsyncFunctionRandomFails, options);
68
+
69
+ try {
70
+ const sum = await myAsyncFunctionRetry(1, 5);
71
+ console.log("Success: ", sum);
72
+ } catch (err) {
73
+ console.error("Failed after retries:", err);
74
+ }
71
75
  ```
72
76
 
73
77
  ## License
@@ -0,0 +1,25 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { Retryify } from "../src";
3
+
4
+ describe("Retry", () => {
5
+ let i = 0;
6
+ const targetValue = 3;
7
+ const successOn3 = Retryify(async () => {
8
+ i = i + 1;
9
+
10
+ if (i === targetValue) {
11
+ return i;
12
+ } else {
13
+ throw new Error(`Attempt ${i}`);
14
+ }
15
+ }, {
16
+ retryDelay: 100,
17
+ onError: (err, attempt) => {
18
+ console.log(err);
19
+ },
20
+ });
21
+
22
+ it("Retryify", async () => {
23
+ expect(await successOn3()).toBe(targetValue);
24
+ });
25
+ });
package/lib/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
- type Options = {
1
+ type RetryOptions = {
2
2
  maxAttempts: number;
3
3
  retryDelay: number;
4
4
  onError: (err: any, attempt: number) => void;
5
5
  };
6
- declare function promiseRetry<T>(func: (attempt: number) => Promise<T>, options?: Partial<Options>, attempt?: number): Promise<T>;
7
- export default promiseRetry;
6
+ declare const promiseRetry: <T>(func: (attempt: number) => Promise<T>, options?: Partial<RetryOptions>, attempt?: number) => Promise<T>;
7
+ declare const Retryify: <Args extends unknown[], Return>(cb: (...args: Args) => Promise<Return>, options?: Partial<RetryOptions>) => (...args: Args) => Promise<Return>;
8
+ export { promiseRetry, Retryify, type RetryOptions };
@@ -1,2 +1,2 @@
1
- function r(){return r=Object.assign?Object.assign.bind():function(r){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var e in n)Object.prototype.hasOwnProperty.call(n,e)&&(r[e]=n[e])}return r},r.apply(this,arguments)}var t={maxAttempts:10,retryDelay:0,onError:function(r,t){}};module.exports=function n(e,o,i){void 0===o&&(o=t),void 0===i&&(i=1);var a=r({},t,o);return e(i).catch(function(r){if(a.onError(r,i),i<a.maxAttempts)return new Promise(function(r){setTimeout(function(){return r(n(e,o,i+1))},a.retryDelay)});throw r})};
1
+ function r(){return r=Object.assign?Object.assign.bind():function(r){for(var n=1;n<arguments.length;n++){var t=arguments[n];for(var e in t)({}).hasOwnProperty.call(t,e)&&(r[e]=t[e])}return r},r.apply(null,arguments)}var n={maxAttempts:10,retryDelay:0,onError:function(r,n){}},t=function(e,o,i){void 0===o&&(o=n),void 0===i&&(i=1);var u=r({},n,o);return e(i).catch(function(r){if(u.onError(r,i),i<u.maxAttempts)return new Promise(function(r){setTimeout(function(){return r(t(e,o,i+1))},u.retryDelay)});throw r})};exports.Retryify=function(r,n){return void 0===n&&(n={}),function(){var e=arguments;return t(function(){return r.apply(void 0,[].slice.call(e))},n)}},exports.promiseRetry=t;
2
2
  //# sourceMappingURL=promise-retry.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"promise-retry.cjs","sources":["../src/index.ts"],"sourcesContent":["type Options = {\n maxAttempts: number;\n retryDelay: number;\n onError: (err: any, attempt: number) => void;\n};\n\nconst defaultOptions: Options = {\n maxAttempts: 10,\n retryDelay: 0,\n onError: (err: any, attempt: number) => {},\n};\n\nfunction promiseRetry<T>(\n func: (attempt: number) => Promise<T>,\n options: Partial<Options> = defaultOptions,\n attempt = 1\n): Promise<T> {\n const config = { ...defaultOptions, ...options };\n\n return func(attempt).catch((err: any) => {\n // For logging...\n config.onError(err, attempt);\n\n if (attempt < config.maxAttempts) {\n return new Promise((resolve) => {\n setTimeout(\n () => resolve(promiseRetry(func, options, attempt + 1)),\n config.retryDelay\n );\n });\n } else {\n throw err;\n }\n });\n}\n\nexport default promiseRetry;\n"],"names":["defaultOptions","maxAttempts","retryDelay","onError","err","attempt","promiseRetry","func","options","config","_extends","Promise","resolve","setTimeout"],"mappings":"oOAMA,IAAMA,EAA0B,CAC9BC,YAAa,GACbC,WAAY,EACZC,QAAS,SAACC,EAAUC,qBAGtB,SAASC,EACPC,EACAC,EACAH,QADAG,IAAAA,IAAAA,EAA4BR,QAC5BK,IAAAA,IAAAA,EAAU,GAEV,IAAMI,EAAMC,EAAA,CAAA,EAAQV,EAAmBQ,GAEvC,OAAOD,EAAKF,GAAc,MAAC,SAACD,GAI1B,GAFAK,EAAON,QAAQC,EAAKC,GAEhBA,EAAUI,EAAOR,YACnB,OAAO,IAAIU,QAAQ,SAACC,GAClBC,WACE,WAAM,OAAAD,EAAQN,EAAaC,EAAMC,EAASH,EAAU,GAAG,EACvDI,EAAOP,WAEX,GAEA,MAAME,CAEV,EACF"}
1
+ {"version":3,"file":"promise-retry.cjs","sources":["../src/index.ts"],"sourcesContent":["type RetryOptions = {\n maxAttempts: number;\n retryDelay: number;\n onError: (err: any, attempt: number) => void;\n};\n\nconst defaultOptions: RetryOptions = {\n maxAttempts: 10,\n retryDelay: 0,\n onError: (err: any, attempt: number) => {},\n};\n\nconst promiseRetry = <T>(\n func: (attempt: number) => Promise<T>,\n options: Partial<RetryOptions> = defaultOptions,\n attempt = 1,\n): Promise<T> => {\n const config: RetryOptions = { ...defaultOptions, ...options };\n\n return func(attempt).catch((err: any) => {\n // For logging...\n config.onError(err, attempt);\n\n if (attempt < config.maxAttempts) {\n return new Promise((resolve) => {\n setTimeout(\n () => resolve(promiseRetry(func, options, attempt + 1)),\n config.retryDelay,\n );\n });\n } else {\n throw err;\n }\n });\n};\n\nconst Retryify = <Args extends unknown[], Return>(\n cb: (...args: Args) => Promise<Return>,\n options: Partial<RetryOptions> = {},\n) =>\n(...args: Args): Promise<Return> => {\n return promiseRetry<Return>(() => {\n return cb(...args);\n }, options);\n};\n\nexport { promiseRetry, Retryify, type RetryOptions };\n"],"names":["defaultOptions","maxAttempts","retryDelay","onError","err","attempt","promiseRetry","func","options","config","_extends","Promise","resolve","setTimeout","cb","_arguments","arguments","apply","slice","call"],"mappings":"wNAMA,IAAMA,EAA+B,CACnCC,YAAa,GACbC,WAAY,EACZC,QAAS,SAACC,EAAUC,MAGhBC,EAAe,SACnBC,EACAC,EACAH,QADA,IAAAG,IAAAA,EAAiCR,QACjCK,IAAAA,IAAAA,EAAU,GAEV,IAAMI,EAAMC,EAAA,GAAsBV,EAAmBQ,GAErD,OAAOD,EAAKF,GAAQ,MAAO,SAACD,GAI1B,GAFAK,EAAON,QAAQC,EAAKC,GAEhBA,EAAUI,EAAOR,YACnB,OAAW,IAAAU,QAAQ,SAACC,GAClBC,WACE,WAAA,OAAMD,EAAQN,EAAaC,EAAMC,EAASH,EAAU,GAAG,EACvDI,EAAOP,WAEX,GAEA,MAAME,CAEV,EACF,mBAEiB,SACfU,EACAN,GAEF,YAFmC,IAAjCA,IAAAA,EAAiC,CAAE,GAErC,eAAmCO,EAAAC,UACjC,OAAOV,EAAqB,WAC1B,OAAOQ,EAAEG,gBAAAC,MAAAC,KAAAJ,GACX,EAAGP,EACL,CAAC"}
@@ -1,2 +1,2 @@
1
- function t(){return t=Object.assign?Object.assign.bind():function(t){for(var r=1;r<arguments.length;r++){var e=arguments[r];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])}return t},t.apply(this,arguments)}const r={maxAttempts:10,retryDelay:0,onError:(t,r)=>{}};function e(n,o=r,a=1){const s=t({},r,o);return n(a).catch(t=>{if(s.onError(t,a),a<s.maxAttempts)return new Promise(t=>{setTimeout(()=>t(e(n,o,a+1)),s.retryDelay)});throw t})}export{e as default};
1
+ function r(){return r=Object.assign?Object.assign.bind():function(r){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var e in n)({}).hasOwnProperty.call(n,e)&&(r[e]=n[e])}return r},r.apply(null,arguments)}const t={maxAttempts:10,retryDelay:0,onError:(r,t)=>{}},n=(e,o=t,a=1)=>{const s=r({},t,o);return e(a).catch(r=>{if(s.onError(r,a),a<s.maxAttempts)return new Promise(r=>{setTimeout(()=>r(n(e,o,a+1)),s.retryDelay)});throw r})},e=(r,t={})=>(...e)=>n(()=>r(...e),t);export{e as Retryify,n as promiseRetry};
2
2
  //# sourceMappingURL=promise-retry.modern.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"promise-retry.modern.js","sources":["../src/index.ts"],"sourcesContent":["type Options = {\n maxAttempts: number;\n retryDelay: number;\n onError: (err: any, attempt: number) => void;\n};\n\nconst defaultOptions: Options = {\n maxAttempts: 10,\n retryDelay: 0,\n onError: (err: any, attempt: number) => {},\n};\n\nfunction promiseRetry<T>(\n func: (attempt: number) => Promise<T>,\n options: Partial<Options> = defaultOptions,\n attempt = 1\n): Promise<T> {\n const config = { ...defaultOptions, ...options };\n\n return func(attempt).catch((err: any) => {\n // For logging...\n config.onError(err, attempt);\n\n if (attempt < config.maxAttempts) {\n return new Promise((resolve) => {\n setTimeout(\n () => resolve(promiseRetry(func, options, attempt + 1)),\n config.retryDelay\n );\n });\n } else {\n throw err;\n }\n });\n}\n\nexport default promiseRetry;\n"],"names":["defaultOptions","maxAttempts","retryDelay","onError","err","attempt","promiseRetry","func","options","config","_extends","catch","Promise","resolve","setTimeout"],"mappings":"oOAMA,MAAMA,EAA0B,CAC9BC,YAAa,GACbC,WAAY,EACZC,QAASA,CAACC,EAAUC,KAAXF,GAGX,SAASG,EACPC,EACAC,EAA4BR,EAC5BK,EAAU,GAEV,MAAMI,EAAMC,EAAA,CAAA,EAAQV,EAAmBQ,GAEvC,OAAOD,EAAKF,GAASM,MAAOP,IAI1B,GAFAK,EAAON,QAAQC,EAAKC,GAEhBA,EAAUI,EAAOR,YACnB,OAAW,IAAAW,QAASC,IAClBC,WACE,IAAMD,EAAQP,EAAaC,EAAMC,EAASH,EAAU,IACpDI,EAAOP,WAEX,GAEA,MAAME,CACP,EAEL"}
1
+ {"version":3,"file":"promise-retry.modern.js","sources":["../src/index.ts"],"sourcesContent":["type RetryOptions = {\n maxAttempts: number;\n retryDelay: number;\n onError: (err: any, attempt: number) => void;\n};\n\nconst defaultOptions: RetryOptions = {\n maxAttempts: 10,\n retryDelay: 0,\n onError: (err: any, attempt: number) => {},\n};\n\nconst promiseRetry = <T>(\n func: (attempt: number) => Promise<T>,\n options: Partial<RetryOptions> = defaultOptions,\n attempt = 1,\n): Promise<T> => {\n const config: RetryOptions = { ...defaultOptions, ...options };\n\n return func(attempt).catch((err: any) => {\n // For logging...\n config.onError(err, attempt);\n\n if (attempt < config.maxAttempts) {\n return new Promise((resolve) => {\n setTimeout(\n () => resolve(promiseRetry(func, options, attempt + 1)),\n config.retryDelay,\n );\n });\n } else {\n throw err;\n }\n });\n};\n\nconst Retryify = <Args extends unknown[], Return>(\n cb: (...args: Args) => Promise<Return>,\n options: Partial<RetryOptions> = {},\n) =>\n(...args: Args): Promise<Return> => {\n return promiseRetry<Return>(() => {\n return cb(...args);\n }, options);\n};\n\nexport { promiseRetry, Retryify, type RetryOptions };\n"],"names":["defaultOptions","maxAttempts","retryDelay","onError","err","attempt","promiseRetry","func","options","config","_extends","catch","Promise","resolve","setTimeout","Retryify","cb","args"],"mappings":"wNAMA,MAAMA,EAA+B,CACnCC,YAAa,GACbC,WAAY,EACZC,QAASA,CAACC,EAAUC,KAAXF,GAGLG,EAAeA,CACnBC,EACAC,EAAiCR,EACjCK,EAAU,KAEV,MAAMI,EAAMC,EAAsBV,GAAAA,EAAmBQ,GAErD,OAAOD,EAAKF,GAASM,MAAOP,IAI1B,GAFAK,EAAON,QAAQC,EAAKC,GAEhBA,EAAUI,EAAOR,YACnB,OAAW,IAAAW,QAASC,IAClBC,WACE,IAAMD,EAAQP,EAAaC,EAAMC,EAASH,EAAU,IACpDI,EAAOP,WAAU,GAIrB,MAAME,CACP,EACF,EAGGW,EAAWA,CACfC,EACAR,EAAiC,CAAA,IAEnC,IAAIS,IACKX,EAAqB,IACnBU,KAAMC,GACZT"}
@@ -1,2 +1,2 @@
1
- function t(){return t=Object.assign?Object.assign.bind():function(t){for(var r=1;r<arguments.length;r++){var n=arguments[r];for(var e in n)Object.prototype.hasOwnProperty.call(n,e)&&(t[e]=n[e])}return t},t.apply(this,arguments)}var r={maxAttempts:10,retryDelay:0,onError:function(t,r){}};function n(e,o,a){void 0===o&&(o=r),void 0===a&&(a=1);var i=t({},r,o);return e(a).catch(function(t){if(i.onError(t,a),a<i.maxAttempts)return new Promise(function(t){setTimeout(function(){return t(n(e,o,a+1))},i.retryDelay)});throw t})}export{n as default};
1
+ function r(){return r=Object.assign?Object.assign.bind():function(r){for(var n=1;n<arguments.length;n++){var t=arguments[n];for(var e in t)({}).hasOwnProperty.call(t,e)&&(r[e]=t[e])}return r},r.apply(null,arguments)}var n={maxAttempts:10,retryDelay:0,onError:function(r,n){}},t=function(e,o,i){void 0===o&&(o=n),void 0===i&&(i=1);var u=r({},n,o);return e(i).catch(function(r){if(u.onError(r,i),i<u.maxAttempts)return new Promise(function(r){setTimeout(function(){return r(t(e,o,i+1))},u.retryDelay)});throw r})},e=function(r,n){return void 0===n&&(n={}),function(){var e=arguments;return t(function(){return r.apply(void 0,[].slice.call(e))},n)}};export{e as Retryify,t as promiseRetry};
2
2
  //# sourceMappingURL=promise-retry.module.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"promise-retry.module.js","sources":["../src/index.ts"],"sourcesContent":["type Options = {\n maxAttempts: number;\n retryDelay: number;\n onError: (err: any, attempt: number) => void;\n};\n\nconst defaultOptions: Options = {\n maxAttempts: 10,\n retryDelay: 0,\n onError: (err: any, attempt: number) => {},\n};\n\nfunction promiseRetry<T>(\n func: (attempt: number) => Promise<T>,\n options: Partial<Options> = defaultOptions,\n attempt = 1\n): Promise<T> {\n const config = { ...defaultOptions, ...options };\n\n return func(attempt).catch((err: any) => {\n // For logging...\n config.onError(err, attempt);\n\n if (attempt < config.maxAttempts) {\n return new Promise((resolve) => {\n setTimeout(\n () => resolve(promiseRetry(func, options, attempt + 1)),\n config.retryDelay\n );\n });\n } else {\n throw err;\n }\n });\n}\n\nexport default promiseRetry;\n"],"names":["defaultOptions","maxAttempts","retryDelay","onError","err","attempt","promiseRetry","func","options","config","_extends","Promise","resolve","setTimeout"],"mappings":"oOAMA,IAAMA,EAA0B,CAC9BC,YAAa,GACbC,WAAY,EACZC,QAAS,SAACC,EAAUC,MAGtB,SAASC,EACPC,EACAC,EACAH,QADAG,IAAAA,IAAAA,EAA4BR,QAC5BK,IAAAA,IAAAA,EAAU,GAEV,IAAMI,EAAMC,EAAA,CAAA,EAAQV,EAAmBQ,GAEvC,OAAOD,EAAKF,GAAc,MAAC,SAACD,GAI1B,GAFAK,EAAON,QAAQC,EAAKC,GAEhBA,EAAUI,EAAOR,YACnB,OAAO,IAAIU,QAAQ,SAACC,GAClBC,WACE,WAAM,OAAAD,EAAQN,EAAaC,EAAMC,EAASH,EAAU,GAAG,EACvDI,EAAOP,WAEX,GAEA,MAAME,CAEV,EACF"}
1
+ {"version":3,"file":"promise-retry.module.js","sources":["../src/index.ts"],"sourcesContent":["type RetryOptions = {\n maxAttempts: number;\n retryDelay: number;\n onError: (err: any, attempt: number) => void;\n};\n\nconst defaultOptions: RetryOptions = {\n maxAttempts: 10,\n retryDelay: 0,\n onError: (err: any, attempt: number) => {},\n};\n\nconst promiseRetry = <T>(\n func: (attempt: number) => Promise<T>,\n options: Partial<RetryOptions> = defaultOptions,\n attempt = 1,\n): Promise<T> => {\n const config: RetryOptions = { ...defaultOptions, ...options };\n\n return func(attempt).catch((err: any) => {\n // For logging...\n config.onError(err, attempt);\n\n if (attempt < config.maxAttempts) {\n return new Promise((resolve) => {\n setTimeout(\n () => resolve(promiseRetry(func, options, attempt + 1)),\n config.retryDelay,\n );\n });\n } else {\n throw err;\n }\n });\n};\n\nconst Retryify = <Args extends unknown[], Return>(\n cb: (...args: Args) => Promise<Return>,\n options: Partial<RetryOptions> = {},\n) =>\n(...args: Args): Promise<Return> => {\n return promiseRetry<Return>(() => {\n return cb(...args);\n }, options);\n};\n\nexport { promiseRetry, Retryify, type RetryOptions };\n"],"names":["defaultOptions","maxAttempts","retryDelay","onError","err","attempt","promiseRetry","func","options","config","_extends","Promise","resolve","setTimeout","Retryify","cb","_arguments","arguments","apply","slice","call"],"mappings":"wNAMA,IAAMA,EAA+B,CACnCC,YAAa,GACbC,WAAY,EACZC,QAAS,SAACC,EAAUC,MAGhBC,EAAe,SACnBC,EACAC,EACAH,QADA,IAAAG,IAAAA,EAAiCR,QACjCK,IAAAA,IAAAA,EAAU,GAEV,IAAMI,EAAMC,EAAA,GAAsBV,EAAmBQ,GAErD,OAAOD,EAAKF,GAAQ,MAAO,SAACD,GAI1B,GAFAK,EAAON,QAAQC,EAAKC,GAEhBA,EAAUI,EAAOR,YACnB,OAAW,IAAAU,QAAQ,SAACC,GAClBC,WACE,WAAA,OAAMD,EAAQN,EAAaC,EAAMC,EAASH,EAAU,GAAG,EACvDI,EAAOP,WAEX,GAEA,MAAME,CAEV,EACF,EAEMU,EAAW,SACfC,EACAP,GAEF,YAFmC,IAAjCA,IAAAA,EAAiC,CAAE,GAErC,eAAmCQ,EAAAC,UACjC,OAAOX,EAAqB,WAC1B,OAAOS,EAAEG,gBAAAC,MAAAC,KAAAJ,GACX,EAAGR,EACL,CAAC"}
@@ -1,2 +1,2 @@
1
- !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t||self).promiseRetry=e()}(this,function(){function t(){return t=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t},t.apply(this,arguments)}var e={maxAttempts:10,retryDelay:0,onError:function(t,e){}};return function n(r,o,i){void 0===o&&(o=e),void 0===i&&(i=1);var f=t({},e,o);return r(i).catch(function(t){if(f.onError(t,i),i<f.maxAttempts)return new Promise(function(t){setTimeout(function(){return t(n(r,o,i+1))},f.retryDelay)});throw t})}});
1
+ !function(n,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((n||self).promiseRetry={})}(this,function(n){function t(){return t=Object.assign?Object.assign.bind():function(n){for(var t=1;t<arguments.length;t++){var e=arguments[t];for(var r in e)({}).hasOwnProperty.call(e,r)&&(n[r]=e[r])}return n},t.apply(null,arguments)}var e={maxAttempts:10,retryDelay:0,onError:function(n,t){}},r=function(n,o,i){void 0===o&&(o=e),void 0===i&&(i=1);var f=t({},e,o);return n(i).catch(function(t){if(f.onError(t,i),i<f.maxAttempts)return new Promise(function(t){setTimeout(function(){return t(r(n,o,i+1))},f.retryDelay)});throw t})};n.Retryify=function(n,t){return void 0===t&&(t={}),function(){var e=arguments;return r(function(){return n.apply(void 0,[].slice.call(e))},t)}},n.promiseRetry=r});
2
2
  //# sourceMappingURL=promise-retry.umd.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"promise-retry.umd.js","sources":["../src/index.ts"],"sourcesContent":["type Options = {\n maxAttempts: number;\n retryDelay: number;\n onError: (err: any, attempt: number) => void;\n};\n\nconst defaultOptions: Options = {\n maxAttempts: 10,\n retryDelay: 0,\n onError: (err: any, attempt: number) => {},\n};\n\nfunction promiseRetry<T>(\n func: (attempt: number) => Promise<T>,\n options: Partial<Options> = defaultOptions,\n attempt = 1\n): Promise<T> {\n const config = { ...defaultOptions, ...options };\n\n return func(attempt).catch((err: any) => {\n // For logging...\n config.onError(err, attempt);\n\n if (attempt < config.maxAttempts) {\n return new Promise((resolve) => {\n setTimeout(\n () => resolve(promiseRetry(func, options, attempt + 1)),\n config.retryDelay\n );\n });\n } else {\n throw err;\n }\n });\n}\n\nexport default promiseRetry;\n"],"names":["defaultOptions","maxAttempts","retryDelay","onError","err","attempt","promiseRetry","func","options","config","_extends","Promise","resolve","setTimeout"],"mappings":"mcAMA,IAAMA,EAA0B,CAC9BC,YAAa,GACbC,WAAY,EACZC,QAAS,SAACC,EAAUC,aAGtB,SAASC,EACPC,EACAC,EACAH,QADAG,IAAAA,IAAAA,EAA4BR,QAC5BK,IAAAA,IAAAA,EAAU,GAEV,IAAMI,EAAMC,EAAA,CAAA,EAAQV,EAAmBQ,GAEvC,OAAOD,EAAKF,GAAc,MAAC,SAACD,GAI1B,GAFAK,EAAON,QAAQC,EAAKC,GAEhBA,EAAUI,EAAOR,YACnB,OAAO,IAAIU,QAAQ,SAACC,GAClBC,WACE,WAAM,OAAAD,EAAQN,EAAaC,EAAMC,EAASH,EAAU,GAAG,EACvDI,EAAOP,WAEX,GAEA,MAAME,CAEV,EACF"}
1
+ {"version":3,"file":"promise-retry.umd.js","sources":["../src/index.ts"],"sourcesContent":["type RetryOptions = {\n maxAttempts: number;\n retryDelay: number;\n onError: (err: any, attempt: number) => void;\n};\n\nconst defaultOptions: RetryOptions = {\n maxAttempts: 10,\n retryDelay: 0,\n onError: (err: any, attempt: number) => {},\n};\n\nconst promiseRetry = <T>(\n func: (attempt: number) => Promise<T>,\n options: Partial<RetryOptions> = defaultOptions,\n attempt = 1,\n): Promise<T> => {\n const config: RetryOptions = { ...defaultOptions, ...options };\n\n return func(attempt).catch((err: any) => {\n // For logging...\n config.onError(err, attempt);\n\n if (attempt < config.maxAttempts) {\n return new Promise((resolve) => {\n setTimeout(\n () => resolve(promiseRetry(func, options, attempt + 1)),\n config.retryDelay,\n );\n });\n } else {\n throw err;\n }\n });\n};\n\nconst Retryify = <Args extends unknown[], Return>(\n cb: (...args: Args) => Promise<Return>,\n options: Partial<RetryOptions> = {},\n) =>\n(...args: Args): Promise<Return> => {\n return promiseRetry<Return>(() => {\n return cb(...args);\n }, options);\n};\n\nexport { promiseRetry, Retryify, type RetryOptions };\n"],"names":["defaultOptions","maxAttempts","retryDelay","onError","err","attempt","promiseRetry","func","options","config","_extends","Promise","resolve","setTimeout","cb","_arguments","arguments","apply","slice","call"],"mappings":"8bAMA,IAAMA,EAA+B,CACnCC,YAAa,GACbC,WAAY,EACZC,QAAS,SAACC,EAAUC,MAGhBC,EAAe,SACnBC,EACAC,EACAH,QADA,IAAAG,IAAAA,EAAiCR,QACjCK,IAAAA,IAAAA,EAAU,GAEV,IAAMI,EAAMC,EAAA,GAAsBV,EAAmBQ,GAErD,OAAOD,EAAKF,GAAQ,MAAO,SAACD,GAI1B,GAFAK,EAAON,QAAQC,EAAKC,GAEhBA,EAAUI,EAAOR,YACnB,OAAW,IAAAU,QAAQ,SAACC,GAClBC,WACE,WAAA,OAAMD,EAAQN,EAAaC,EAAMC,EAASH,EAAU,GAAG,EACvDI,EAAOP,WAEX,GAEA,MAAME,CAEV,EACF,aAEiB,SACfU,EACAN,GAEF,YAFmC,IAAjCA,IAAAA,EAAiC,CAAE,GAErC,eAAmCO,EAAAC,UACjC,OAAOV,EAAqB,WAC1B,OAAOQ,EAAEG,gBAAAC,MAAAC,KAAAJ,GACX,EAAGP,EACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chriscdn/promise-retry",
3
- "version": "2.0.6",
3
+ "version": "3.0.0",
4
4
  "description": "Retry a function returning a rejected promise until it resolves.",
5
5
  "repository": "https://github.com/chriscdn/promise-retry",
6
6
  "author": "Christopher Meyer <chris@schwiiz.org>",
@@ -18,13 +18,16 @@
18
18
  "types": "./lib/index.d.ts",
19
19
  "scripts": {
20
20
  "build": "rm -rf ./lib/ && microbundle",
21
- "dev": "microbundle watch"
21
+ "dev": "microbundle watch",
22
+ "test": "vitest"
22
23
  },
23
24
  "devDependencies": {
24
- "microbundle": "^0.15.1"
25
+ "microbundle": "^0.15.1",
26
+ "vitest": "^3.1.1"
25
27
  },
26
28
  "keywords": [
27
29
  "promise",
28
30
  "retry"
29
- ]
31
+ ],
32
+ "dependencies": {}
30
33
  }
package/src/index.ts CHANGED
@@ -1,21 +1,21 @@
1
- type Options = {
1
+ type RetryOptions = {
2
2
  maxAttempts: number;
3
3
  retryDelay: number;
4
4
  onError: (err: any, attempt: number) => void;
5
5
  };
6
6
 
7
- const defaultOptions: Options = {
7
+ const defaultOptions: RetryOptions = {
8
8
  maxAttempts: 10,
9
9
  retryDelay: 0,
10
10
  onError: (err: any, attempt: number) => {},
11
11
  };
12
12
 
13
- function promiseRetry<T>(
13
+ const promiseRetry = <T>(
14
14
  func: (attempt: number) => Promise<T>,
15
- options: Partial<Options> = defaultOptions,
16
- attempt = 1
17
- ): Promise<T> {
18
- const config = { ...defaultOptions, ...options };
15
+ options: Partial<RetryOptions> = defaultOptions,
16
+ attempt = 1,
17
+ ): Promise<T> => {
18
+ const config: RetryOptions = { ...defaultOptions, ...options };
19
19
 
20
20
  return func(attempt).catch((err: any) => {
21
21
  // For logging...
@@ -25,13 +25,23 @@ function promiseRetry<T>(
25
25
  return new Promise((resolve) => {
26
26
  setTimeout(
27
27
  () => resolve(promiseRetry(func, options, attempt + 1)),
28
- config.retryDelay
28
+ config.retryDelay,
29
29
  );
30
30
  });
31
31
  } else {
32
32
  throw err;
33
33
  }
34
34
  });
35
- }
35
+ };
36
+
37
+ const Retryify = <Args extends unknown[], Return>(
38
+ cb: (...args: Args) => Promise<Return>,
39
+ options: Partial<RetryOptions> = {},
40
+ ) =>
41
+ (...args: Args): Promise<Return> => {
42
+ return promiseRetry<Return>(() => {
43
+ return cb(...args);
44
+ }, options);
45
+ };
36
46
 
37
- export default promiseRetry;
47
+ export { promiseRetry, Retryify, type RetryOptions };
package/src/test.js CHANGED
@@ -1,41 +1,18 @@
1
- const promiseRetry = require('./index')
2
- async function retryMe(name, attempt) {
3
- console.log(`${name} - ${attempt}`)
4
- if (coinFlip()) {
5
- throw new Error('shit')
1
+ import { Retryify } from "../lib/promise-retry.module.js";
2
+
3
+ const myAsyncFunctionThatSometimesFails = async (a, b) => {
4
+ if (Math.random() < 0.2) {
5
+ return a + b;
6
6
  } else {
7
- return `good: ${attempt}`
7
+ throw new Error("Random failure");
8
8
  }
9
- }
9
+ };
10
+
11
+ const myAsyncFunctionRetry = Retryify(myAsyncFunctionThatSometimesFails, {});
10
12
 
11
- function coinFlip() {
12
- return !Math.floor(Math.random() * 2)
13
+ try {
14
+ const sum = await myAsyncFunctionRetry(1, 5);
15
+ console.log("Success: ", sum);
16
+ } catch (err) {
17
+ console.error("Failed after retries:", err);
13
18
  }
14
- /*
15
- promiseRetry((attempt) => retryMe("bob", attempt), {
16
- maxAttempts: 10,
17
- milliseconds: 1000,
18
- })
19
- .then((poo) => {
20
- console.log(`poo: ${poo}`);
21
- })
22
- .catch((err) => {
23
- console.log("bummer");
24
- });
25
- */
26
- ;(async () => {
27
- const value = await promiseRetry(
28
- async (attempt) => {
29
- if (coinFlip()) {
30
- return attempt
31
- } else {
32
- console.log('nope')
33
- throw new Error('nope')
34
- }
35
- },
36
- {
37
- milliseconds: 1000,
38
- }
39
- )
40
- console.log(value)
41
- })()