npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@lcdev/fetch

v0.1.11

Published

Wrapper for DOM fetch

Downloads

85

Readme

Fetch

Tiny wrapper around DOM fetch for common API wrappings. Isomorphic (supports browsers and Node.js), if fetch is available or polyfilled.

Licensed under MPL 2.0 Build Status npm BundlePhobia

yarn add @lcdev/fetch@VERSION

Features:

  • Easy to use builder-style API
  • Quick JSON, blob and text parsing options
  • Shareable builders for common options (authorization headers, onResponse hooks, etc.)
  • No magic - call build() and pass to fetch if you want
  • TypeScript friendly
  • Tiny footprint (2kb)

If you are looking for something not available here, try ky-universal or axios.

There are two main functions exported by this package:

  1. The apiCall function, which is used for creating a one-off fetch request
  2. The api function, which creates a shared builder for many fetch requests

apiCall

The simplest function is apiCall, which sets up a fetch request.

import { HttpMethod, apiCall } from '@lcdev/fetch';

await apiCall('https://base-url.com/endpoint', HttpMethod.GET).json<TheResponseObject>();

This can be shortened by using the http method aliases exported by this package.

import { get } from '@lcdev/fetch';

await get('https://base-url.com/endpoint').json<TheResponseObject>();

There are get, post, put, patch, and remove aliases.

With a ApiCall builder (the object returned by apiCall), we can chain many options for the request.

  • withQuery(object, options?: SerializationOptions): adds query parameters, stringifying the object with query-string
  • withHeaders(Headers): adds headers to request
  • withHeader(key, value): adds a single header to the request
  • withContentType(string): changes the content-type header
  • withBearerToken(object: { token?: string }): adds Authorization: Bearer {token} header
  • withBody(object, isJson?: boolean, options?: SerializationOptions): adds a request body
  • withJsonBody(object, options?: SerializationOptions): adds JSON request body
  • withFormDataBody(FormData, options?: SerializationOptions): adds form-data request body
  • withURLEncodedBody(object, options?: SerializationOptions): adds 'application/x-www-form-urlencoded' request body
  • withExtraOptions(options: ExtraOptions): escape hatch to add extra options to fetch while still using the builder pattern
  • expectStatus(number): throw an error if the response status isn't the expected one
  • expectSuccessStatus(): throw an error if the response status isn't in 200 range
  • onPreBuild(callback): calls your function before options are built for every fetch
  • onResponse(callback): calls your function whenever responses are received
  • onJsonResponse(callback): calls your function whenever JSON responses are received
  • build(): constructs options that can be passed into fetch directly
  • json<T>(): calls fetch and parses response as JSON
  • jsonAndResponse<T>(): calls fetch and parses response as JSON, along with the full Response object
  • blob<T>(): calls fetch and parses response as a blob
  • blobAndResponse<T>(): calls fetch and parses response as a blob, along with the full Response object
  • text<T>(): calls fetch and parses response as text
  • textAndResponse<T>(): calls fetch and parses response as text, along with the full Response object

Because we expose build, there is always an escape hatch if you need something non-standard.

Note that fetch calls are lazy - meaning that nothing will run until you call .then or await it.

api

Most of the time, we make web apps that call APIs many times in different ways (endpoints, authorization, etc.). This package provides a way to share configuration easily between all calls, without being "global".

import { api } from '@lcdev/fetch';

const myBackend = api('https://base-url.com')
  .withBearerToken({ token: '...' })
  .onResponse((res) => {
    if (res.status === 401) logout();
  });

// we can re-use myBackend where we want to
// you might put myBackend in a React Context, or inject it into state management
await myBackend.get('/endpoint').json<TheResponseObject>();
await myBackend.post('/endpoint').withJsonBody({ foo: 'bar' }).json<TheOtherResponse>();

Here, myBackend is an Api object, which exposes ways to create ApiCalls (like above). You can perform the same builder functions on these as with apiCall.

You can add little callbacks to myBackend using onResponse or onJsonResponse. You might do this for logging, for business logic, etc.

You can change the base URL if required with changeBaseURL(path), though be warned that every request from then on will then be based on that.

NodeJS Support

Just polyfill fetch, and this package will work. Install cross-fetch package and add the following to your main file.

yarn add cross-fetch@3
import fetch from 'cross-fetch';
import { setGlobalFetch } from '@lcdev/fetch';

setGlobalFetch(fetch);

Client Certificates

Some API servers require a client TLS certificate to authenticate against their API. In NodeJS, you can do this using a custom HTTPS agent that is aware of the client certificate. Then you can use .withExtraOptions() to pass the custom agent to the fetch options

Note: agent is a non-standard option for node-fetch.

import * as https from 'https';

const myApi = api('https://base-url.com')
  .withBearerToken({ token: '...' })
  .withExtraOptions({
    agent: new https.Agent({
      pfx: myPfxClientCertificate,
    }),
  });