Aspida
TypeScript friendly HTTP client wrapper for the browser and node.js.
Install / Use
/learn @aspida/AspidaREADME
aspida
<br /> <img src="https://aspida.github.io/aspida/logos/png/logo.png" alt="aspida" title="aspida" /> <div align="center"> <a href="https://www.npmjs.com/package/aspida"> <img src="https://img.shields.io/npm/v/aspida" alt="npm version" /> </a> <a href="https://www.npmjs.com/package/aspida"> <img src="https://img.shields.io/npm/dm/aspida" alt="npm download" /> </a> </div> <br /> <p align="center">TypeScript friendly HTTP client wrapper for the browser and node.js.</p> <div align="center"> <a href="https://github.com/aspida/aspida/tree/master/packages/aspida#readme">🇺🇸English</a> | <a href="https://github.com/aspida/aspida/tree/master/packages/aspida/docs/ja#readme">🇯🇵日本語</a> </div> <br /> <br />Features
- Path, URL query, header, body, and response can all specify the type
- FormData / URLSearchParams content can also specify the type
- HTTP client supports axios / fetch / node-fetch
Procedure
- Reproduce the endpoint directory structure in the "api" directory
- Export a Type alias named "Methods"
- Call "aspida" with npm scripts
- API type definition file "api/$api.ts" will be generated, so import the application and make an HTTP request
Getting Started
Installation (axios ver.)
-
Using npm:
$ npm install aspida @aspida/axios axios -
Using Yarn:
$ yarn add aspida @aspida/axios axios
Create "api" directory
$ mkdir api
Type helper DefineMethods
DefineMethods<> is helper type for defining Methods. In earlier aspida, user shuold define without checking for API definition.
If you already have aspida in your projects, you can easily use DefineMethods<> with surrounding your definition.
It is just an option whether to use DefineMethods<>.
Be aware of the limitation that DefineMethods<> can't detect extra meaningless properties.
Create an endpoint type definition file
-
GET: /v1/users/?limit={number}
-
POST: /v1/users
api/v1/users/index.tsimport type { DefineMethods } from "aspida"; type User = { id: number; name: string; }; export type Methods = DefineMethods<{ get: { query?: { limit: number; }; resBody: User[]; }; post: { reqBody: { name: string; }; resBody: User; /** * reqHeaders(?): ... * reqFormat: ... * status: ... * resHeaders(?): ... * polymorph: [...] */ }; }>; -
GET: /v1/users/${userId}
-
PUT: /v1/users/${userId}
api/v1/users/_userId@number/index.tsSpecify the type of path variable “userId” starting with underscore with “@number”
If not specified with @, the default path variable type is "number | string"import type { DefineMethods } from "aspida"; type User = { id: number; name: string; }; export type Methods = DefineMethods<{ get: { resBody: User; }; put: { reqBody: { name: string; }; resBody: User; }; }>;
Build type definition file
package.json
{
"scripts": {
"api:build": "aspida"
}
}
$ npm run api:build
> api/$api.ts was built successfully.
Make HTTP request from application
src/index.ts
import aspida from "@aspida/axios";
import api from "../api/$api";
(async () => {
const userId = 0;
const limit = 10;
const client = api(aspida());
await client.v1.users.post({ body: { name: "taro" } });
const res = await client.v1.users.get({ query: { limit } });
console.log(res);
// req -> GET: /v1/users/?limit=10
// res -> { status: 200, body: [{ id: 0, name: "taro" }], headers: {...} }
const user = await client.v1.users._userId(userId).$get();
console.log(user);
// req -> GET: /v1/users/0
// res -> { id: 0, name: "taro" }
})();
aspida official HTTP clients
Command Line Interface Options
<table> <thead> <tr> <th>Option</th> <th>Type</th> <th>Default</th> <th width="100%">Description</th> </tr> </thead> <tbody> <tr> <td nowrap><code>--config</code><br /><code>-c</code></td> <td><code>string</code></td> <td><code>"aspida.config.js"</code></td> <td>Specify the path to the configuration file.</td> </tr> <tr> <td nowrap><code>--watch</code><br /><code>-w</code></td> <td></td> <td></td> <td> Enable watch mode.<br /> Regenerate <code>$api.ts</code> according to the increase / decrease of the API endpoint file. </td> </tr> <tr> <td nowrap><code>--version</code><br /><code>-v</code></td> <td></td> <td></td> <td>Print aspida version.</td> </tr> </tbody> </table>Options of aspida.config.js
| Option | Type | Default | Description |
| -------------------- | ------------------------------------ | ------- | ----------------------------------------------------- |
| input | string | "api" | Specifies the endpoint type definition root directory |
| baseURL | string | "" | Specify baseURL of the request |
| trailingSlash | boolean | false | Append / to the request URL |
| outputEachDir | boolean | false | Generate $api.ts in each endpoint directory |
| outputMode (>=1.6.0) | "all" | "normalOnly" | "aliasOnly" | "all" | Output either get or $get for compression |
Node.js API
import { version, build, watch } from "aspida/dist/commands";
console.log(version()); // 0.x.y
build();
build("./app/aspida.config.js");
build({ input: "api1" });
build([
{ baseURL: "https://example.com/v1" },
{
input: "api2",
baseURL: "https://example.com/v2",
trailingSlash: true,
outputEachDir: true,
outputMode: "all",
},
]);
watch();
watch("./app/aspida.config.js");
watch({ input: "api1" });
watch([
{ baseURL: "https://example.com/v1" },
{
input: "api2",
baseURL: "https://example.com/v2",
trailingSlash: true,
outputEachDir: true,
outputMode: "all",
},
]);
Ecosystem
- openapi2aspida - Convert OpenAPI 3.0 and Swagger 2.0 definitions
- aspida-mock - TypeScript friendly RESTful API mock
- frourio - Fast and type-safe full stack framework, for TypeScript TypeScript
- @aspida/react-query - React Query wrapper
- @aspida/swr - SWR (React Hooks) wrapper
- @aspida/swrv - SWRV (Vue Composition API) wrapper
- eslint-plugin-aspida - Support writing aspida api definition
Tips
- Change the directory where type definition file is placed to other than "api"
- Serialize GET parameters manually
- POST with FormData
- POST with URLSearchParams
- Receive response with ArrayBuffer
- Define polymorphic request
- Define endpoints that contain special characters
- Import only some endpoints
- Retrieve endpoint URL string
- Reflect TSDoc comments
<a id="tips1"></a>
Change the directory where type definition file is placed to other than "api"
Create a configuration file at the root of the project
aspida.config.js
module.exports = { input: "src" };
Specify baseURL in configuration file
module.exports = { baseURL: "https://example.com/api" };
If you want to define multiple API endpoints, specify them in an array
module.exports = [{ input: "api1" }, { input: "api2", baseURL: "https://example.com/api" }];
<a id="tips2"></a>
Serialize GET parameters manually
aspida leaves GET parameter serialization to standard HTTP client behavior
If you want to serialize manually, you can use config object of HTTP client
src/index.ts
import axios from "axios";
import qs from "qs";
import aspida from "@aspida/axios";
import api from "../api/$api";
(async () => {
const client = api(
aspida(axios, { paramsSerializer: params => qs.stringify(params, { indices: false }) })
);
const users = await client.v1.users.$get({
// config: { paramsSerializer: (params) => qs.stringify(params, { indices: false }) },
query: { ids: [1, 2, 3] },
});
console.log(users);
// req -> GET: /v1/users/?ids=1&ids=2&ids=3
// res -> [{ id: 1, name: "taro1" }, { id: 2, name: "taro2" }, { id: 3, name: "taro3" }]
})();
<a id="tips3"></a>
POST with FormData
api/v1/users/index.ts
import type { DefineMethods } from "aspida";
import type { ReadStream } from "fs";
export type Methods = DefineMethods<{
post: {
reqFormat: FormData;
reqBody: {
name: string;
icon: File | ReadStream;
};
resBody: {
id: number;
name: string;
};
};
}>;
src/index.ts
import aspida from "@aspida/axios";
import api from "../api/$api";
(async () => {
const client = api(aspida());
const user = a
Related Skills
node-connect
348.0kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
108.8kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
Writing Hookify Rules
108.8kThis skill should be used when the user asks to "create a hookify rule", "write a hook rule", "configure hookify", "add a hookify rule", or needs guidance on hookify rule syntax and patterns.
review-duplication
100.2kUse this skill during code reviews to proactively investigate the codebase for duplicated functionality, reinvented wheels, or failure to reuse existing project best practices and shared utilities.
