{"id":30011954,"url":"https://github.com/matthewbub/fetch-with-retry","last_synced_at":"2025-08-05T13:19:43.366Z","repository":{"id":304641310,"uuid":"1015176788","full_name":"matthewbub/fetch-with-retry","owner":"matthewbub","description":"A promise-based fetch with retry, heavily based on p-retry and is-network-error. This is a consolidated version of the two packages with type checking and a few other changes.","archived":false,"fork":false,"pushed_at":"2025-07-07T05:54:34.000Z","size":31,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-03T16:58:20.229Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/matthewbub.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-07T05:52:54.000Z","updated_at":"2025-07-07T05:54:37.000Z","dependencies_parsed_at":"2025-07-14T13:21:34.958Z","dependency_job_id":"cf618b9e-d0dd-4152-8e2d-cd832226b2b5","html_url":"https://github.com/matthewbub/fetch-with-retry","commit_stats":null,"previous_names":["matthewbub/fetch-with-retry"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/matthewbub/fetch-with-retry","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matthewbub%2Ffetch-with-retry","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matthewbub%2Ffetch-with-retry/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matthewbub%2Ffetch-with-retry/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matthewbub%2Ffetch-with-retry/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/matthewbub","download_url":"https://codeload.github.com/matthewbub/fetch-with-retry/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matthewbub%2Ffetch-with-retry/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268904487,"owners_count":24326574,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-05T02:00:12.334Z","response_time":2576,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-08-05T13:19:42.223Z","updated_at":"2025-08-05T13:19:43.351Z","avatar_url":"https://github.com/matthewbub.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fetch-with-retry\n\nA promise-based fetch with retry, heavily based on [p-retry](https://github.com/sindresorhus/p-retry) and i[s-network-error](https://github.com/sindresorhus/is-network-error). This is a consolidated version of the two packages with type checking and a few other changes.\n\n## Features\n\n- **Exponential backoff** with configurable factor and randomization\n- **Network error detection** across different browsers and environments\n- **Abort signal support** for cancelling retry operations\n- **Time-based limits** with `maxRetryTime` option\n- **Custom retry logic** with `shouldRetry` callback\n- **TypeScript support** with full type definitions\n- **Zero dependencies** - consolidated implementation\n\n## Usage\n\n### Basic Example\n\n```typescript\nimport { fetchWithRetry } from \"./fetch-with-retry\";\n\nconst result = await fetchWithRetry(\n  async (attemptNumber) =\u003e {\n    console.log(`Attempt ${attemptNumber}`);\n    return fetch(\"https://api.example.com/data\");\n  },\n  {\n    retries: 3,\n    minTimeout: 1000,\n    maxTimeout: 5000,\n    factor: 2,\n  }\n);\n```\n\n### Advanced Configuration\n\n```typescript\nimport { fetchWithRetry } from \"./fetch-with-retry\";\n\nconst result = await fetchWithRetry(\n  async (attemptNumber) =\u003e {\n    const response = await fetch(\"https://api.example.com/data\");\n    if (!response.ok) {\n      throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n    }\n    return response.json();\n  },\n  {\n    retries: 5,\n    factor: 2,\n    minTimeout: 1000,\n    maxTimeout: 30000,\n    randomize: true,\n    maxRetryTime: 60000, // Stop after 1 minute total\n    onFailedAttempt: async ({ error, attemptNumber, retriesLeft }) =\u003e {\n      console.log(`Attempt ${attemptNumber} failed: ${error.message}`);\n      console.log(`${retriesLeft} retries left`);\n    },\n    shouldRetry: async ({ error, attemptNumber }) =\u003e {\n      // Don't retry on 4xx errors (client errors)\n      if (error.message.includes(\"HTTP 4\")) {\n        return false;\n      }\n      return true;\n    },\n    signal: AbortSignal.timeout(120000), // Overall timeout\n    unref: true, // Don't keep Node.js process alive\n  }\n);\n```\n\n## API\n\n### `fetchWithRetry(input, options)`\n\n#### Parameters\n\n- **`input`** `(attemptNumber: number) =\u003e Promise\u003cT\u003e` - Function that returns a promise to retry\n- **`options`** `RetryOptions` - Configuration options\n\n#### RetryOptions\n\n| Option            | Type          | Default                       | Description                             |\n| ----------------- | ------------- | ----------------------------- | --------------------------------------- |\n| `retries`         | `number`      | `10`                          | Number of retry attempts                |\n| `factor`          | `number`      | `2`                           | Exponential backoff factor              |\n| `minTimeout`      | `number`      | `1000`                        | Minimum delay between retries (ms)      |\n| `maxTimeout`      | `number`      | `Infinity`                    | Maximum delay between retries (ms)      |\n| `randomize`       | `boolean`     | `false`                       | Add randomization to delays (1.0-2.0x)  |\n| `maxRetryTime`    | `number`      | `Infinity`                    | Maximum total time for all retries (ms) |\n| `onFailedAttempt` | `function`    | `() =\u003e Promise.resolve()`     | Callback on each failed attempt         |\n| `shouldRetry`     | `function`    | `() =\u003e Promise.resolve(true)` | Custom retry logic                      |\n| `signal`          | `AbortSignal` | `undefined`                   | Abort signal for cancellation           |\n| `unref`           | `boolean`     | `false`                       | Don't keep Node.js process alive        |\n\n#### Callback Context\n\nBoth `onFailedAttempt` and `shouldRetry` receive a context object:\n\n```typescript\n{\n  error: Error; // The error that occurred\n  attemptNumber: number; // Current attempt (1-based)\n  retriesLeft: number; // Remaining retry attempts\n}\n```\n\n## Development\n\n### Scripts\n\n- `pnpm run test` - Run tests with Vitest\n- `pnpm run build` - Build TypeScript to JavaScript\n\n### Testing\n\nThe project uses Vitest for testing. Tests cover network error detection across different browser environments and error conditions.\n\n```bash\npnpm test\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatthewbub%2Ffetch-with-retry","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmatthewbub%2Ffetch-with-retry","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatthewbub%2Ffetch-with-retry/lists"}