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

fetchwizard

v0.0.4

Published

Experience an upgraded fetch API ๐ŸŒ. Operates seamlessly on node, browsers, and workers ๐Ÿ’ป๐ŸŒ๐Ÿ› ๏ธ.

Downloads

24

Readme

cover npm version npm downloads bundle JSDocs License

๐Ÿง™โ€โ™‚๏ธ fetchwizard

Experience an upgraded fetch API ๐ŸŒ. Operates seamlessly on node, browsers, and workers ๐Ÿ’ป๐ŸŒ๐Ÿ› ๏ธ.

๐Ÿ•’ Quick Start

Install:

# nyxi
nyxi fetchwizard

#pnpm
pnpm add fetchwizard

# npm
npm i fetchwizard

# yarn
yarn add fetchwizard

Import:

// ESM / Typescript
import { fetchwizard } from 'fetchwizard'

// CommonJS
const { fetchwizard } = require('fetchwizard')

โš™๏ธ Works with Node.js

We use conditional exports to detect Node.js and automatically use nyxblabs/fetch-for-all. If globalThis.fetch is available, it will be used instead. To leverage Node.js 17.5.0 experimental native fetch API, use the ๐Ÿ”ฌ --experimental-fetch flag.

โณ keepAlive support

By setting the FETCH_KEEP_ALIVE environment variable to true, an โšก๏ธ http/https agent will be registered that keeps sockets around even when there are no outstanding requests, so they can be used for future requests without having to reestablish a TCP connection.

Note: This option can potentially introduce memory leaks. Please check node-fetch/node-fetch#1325.

๐Ÿ“š Parsing Response

fetchwizard will smartly parse JSON and native values using nyxjson, falling back to text if it fails to parse.

const { users } = await fetchwizard('/api/users')

For binary content types, fetchwizard will instead return a ๐Ÿ“ฆ Blob object.

You can optionally provide a different parser than destr, or specify ๐Ÿ“ฆ blob, ๐Ÿงฑ arrayBuffer or ๐Ÿ“ text to force parsing the body with the respective FetchResponse method.

// Use JSON.parse
await fetchwizard('/movie?lang=en', { parseResponse: JSON.parse })

// Return text as is
await fetchwizard('/movie?lang=en', { parseResponse: txt => txt })

// Get the blob version of the response
await fetchwizard('/api/generate-image', { responseType: 'blob' })

๐Ÿ“ JSON Body

fetchwizard automatically stringifies the request body (if an object is passed) and adds JSON ๐Ÿ“‹ Content-Type and ๐Ÿ“ฅ Accept headers (for put, patch, and post requests).

const { users } = await fetchwizard('/api/users', { method: 'POST', body: { some: 'json' } })

โŒ Handling Errors

fetchwizard automatically throws errors when response.ok is false with a friendly error message and compact stack (hiding internals).

Parsed error body is available with error.data. You may also use the FetchError type.

await fetchwizard('http://google.com/404')
// FetchError: 404 Not Found (http://google.com/404)
//     at async main (/project/playground.ts:4:3)

In order to bypass errors as response you can use error.data:

await fetchwizard(...).catch((error) => error.data)

๐Ÿ” Auto Retry

fetchwizard automatically retries the request if an error occurs. The default number of retries is 1 (except for POST, PUT, PATCH, and DELETE methods, which have a default of 0 retries).

await fetchwizard('http://google.com/404', {
   retry: 3
})

โœจ Type Friendly

Responses can be type-assisted:

const article = await fetchwizard<Article>(`/api/article/${id}`)
// Auto complete working with article.id

๐ŸŒ Adding baseURL

By using the baseURL option, fetchwizard prepends it while respecting trailing/leading slashes and query search parameters for baseURL using url-ops:

await fetchwizard('/config', { baseURL })

๐Ÿ” Adding Query Search Params

By using the query option (or params as an alias), fetchwizard adds query search parameters to the URL by preserving the query in the request itself using url-ops:

await fetchwizard('/movie?lang=en', { query: { id: 123 } })

