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.
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/nixify@3.1.1/+esm'
</script>
- 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.
// 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);
}
}
Creates an instance of Nixify with predefined service configurations.
config
: An object containing service configurations.
NixifyInstance
: An instance of Nixify configured with the provided options.
const http = Nixify.create({
github: {
url: "https://api.github.com",
headers: {
"x-API-KEY": "[TOKEN]",
},
},
gitlab: {
url: "https://gitlab.com/api/v4/",
headers: {},
},
});
Prior to initiating a request for a particular service instance or globally, customize request headers or execute additional actions.
fn
: A callback function to be invoked right before a request.request
: A representation of the Request API, encapsulating HTTP configurations.config
: An object withNixifyInstance
configurations.
// 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");
});
Still under development.
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 withNixifyInstance
configurations.
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.
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.
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.
Before making a request for a specific service instance or globally, modify request headers.
headers
: An object containing headers.
// Set headers for a specific service instance
http.gitlab.setHeaders({ Authorization: `Bearer ${token}` });
// Set headers globally
http.setHeaders({ Authorization: `Bearer ${token}` });
// 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])
// 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;
}
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;
}
We welcome contributions! Feel free to open issues, submit pull requests, or provide feedback. Make sure to follow our contribution guidelines.
- @Omar Chadidi β€οΈ
This library is licensed under the MIT License.