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

relax-client

v2.2.0

Published

A request helper to make building custom API clients simple

Downloads

155

Readme

relax-client

CircleCI

A super-simple REST client creation tool to encourage custom API clients for every business.

Intention

Every time I stepped into a project, the frontend code was littered with bespoke, individual fetch (or axios, flavor-of-the-week, etc.) requests being made every time the developer needed to hit the API. When I see that, my eyes cross and I get tired. So I started always creating custom API clients for every project.

This library aims to make that task a little easier.

relax-client is a wrapper around fetch that uses middlewares to apply helpful additional features. The library ships with several middlewares, but writing new ones is trivial.

Usage

npm install --save relax-client
// api-client.js

import create, {bearerAuth, json} from 'relax-client'

const client = create(`https://api.test.com/v1`)
	.use(bearerAuth(`storage-key`))
	.use(json())

export const login = (username, password) => client.post(`login`, {username, password})
export const logout = () => client.get(`logout`)

export const getAccount = () => client.get(`account`)
export const updateAccount = (username) => client.put(`account`, {username})
export const deleteAccount = () => client.destroy(`account`)

// app.js

import * as client from './api-client'

loginForm.on(`submit`, async function(e) {
	e.preventDefault()

	const username = loginForm.querySelector(`[name="username"]`).value
	const password = loginForm.querySelector(`[name="password"]`).value

	const {success} = await client.login(username, password)
	if (success) {
		const account = await client.getAccount()
	}
})

Middleware

Middlewares are added via the use function. Each middleware function is called with two arguments - the current request details and a callback that accepts an update object for those request details. The callback will return a Promise that ultimately resolves with the response object, and your middlewares can further process the response.

Depending on what actions your middlewares take, the order can matter. They take effect in the order they are added for the creation of the response (FILO), and in reverse order for updating the request (LIFO).

import create, {Client, form} from 'relax-client'

function custom() {
	return (request, next) => {
		console.log(`requesting ${request.url}`)
		const response = await next({url: `${request.url}?some-extra-data`})
		const text = await response.text()
		console.log(`response: ${text}`)
		return text
	}
}

const {get, post, put, destroy} = create(`https://api.test.com/v1`)
	.use(form())
	.use(custom())

// client.get | client.post | etc.

An individual request can also be configured to use a "one-off" middleware in the event it differs from the conventions of the API at large (eg. a particularly large request body needs compression).

import create, {json} from 'relax-client'
import gzip from 'relax-client/dist/middlewares/gzip'

const client = create(`https://api.test.com/v1`).use(json())

export const createAccount = (username, criminalRecord) =>
	client.post(`account`, {username, criminalRecord}, { middleware: gzip() })
export const getAccount = () => client.get(`account`)

Bearer Auth

The bearer auth middleware can be used to automatically configure all requests to the API with authentication headers. By default, it uses the Authorization header and stores auth tokens in localStorage, but can be configured according to your use case.

import create, {bearerAuth} from 'relax-client'

// the following all store an auth token in local storage
const authMiddleware = bearerAuth(`storage-key`)
const authMiddleware = bearerAuth(`storage-key`, {store: bearerAuth.THIS_SUBDOMAIN})
const authMiddleware = bearerAuth(`storage-key`, {store: 'localstorage'})

// the following all store an auth token in a cookie
const authMiddleware = bearerAuth(`storage-key`, {store: bearerAuth.ALL_SUBDOMAINS})
const authMiddleware = bearerAuth(`storage-key`, {store: 'cookie'})

// the following all store an auth token in memory
const authMiddleware = bearerAuth(`storage-key`, {store: bearerAuth.THIS_SESSION})
const authMiddleware = bearerAuth(`storage-key`, {store: 'memory'})

// this will use X-Auth-Token as both the request and response header for the token
const authMiddleware = bearerAuth(`storage-key`, {header: `X-Auth-Token`})

// client usage
const client = create(`https://api.test.com/v1`).use(authMiddleware)

// this should return a response with an Authorization (or custom) header containing an auth token
await client.post('/login', {username, password})

// all subsequent requests will automatically contain an Authorization (or custom) header with the token
const res = await client.get('/account')

The store config value can also be an object with functions read and write. In that case, read will take the storage key as an argument, and write will take both the storage key and token value. Either or both functions can return a simple value or a promise. In the example below, some tokens service is responsible both for generating the key that's used and for reading / writing to some other custom storage location.

import create, {bearerAuth} from 'relax-client'
import tokens from './services/tokens'

// the following all store an auth token in local storage
const authMiddleware = bearerAuth(tokens.getKey(), {
	store: {
		read: (k) => tokens.get(k),
		write: (k, v) => tokens.put(k, v),
	}
})

Gzip

A gzip middleware for compressing request bodies is available, but it uses Pako, which is too large a library to include by default. Given that, it's not exposed from the index file, so it will need to be explicitly loaded from the dist directory.

import create, {Client, json} from 'relax-client'
import gzip from 'relax-client/dist/middlewares/gzip'

const {get, post, put, destroy} = create(`https://api.test.com/v1`)
	.use(json())
	.use(gzip())