โšก๏ธ Interceptors

It is possible to provide async interceptors to hook into the lifecycle events of fetchwizard calls.

You might want to use fetchwizard.create to set shared interceptors.

๐Ÿš€ onRequest({ request, options })

The onRequest interceptor is called as soon as fetchwizard is being called, allowing you to modify options or perform simple logging.

await fetchwizard('/api', {
   async onRequest({ request, options }) {
      // Log request
      console.log('[fetch request]', request, options)

      // Add `?t=1640125211170` to query search params
      options.query = options.query || {}
      options.query.t = new Date()
   }
})

โŒ onRequestError({ request, options, error })

The onRequestError interceptor will be called when the fetch request fails.

await fetchwizard('/api', {
   async onRequestError({ request, options, error }) {
      // Log error
      console.log('[fetch request error]', request, error)
   }
})

โœ… onResponse({ request, options, response })

The onResponse interceptor will be called after the fetch call and parsing the response body.

await fetchwizard('/api', {
   async onResponse({ request, response, options }) {
      // Log response
      console.log('[fetch response]', request, response.status, response.body)
   }
})

โŒ onResponseError({ request, options, response })

The onResponseError interceptor is similar to onResponse, but it will be called when the fetch request is successful (response.ok is not true).

await fetchwizard('/api', {
   async onResponseError({ request, response, options }) {
      // Log error
      console.log('[fetch response error]', request, response.status, response.body)
   }
})

๐Ÿ”ง Create fetch with default options

This utility is useful if you need to use common options across several fetch calls.

Note: Defaults will be cloned at one level and inherited. Be careful with nested options like headers.

const apiFetch = fetchwizard.create({ baseURL: '/api' })

apiFetch('/test') // Same as fetchwizard('/test', { baseURL: '/api' })

๐Ÿ“ Adding headers

By using the headers option, fetchwizard adds extra headers in addition to the default headers of the request:

await fetchwizard('/movies', {
   headers: {
      'Accept': 'application/json',
      'Cache-Control': 'no-cache'
   }
})

๐ŸŒ Adding HTTP(S) Agent

If you need to use an HTTP(S) Agent, you can add the agent option with https-proxy-agent (for Node.js only):

import { HttpsProxyAgent } from 'https-proxy-agent'

await fetchwizard('/api', {
   agent: new HttpsProxyAgent('http://example.com')
})

๐Ÿ” Access to Raw Response

If you need to access the raw response (for headers, etc.), you can use fetchwizard.raw:

const response = await fetchwizard.raw('/sushi')

// response._data
// response.headers
// ...

๐Ÿš€ Native fetch

As a shortcut, you can use fetchwizard.native which provides the native fetch API.

const json = await fetchwizard.native('/sushi').then(r => r.json())

๐Ÿ“ฆ Bundler Notes

  • โœจ All targets are exported with Module and CommonJS format and named exports
  • โš™๏ธ No export is transpiled for the sake of modern syntax
    • ๐Ÿ”„ You probably need to transpile fetchwizard, destr, and ufo packages with babel for ES5 support
  • ๐Ÿ“ฅ You need to polyfill fetch global for supporting legacy browsers like using unfetch

โ“ FAQ

โ” Why export is called fetchwizard instead of fetch?

Using the same name of fetch can be confusing since API is different but still it is a fetch so using closest possible alternative. You can however, import { fetch } from fetchwizard which is auto polyfilled for Node.js and using native otherwise. ๐Ÿ”€

โ” Why not having default export?

Default exports are always risky to be mixed with CommonJS exports. โš ๏ธ

This also guarantees we can introduce more utils without breaking the package and also encourage using fetchwizard name. ๐Ÿ“ฆ

โ” Why not transpiled?

By keep transpiling libraries we push web backward with legacy code which is unneeded for most of the users. โฎ๏ธ

If you need to support legacy users, you can optionally transpile the library in your build pipeline. โš™๏ธ

๐Ÿ“œ License

MIT - Made with ๐Ÿ’ž