{"id":19419066,"url":"https://github.com/launchcodedev/fetch","last_synced_at":"2025-04-24T14:31:39.963Z","repository":{"id":54269551,"uuid":"295769163","full_name":"launchcodedev/fetch","owner":"launchcodedev","description":"Tiny wrapper for DOM fetch with reuse-ability in mind using the builder pattern","archived":false,"fork":false,"pushed_at":"2021-02-28T04:44:38.000Z","size":249,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-23T01:18:43.145Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/launchcodedev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-09-15T15:22:42.000Z","updated_at":"2024-06-01T16:19:54.000Z","dependencies_parsed_at":"2022-08-13T10:31:19.044Z","dependency_job_id":null,"html_url":"https://github.com/launchcodedev/fetch","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/launchcodedev%2Ffetch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/launchcodedev%2Ffetch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/launchcodedev%2Ffetch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/launchcodedev%2Ffetch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/launchcodedev","download_url":"https://codeload.github.com/launchcodedev/fetch/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250643411,"owners_count":21464169,"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","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":"2024-11-10T13:16:03.214Z","updated_at":"2025-04-24T14:31:39.641Z","avatar_url":"https://github.com/launchcodedev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fetch\nTiny wrapper around DOM fetch for common API wrappings. Isomorphic (supports browsers and Node.js), if `fetch` is available or polyfilled.\n\n[![Licensed under MPL 2.0](https://img.shields.io/badge/license-MPL_2.0-green.svg)](https://www.mozilla.org/en-US/MPL/2.0/)\n[![Build Status](https://github.com/launchcodedev/fetch/workflows/CI/badge.svg)](https://github.com/launchcodedev/fetch/actions)\n[![npm](https://img.shields.io/npm/v/@lcdev/fetch.svg)](https://www.npmjs.com/package/@lcdev/fetch)\n[![BundlePhobia](https://badgen.net/bundlephobia/minzip/@lcdev/fetch)](https://bundlephobia.com/result?p=@lcdev/fetch@latest)\n\n```bash\nyarn add @lcdev/fetch@VERSION\n```\n\nFeatures:\n- Easy to use builder-style API\n- Quick JSON, blob and text parsing options\n- Shareable builders for common options (authorization headers, onResponse hooks, etc.)\n- No magic - call `build()` and pass to fetch if you want\n- TypeScript friendly\n- Tiny footprint (2kb)\n\nIf you are looking for something not available here, try [ky-universal](https://github.com/sindresorhus/ky-universal) or [axios](https://github.com/axios/axios).\n\nThere are two main functions exported by this package:\n\n1. The `apiCall` function, which is used for creating a one-off fetch request\n2. The `api` function, which creates a shared builder for many fetch requests\n\n### `apiCall`\nThe simplest function is `apiCall`, which sets up a fetch request.\n\n```typescript\nimport { HttpMethod, apiCall } from '@lcdev/fetch';\n\nawait apiCall('https://base-url.com/endpoint', HttpMethod.GET).json\u003cTheResponseObject\u003e();\n```\n\nThis can be shortened by using the http method aliases exported by this package.\n\n```typescript\nimport { get } from '@lcdev/fetch';\n\nawait get('https://base-url.com/endpoint').json\u003cTheResponseObject\u003e();\n```\n\nThere are `get`, `post`, `put`, `patch`, and `remove` aliases.\n\nWith a `ApiCall` builder (the object returned by `apiCall`), we can chain many options for the request.\n\n- `withQuery(object, options?: SerializationOptions)`: adds query parameters, stringifying the object with `query-string`\n- `withHeaders(Headers)`: adds headers to request\n- `withHeader(key, value)`: adds a single header to the request\n- `withContentType(string)`: changes the content-type header\n- `withBearerToken(object: { token?: string })`: adds `Authorization: Bearer {token}` header\n- `withBody(object, isJson?: boolean, options?: SerializationOptions)`: adds a request body\n- `withJsonBody(object, options?: SerializationOptions)`: adds JSON request body\n- `withFormDataBody(FormData, options?: SerializationOptions)`: adds form-data request body\n- `withURLEncodedBody(object, options?: SerializationOptions)`: adds 'application/x-www-form-urlencoded' request body\n- `withExtraOptions(options: ExtraOptions)`: escape hatch to add extra options to `fetch` while still using the builder pattern\n- `expectStatus(number)`: throw an error if the response status isn't the expected one\n- `expectSuccessStatus()`: throw an error if the response status isn't in 200 range\n- `onPreBuild(callback)`: calls your function before options are built for every `fetch`\n- `onResponse(callback)`: calls your function whenever responses are received\n- `onJsonResponse(callback)`: calls your function whenever JSON responses are received\n- `build()`: constructs options that can be passed into `fetch` directly\n- `json\u003cT\u003e()`: calls fetch and parses response as JSON\n- `jsonAndResponse\u003cT\u003e()`: calls fetch and parses response as JSON, along with the full Response object\n- `blob\u003cT\u003e()`: calls fetch and parses response as a blob\n- `blobAndResponse\u003cT\u003e()`: calls fetch and parses response as a blob, along with the full Response object\n- `text\u003cT\u003e()`: calls fetch and parses response as text\n- `textAndResponse\u003cT\u003e()`: calls fetch and parses response as text, along with the full Response object\n\nBecause we expose `build`, there is always an escape hatch if you need something non-standard.\n\nNote that fetch calls are **lazy** - meaning that nothing will run until you call `.then` or `await` it.\n\n### `api`\nMost of the time, we make web apps that call APIs many times in different ways (endpoints, authorization, etc.).\nThis package provides a way to share configuration easily between all calls, without being \"global\".\n\n```typescript\nimport { api } from '@lcdev/fetch';\n\nconst myBackend = api('https://base-url.com')\n  .withBearerToken({ token: '...' })\n  .onResponse((res) =\u003e {\n    if (res.status === 401) logout();\n  });\n\n// we can re-use myBackend where we want to\n// you might put myBackend in a React Context, or inject it into state management\nawait myBackend.get('/endpoint').json\u003cTheResponseObject\u003e();\nawait myBackend.post('/endpoint').withJsonBody({ foo: 'bar' }).json\u003cTheOtherResponse\u003e();\n```\n\nHere, `myBackend` is an `Api` object, which exposes ways to create `ApiCall`s (like above).\nYou can perform the same builder functions on these as with `apiCall`.\n\nYou can add little callbacks to `myBackend` using `onResponse` or `onJsonResponse`. You might\ndo this for logging, for business logic, etc.\n\nYou can change the base URL if required with `changeBaseURL(path)`, though be warned that \nevery request from then on will then be based on that.\n\n## NodeJS Support\nJust polyfill `fetch`, and this package will work. Install `cross-fetch` package and add the following to your main file.\n\n```bash\nyarn add cross-fetch@3\n```\n\n```typescript\nimport fetch from 'cross-fetch';\nimport { setGlobalFetch } from '@lcdev/fetch';\n\nsetGlobalFetch(fetch);\n```\n\n## Client Certificates\n\nSome API servers require a client TLS certificate to authenticate against their API.\nIn NodeJS, you can do this using a custom HTTPS agent that is aware of the client certificate.\nThen you can use `.withExtraOptions()` to pass the custom `agent` to the `fetch` options\n\n_Note: `agent` is a non-standard option for `node-fetch`._\n\n```typescript\nimport * as https from 'https';\n\nconst myApi = api('https://base-url.com')\n  .withBearerToken({ token: '...' })\n  .withExtraOptions({\n    agent: new https.Agent({\n      pfx: myPfxClientCertificate,\n    }),\n  });\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaunchcodedev%2Ffetch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flaunchcodedev%2Ffetch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaunchcodedev%2Ffetch/lists"}