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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tni/http

v2.0.0

Published

Axios 请求封装

Downloads

112

Readme

@tni/http

基于 axios 的 HTTP 请求封装,设计风格参考 vben-admin,适合统一管理项目里的 API 调用行为。

内置能力包括:

  • 请求/响应拦截
  • 自动拼接 apiUrlurlPrefix
  • 自动注入 token
  • 重复请求取消
  • 统一响应转换
  • 401 未登录回调
  • GET/HEAD 请求失败重试
  • requestOptions 统一控制请求行为

安装

vp add @tni/http

导出内容

import {
  createAxios,
  defHttp,
  VAxios,
  HttpResponseError,
  type CreateAxiosOptions,
  type RequestOptions,
} from "@tni/http";

快速开始

import { createAxios } from "@tni/http";

const http = createAxios({
  requestOptions: {
    apiUrl: "https://api.example.com",
    urlPrefix: "/v1",
  },
  authentication: {
    getToken: () => localStorage.getItem("token") ?? undefined,
  },
});

// 默认返回 res.data,并自动兼容常见 { code, data/result, message } 响应结构
const data = await http.get<{ list: string[] }>({ url: "/demo" });

如何使用

1. 创建一个项目级 HTTP 实例

通常建议在业务项目中单独封装一个 http.ts,统一设置接口域名、前缀和鉴权逻辑。

import { createAxios } from "@tni/http";

export const http = createAxios({
  timeout: 10_000,
  requestOptions: {
    apiUrl: "https://api.example.com",
    urlPrefix: "/api",
  },
  authentication: {
    getToken: () => localStorage.getItem("token") ?? undefined,
    onUnauthorized: () => {
      localStorage.removeItem("token");
      window.location.href = "/login";
    },
  },
});

如果不需要自定义配置,也可以直接使用默认实例:

import { defHttp } from "@tni/http";

2. 发起 GET 请求

type User = {
  id: number;
  name: string;
};

const users = await http.get<User[]>({
  url: "/users",
  params: {
    page: 1,
    pageSize: 20,
  },
});

3. 发起 POST / PUT / DELETE 请求

await http.post({
  url: "/users",
  data: {
    name: "Alice",
  },
});

await http.put({
  url: "/users/1",
  data: {
    name: "Bob",
  },
});

await http.delete({
  url: "/users/1",
});

4. 覆盖单次请求配置

第二个参数可以传入 requestOptions,覆盖当前请求的行为。

const detail = await http.get(
  {
    url: "/users/detail",
    params: { id: 1 },
  },
  {
    withToken: false,
    joinTime: false,
    errorMessageMode: "none",
  },
);

5. 获取原始响应对象

默认情况下,@tni/http 返回的是转换后的业务数据。如果你需要状态码、响应头等原始响应信息,可以使用 request 并开启 isReturnNativeResponse

const response = await http.request<{ id: number; name: string }>(
  {
    url: "/users/1",
    method: "GET",
  },
  {
    isReturnNativeResponse: true,
  },
);

console.log(response.status);
console.log(response.data);

6. 处理业务错误

默认响应转换会把以下结构识别为业务响应:

{
  code: 0,
  data: {},
  message: "success"
}

或:

{
  code: 200,
  result: {},
  msg: "success"
}

code 不在成功码列表中时,会抛出 HttpResponseError

import { HttpResponseError } from "@tni/http";

try {
  await http.get({ url: "/users/1" });
} catch (error) {
  if (error instanceof HttpResponseError) {
    console.error(error.code);
    console.error(error.message);
    console.error(error.data);
  }
}

默认行为

createAxios() 默认配置如下:

| 配置项 | 默认值 | 说明 | | --------------------------------------- | -------------------------------- | ----------------------------- | | timeout | 10000 | 请求超时时间 | | headers["Content-Type"] | application/json;charset=utf-8 | 默认请求头 | | authentication.headerName | Authorization | token 请求头名称 | | authentication.tokenPrefix | Bearer | token 前缀 | | requestOptions.isJoinPrefix | true | 自动拼接 urlPrefix | | requestOptions.joinParamsToUrl | false | 是否把 params 直接拼到 URL | | requestOptions.formatDate | true | 自动把 Date 转成 ISO 字符串 | | requestOptions.joinTime | true | GET 请求自动追加时间戳 _t | | requestOptions.isTransformResponse | true | 自动处理业务响应结构 | | requestOptions.isReturnNativeResponse | false | 默认不返回原始响应对象 | | requestOptions.withToken | true | 默认自动带 token | | requestOptions.successCodes | [0, 200] | 业务成功码 | | requestOptions.errorMessageMode | "console" | 错误输出方式 |

常用配置说明

requestOptions

| 配置项 | 类型 | 说明 | | ------------------------ | --------------------------------------------- | ----------------------------------- | | apiUrl | string | 接口基础地址,会写入 baseURL | | urlPrefix | string | 接口公共前缀,如 /api/v1 | | isJoinPrefix | boolean | 是否自动拼接 urlPrefix | | joinParamsToUrl | boolean | 是否把 params 序列化到 URL 上 | | formatDate | boolean | 是否递归格式化 Date 为 ISO 字符串 | | joinTime | boolean | GET 请求是否自动追加时间戳参数 | | isTransformResponse | boolean | 是否启用默认响应转换 | | isReturnNativeResponse | boolean | 是否直接返回 Axios 原始响应 | | successMessageMode | "none" \| "console" \| "message" \| "modal" | 成功消息输出模式 | | errorMessageMode | "none" \| "console" \| "message" \| "modal" | 错误消息输出模式 | | ignoreCancelToken | boolean | 是否跳过重复请求取消逻辑 | | withToken | boolean | 是否自动注入 token | | successCodes | number[] | 业务成功码列表 | | retryRequest | RetryRequestOptions | 失败重试配置 |

authentication

| 配置项 | 类型 | 说明 | | ---------------- | --------------------------- | ------------------------ | | headerName | string | token 请求头名称 | | tokenPrefix | string | token 前缀,如 Bearer | | getToken | () => string \| undefined | 获取 token 的方法 | | onUnauthorized | (err: unknown) => void | 接口返回 401 时触发 |

进阶用法

自定义拦截与响应转换

可以通过 transform 扩展请求前处理、响应处理和错误处理逻辑。

const http = createAxios({
  transform: {
    beforeRequestHook: (config) => {
      config.headers = config.headers ?? {};
      config.headers["X-Trace-Id"] = crypto.randomUUID();
      return config;
    },
    responseInterceptors: (res) => {
      console.log("response status:", res.status);
      return res;
    },
  },
});

开启 GET 请求失败重试

重试仅对 GETHEAD 请求生效,且默认更适合处理网络异常或 5xx 错误。

const data = await http.get(
  {
    url: "/reports",
  },
  {
    retryRequest: {
      isOpenRetry: true,
      count: 2,
      waitTime: 1000,
    },
  },
);

取消当前实例下的全部待处理请求

http.cancelAllRequests();

适用的默认响应结构

默认转换逻辑会优先读取这些字段:

  • code
  • messagemsg
  • dataresult

也就是说,以下响应都能直接拿到业务数据:

const list = await http.get<string[]>({ url: "/list" });

后端返回:

{ "code": 0, "data": ["a", "b"], "message": "ok" }

或:

{ "code": 200, "result": ["a", "b"], "msg": "ok" }