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

nixify

v3.1.2

Published

Nixify is a tiny JavaScript HTTP client based on browser Fetch API.

Downloads

8

Readme

Nixify HTTP Client Library

Nixify is a lightweight and minimalistic JavaScript HTTP client based on the browser's Fetch API with no dependencies. It's designed for simplicity and ease of use in browser environments, providing a concise API for making HTTP requests to various services.

Installation

Package manager

Using npm:

npm install nixify

Using pnpm:

pnpm add nixify

Using yarn:

yarn add nixify

To import Nixify you have to use ECMAScript

import Nixify from "nixify";

Using jsdelivr:

<script type="module">
  import nixify from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm'
</script>

Nixify Features

  • Lightweight: Minimalistic HTTP client designed for simplicity.
  • First-class TypeScript Support: Developed entirely in TypeScript for a robust experience.
  • Fetch API Integration: Built on the browser's Fetch API for HTTP requests.
  • Shortcut Methods: Shorthand methods like Nixify.get().text() for readability.
  • Retry Request: automatic retry of failed requests based on status codes.
  • Configurable Services: Easily configure instances for different services.
  • Header Management: Set headers globally or for specific instances.
  • Dynamic Route Matching with Params: Support for dynamic route matching with parameters.
  • Hooks: Execute functions before/after requests, with a beforeRetry hook.
  • Automatic JSON Handling: Streamlined interaction with JSON responses.
  • Cancel Requests: Efficiently manage ongoing requests.
  • Concise API: Simple and easy-to-use for handling HTTP requests.

Usage

// Create an instance of Nixify with predefined services
const http = Nixify.create({
  github: {
    url: "https://api.github.com",
    headers: {
      "x-API-KEY": "[TOKEN]",
    },
  },
  gitlab: {
    url: "https://gitlab.com/api/v4",
	retryConfig: {
		retries: 4,
		retryOn: [400] // default statusCodes retryOn [408, 413, 429, 500, 502, 503, 504]
		retryDelay: 2000 // ms
	}

  },
});

// Set headers for a specific service instance
http.gitlab.setHeaders({ Authorization: `Bearer ${token}` });

// Set headers globally
http.setHeaders({ Authorization: `Bearer ${token}` });

// Set headers before making a request for a specific service instance
http.gitlab.beforeRequest((request, config) => {
  // Modify request headers or perform other actions
});

// Set headers globally before making a request
http.beforeRequest((request, config) => {
  request.headers.set("Content-type", "application/json");
});

// Will be called right after response
http.gitlab.afterResponse((request, response config) => {});
http.afterResponse((request, response config) => {});

// Will be called right before retry
http.beforeRetry((request, response, attempt, delay) => {});
http.gitlab.beforeRetry((request, response, attempt, delay) => {});


// Retry custom behavior
const { data, status } = await http.gitlab.get("/projects/:id/registry/repositories", {
	params: { id: 5645 } // /projects/5645/registry/repositories
	retry: {
		retryOn(attempt, response) {
			// Should stop retry by returning false
			if (attempt > 3) return false

			// retry on 4xx or 5xx status codes
			if (response.status >= 400) {
				console.log(`retrying, attempt number ${attempt + 1}`);
				return true;
			}
		}
	}
}).json();

// TypeScript Version
interface Repositories {}
const { data } = await http.gitlab.get<Repositories>("/search/repositories").json();

// Javascript Version
const { data, config } = await http
  .get("https://api.github.com/search/repositories", { headers: {} })
  .json();

const { data, status } = await http.github.get("/search/repositories").json();

/**
 * If the body of the HTTP request is an instance of URLSearchParams,
 * The Content-Type is set automatically by `fetch`, 
 * so we didn't have to explicit set it to 'application/x-www-form-urlencoded;charset=utf-8'.
 */
const searchParams = new URLSearchParams();
searchParams.set('food', 'sushi 🍣');
searchParams.set('drink', 'Bubble Tea 🧋');

const { data } = await http.post(path, { body: searchParams })

/**
 * `fetch` automatically sets the Content-Type header,
 *  So we didn't have to explicit set it to 'multipart/form-data; boundary=---....'
 */
const formData = new FormData();
formData.append('username', 'superAdmin');
formData.append('password', 'admin1234');

const { data } = await http.post(path, { body: formData })

/**
 * Cancellation
 */
const controller = new AbortController();
const { signal } = controller;

setTimeout(() => {
	controller.abort();
}, 5000);

try {
	await http.get(url, { signal }).text();
} catch (error) {
	if (error.name === 'AbortError') {
		console.log('Fetch aborted');
	} else {
		console.error('Fetch error:', error);
	}
}

API DOCUMENTATION

Nixify.create(config: { [name: string]: Options }): ServiceReqMethods | RequestMethods

Creates an instance of Nixify with predefined service configurations.

Parameters:
  • config: An object containing service configurations.
Returns:
  • NixifyInstance: An instance of Nixify configured with the provided options.
Example:
const http = Nixify.create({
  github: {
    url: "https://api.github.com",
    headers: {
      "x-API-KEY": "[TOKEN]",
    },
  },
  gitlab: {
    url: "https://gitlab.com/api/v4/",
    headers: {},
  },
});
Nixify.beforeRequest(fn: (request: Request, config: Options) => void)
Nixify.{service}.beforeRequest(fn: (request: Request, config: Options) => void)

Prior to initiating a request for a particular service instance or globally, customize request headers or execute additional actions.

Parameters:
  • fn: A callback function to be invoked right before a request.
    • request: A representation of the Request API, encapsulating HTTP configurations.
    • config: An object with NixifyInstance configurations.
