Rests API Client SDK Generator
Rests is a JavaScript/TypeScript library designed to streamline and centralize HTTP API requests by enabling the generation of a structured API client SDK. It empowers developers to define API endpoints, methods, and parameters in a declarative, JSON-like configuration, thereby establishing a single source of truth for all API interactions. Key features include a robust configuration system that facilitates advanced handling of validation, authentication, and request/response hooks, alongside a powerful mechanism for complex inheritance that allows for the categorization of requests to prevent repetition. A significant differentiator is its capability to automatically generate TypeScript types for the defined API, enhancing developer experience and ensuring type safety. Additionally, it supports schema definition from pure JSON and can generate basic markdown API references. Rests offers universal compatibility, functioning seamlessly across both browser and Node.js environments. The current stable version is 1.1.1. While a specific release cadence is not explicitly detailed, the project appears to be under active development, evidenced by mentions of a 'Private edition' offering expanded functionalities. Its primary distinction lies in transforming a simple, declarative API definition into a fully-fledged, strongly-typed, and object-oriented API client, significantly simplifying network communication compared to direct `fetch` or `axios` implementations.
Common errors
-
TypeError: Rests is not a function
cause Attempting to call the `rests` module object directly when using CommonJS `require()`, instead of its default export.fixEnsure you are importing the default export: `const Rests = require('rests').default;` -
The password must be at least 8 characters.
cause A request parameter failed a custom `format` or `validate` function defined in the API schema for that specific parameter.fixEnsure all required parameters meet the specified validation and formatting rules before making the API call. Refer to the API schema definition for the specific endpoint. -
ReferenceError: API is not defined
cause The API client instance (`API` in examples) was not correctly initialized, exported, or imported before being used in the current scope.fixVerify that `const API = Rests({...});` has been executed and the `API` object is properly exported from its definition file and imported where it's being used. -
Error: Request failed with status code 401
cause The API request received an HTTP error response, commonly due to missing or invalid authentication credentials (e.g., an expired token) or other server-side issues.fixImplement proper error handling with a `.catch()` block on your API calls. Inspect `err.statusCode`, `err.json`, or `err.message` for details. Ensure authentication tokens are correctly set, potentially through category `$options` or when initializing a specific API category.
Warnings
- gotcha When using CommonJS (`require`), you must explicitly access the `.default` property of the module export to correctly import the Rests factory function. Failing to do so will result in `TypeError: Rests is not a function` or similar issues.
- gotcha Specific advanced features, such as Python API generation with type hints and the creation of comprehensive documentation websites, are explicitly marked as 'Private edition only' and are not included in the public npm package. Users should not expect these functionalities out-of-the-box.
- gotcha While `rests` can be installed as a local dependency for project-level usage, its command-line interface (CLI) for generating types and documentation requires a global installation (`npm i rests -g`) or invocation via `npx`. Forgetting to install globally is a common reason for CLI commands failing.
Install
-
npm install rests -
yarn add rests -
pnpm add rests
Imports
- Rests
import { Rests } from 'rests';import Rests from 'rests';
- Rests (CommonJS)
const Rests = require("rests");const Rests = require("rests").default; - RestsAPISchema
import { RestsAPISchema } from 'rests';import type { RestsAPISchema } from 'rests';
Quickstart
import Rests from 'rests';
// Define your API schema with endpoints, methods, and validation rules
const APIBuilder = Rests({
$options: {
base: 'https://api.example.com' // Set the base URL for all requests
},
user: {
login: {
path: '/user/login',
method: 'POST',
params: {
username: {
required: true,
type: "string",
help: "A valid username is required",
validate: /^[a-zA-Z0-9_]+$/ // Example validation for alphanumeric username
},
password: {
required: true,
help: "A valid password is required",
type: "string",
format: (password: string) => {
if (password.length < 8) {
throw new Error("The password must be at least 8 characters.");
}
return password;
}
}
}
},
profile: {
$options: {
// Set authentication parameters for all requests in this category
params: {
authorization: { type: "string", required: true }
}
},
info: {
path: '/user/profile/info',
method: 'GET'
},
update: {
path: '/user/profile/update',
method: 'POST',
params: {
email: { type: "string", format: (email: string) => email.toLowerCase() }
}
}
}
}
});
// The API client is ready to use
const API = APIBuilder;
// Example 1: Successful login call
API.user.login({
username: 'john.doe',
password: 'supersecurepassword123'
})
.then((res) => {
console.log('Login successful, response body:', res.json);
})
.catch((err) => {
console.error('Login failed:', err.json || err.message);
});
// Example 2: Calling an endpoint with a validation error
API.user.login({
username: 'testuser',
password: 'short' // This will trigger the password format validation error
})
.catch((err) => {
console.log('Validation Error:', err.field, err.message);
// Expected output: "Validation Error: password The password must be at least 8 characters."
});
// Example 3: Initializing a category with specific options (e.g., authorization)
const UserAPI = new API.user({
authorization: 'my_user_auth_token_xyz'
});
UserAPI.profile.info()
.then((res) => console.log('User profile info retrieved:', res.json))
.catch((err) => console.error('Failed to get user profile:', err.message));