Example:
// Set headers before making a request for a specific service instance
http.gitlab.beforeRequest((request, config) => {
  // Modify request headers or perform other actions
});

// Set headers globally before making a request
http.beforeRequest((request, config) => {
  request.headers.set("Content-type", "application/json");
});
Nixify.afterResponse(fn: (request: Request, response: Response, config: Options) => void)
Nixify.{service}.afterResponse(fn: (request: Request, response: Response config: Options) => void)

Still under development.

Parameters:
  • fn: A callback function to be invoked right after a response.
    • request: A representation of the Request API, encapsulating HTTP configurations.
    • response: A representation of the Response API.
    • config: An object with NixifyInstance configurations.
Example:
http.gitlab.afterResponse((request, config) => {});
http.afterResponse((request, config) => {});
Nixify.beforeRetry(fn: (request: Request, response: Response, attempt: number, delay: number) => void)
Nixify.{service}.beforeRetry(fn: (request: Request, response: Response, attempt: number, delay: number) => void)

Registers a function to be executed before a fetch retry attempt within the Nixify service.

Parameters:

  • fn: A callback function to be invoked before a retry attempt.
    • request: A representation of the Request API, encapsulating HTTP configurations.
    • response: A representation of the Response API.
    • attempt: The number of the retry attempt.
    • delay: The delay before the next retry attempt.

Example:

http.beforeRetry((request, response, attempt, delay) => {
  if(response.status === 401) {
	const { data } = await http.get("/refresh-token").json()

	request.headers.set("X-API-KEY", data.token)
  }
});

http.{service}.beforeRetry((request, response, attempt, delay) => {
  // Your logic here
});

This method allows you to register a callback function that will be called before each retry attempt within the Nixify service. The callback function receives information about the request, response, the current attempt number, and the delay before the next retry.

Nixify.setHeaders(headers: { [key: string]: string })
Nixify.{service}.setHeaders(headers: { [key: string]: string })

Before making a request for a specific service instance or globally, modify request headers.

Parameters:
  • headers: An object containing headers.
Example:
// Set headers for a specific service instance
http.gitlab.setHeaders({ Authorization: `Bearer ${token}` });

// Set headers globally
http.setHeaders({ Authorization: `Bearer ${token}` });

Request method aliases

// We provided supported for all request methods.
http.get<T>(url | path, options?) // Returns an Object of callable type-setters methods.
// instead of `responseType`.
  json() // By default
  text()
  blob()
  arrayBuffer()
  formData()
http.delete(url | path, options?)

http.head(url | path, options?)

http.options(url | path, options?)

http.post(url[, body or json])

http.put(url[, body or json])

http.patch(url[, body or json])
Request Config
// These are the available `options?` for making requests. Only the url is required.
interface Options {
  url: string
  headers?: { [key: string]: string }
  hooks?: {
	beforeRequest: (request: Request) => void
	afterResponse: (request: Request, response: Response, config: any) => void
	beforeRetry: (request: Request, response: Response, attempt: number, delay: number) => void
  }
  qs?: {
	readonly strict?: boolean
	readonly encode?: boolean
	readonly arrayFormat?:
		| "bracket"
		| "index"
		| "comma"
		| "separator"
		| "bracket-separator"
		| "colon-list-separator"
		| "none"
	readonly arrayFormatSeparator?: string
	readonly sort?: ((itemLeft: string, itemRight: string) => number) | false
	readonly skipNull?: boolean
	readonly skipEmptyString?: boolean
  }
  timeout?: number | false
  retryConfig?: {
	retries?: number | boolean
	retryDelay?: number | (attempt: number, response: Response | null) => number
	retryOn?: number[] | (attempt: number, response: Response | null) => boolean | Promise<boolean> 
  }
}

// https://developer.mozilla.org/en-US/docs/Web/API/Request/Request#options
interface MethodConfig extends Omit<RequestInit, "method"> {
  // URL parameters to be sent with the request
  // (e.g http.get(path, { qs: { name: "Joe" } }) = path?name=Joe )
  qs?: { [name: string]: string | URLSearchParams | Record<string, string> | string[][] }
  // "/groups/:id/registry/repositories" - { id: 4873 }
  // "/groups/4873/registry/repositories"
  params?: { [key: string]: string | number }
  // `headers` are custom headers to be sent.
  headers?: Object;
  // `json` to send body as Content-Type JSON.
  json?: Object;
  //  `body` to send data under one of these types -
  body?:
    | Blob
    | BufferSource
    | FormData
    | URLSearchParams
    | USVString
    | ReadableStream;
  // `responseType` indicates the type of data that the server will respond with.
  responseType?: "json" | "text" | "blob" | "arrayBuffer" | "formData";
  timeout?: number | false
  retry?: {
	retries?: number | boolean
	retryDelay?: number | (attempt: number, response: Response | null) => number
	retryOn?: number[] | (attempt: number, response: Response | null) => boolean | Promise<boolean> 
  }
  // To cancel request using AbortController
  signal?: AbortController;
}

Response Schema

The response for a request contains the following information.

interface ResponseInterface<T> {
  // `data` is the response that was provided by the server
  data: T;
  // `headers` the HTTP headers that the server responded with
  // All header names are lower cased and can be accessed using the bracket notation.
  // Example: `response.headers['content-type']`
  headers: Headers;
  // `status` is the HTTP status code from the server response
  status: number;
  // `statusText` is the HTTP status message from the server response
  statusText: string;
  // `config` is the config that was provided to the request
  config: Request;
}

Contributing

We welcome contributions! Feel free to open issues, submit pull requests, or provide feedback. Make sure to follow our contribution guidelines.

Authors

License

This library is licensed under the MIT License.