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

@xirang/request

v1.0.0

Published

HTTP request utilities for xirang tools project

Readme

@xirang/request

xirang 工具项目的 HTTP 请求库,基于 axios 构建,支持插件化扩展、多传输层与常见请求场景。

安装

pnpm add @xirang/request

快速开始

xirang 业务场景(推荐)

内置 token / app_id 注入与 { code, data } 响应解包,适用于 xirang 各应用:

import { createRequest } from '@xirang/request';

const client = createRequest({
  baseURL: '/api',
  errorNotify(code, message) {
    console.error(code, message);
  },
});

// 通用请求(studio 等项目中的常见用法)
export const http = client.request;

interface User {
  id: string;
  name: string;
}

const users = await http<User[]>('/users', {
  method: 'GET',
  params: { page: 1 },
});

纯净客户端

不含 xirang 业务逻辑,适合通用场景或自定义插件:

import { createClient } from '@xirang/request';

const client = createClient({
  baseURL: 'https://api.example.com',
  timeout: 10_000,
});

const users = await client.get<User[]>('/users', { params: { page: 1 } });
await client.post('/users', { name: '张三' });
await client.patch('/users/1', { name: '李四' });
await client.delete('/users/1');

架构

传输层 (axios / fetch / http2)
    ↓
核心客户端 (createClient)
    ↓
插件层 (retry / cache / dedupe / 自定义)
    ↓
预设层 (xirangPreset — token / 响应解包)

创建实例

createRequest

含 xirang 业务预设:

import { createRequest } from '@xirang/request';

const client = createRequest({
  baseURL: '/api',
  timeout: 10_000,
  errorNotify: (code, message) => { /* toast 通知 */ },
});

await client.get<User[]>('/users', { params: { page: 1 } });
await client.request<User>('/users', { method: 'GET', params: { page: 1 } });

createClient

无业务预设,通过插件组合能力:

import {
  createClient,
  xirangPreset,
  retryPlugin,
  cachePlugin,
  createMemoryCacheStore,
} from '@xirang/request';

const client = createClient({
  baseURL: '/api',
  transport: 'fetch', // 'axios' | 'fetch' | 'http2'
  plugins: [
    cachePlugin({ ttl: 60_000, store: createMemoryCacheStore() }),
    retryPlugin({ times: 3, delay: 1000, backoff: 2 }),
    xirangPreset({ errorNotify: (code, msg) => console.error(code, msg) }),
  ],
  dedupe: { methods: ['GET'] }, // 并发去重,设为 false 可禁用
});

插件数组中越靠前越靠近传输层。推荐顺序:cache → retry → xirangPreset

请求方法

| 方法 | 说明 | |------|------| | request(url, options) | 通用请求 | | get / post / put / patch / delete | REST | | head / options | HTTP 探测 | | upload(url, data, options?) | 文件上传(FormData / multipart) | | download(url, options?) | 文件下载(blob / stream 等) | | graphql(url, query, variables?, options?) | GraphQL | | postForm(url, data, options?) | application/x-www-form-urlencoded |

// 上传
await client.upload('/upload', formData, {
  onUploadProgress: (e) => console.log(e.loaded / e.total!),
});

// 下载
const blob = await client.download<Blob>('/file.pdf', {
  responseType: 'blob',
  onDownloadProgress: (e) => console.log(e.loaded),
});

// GraphQL
const data = await client.graphql<{ user: User }>(
  '/graphql',
  `query GetUser($id: ID!) { user(id: $id) { name } }`,
  { id: '1' },
);

// 表单
await client.postForm('/login', { username: 'admin', password: '123' });

插件

retryPlugin — 失败重试

import { retryPlugin } from '@xirang/request';

retryPlugin({
  times: 3,       // 最大重试次数,默认 3
  delay: 1000,    // 初始延迟(ms),默认 1000
  backoff: 2,     // 退避系数,默认 2
  statuses: [408, 429, 500, 502, 503, 504],
  retryOn: (error, attempt) => true, // 自定义重试条件
});

cachePlugin — GET 缓存

import { cachePlugin, createMemoryCacheStore } from '@xirang/request';

const store = createMemoryCacheStore();

cachePlugin({
  ttl: 60_000,           // 缓存有效期(ms),默认 60_000
  methods: ['GET'],      // 参与缓存的方法
  store,                 // 自定义存储
});

并发去重

默认对 GET 请求启用:相同 method + url + params 的进行中请求共享同一个 Promise。

import { withDedupe, clearDedupeCache } from '@xirang/request';

// 通过 createClient 配置
createClient({ dedupe: { methods: ['GET'] } });
createClient({ dedupe: false }); // 禁用

SSE 流式请求

import { createSSE, Stream } from '@xirang/request/sse';

// 拉取 SSE 流
for await (const event of await createSSE('/api/chat/stream')) {
  console.log(event.data);
}

// 解析已有 ReadableStream
const stream = Stream({ readableStream: response.body! });
for await (const event of stream) {
  console.log(event);
}

子路径导出

| 路径 | 内容 | |------|------| | @xirang/request | 主入口 | | @xirang/request/fetch | Fetch 中间件 + createFetchRequest | | @xirang/request/http2 | createHttp2Request(Node.js,实验性) | | @xirang/request/sse | Stream + createSSE | | @xirang/request/graphql | GraphQL 工具函数 | | @xirang/request/form | 表单编码工具 | | @xirang/request/presets/xirang | xirang 业务预设 |

// fetch 适配器
import { createFetchRequest } from '@xirang/request/fetch';

const client = createFetchRequest({ baseURL: '/api' });

// HTTP/2(Node.js)
import { createHttp2Request } from '@xirang/request/http2';

const client = createHttp2Request({ baseURL: 'https://api.example.com' });

// 原生 fetch 中间件
import { Fetch } from '@xirang/request/fetch';

const response = await Fetch('/api/data', {
  middlewares: {
    onRequest: async (...args) => args,
    onResponse: async (res) => res,
  },
});

API 参考

createRequest(config?: CreateRequestConfig)

创建含 xirang 预设的请求实例。

interface CreateRequestConfig extends ClientConfig {
  errorNotify?: (code: number, message: unknown) => void;
}

createClient(config?: ClientConfig)

创建插件化请求客户端。

interface ClientConfig extends AxiosRequestConfig {
  transport?: 'axios' | 'fetch' | 'http2';
  plugins?: RequestPlugin[];
  dedupe?: DedupeOptions | false;
  httpVersion?: 1 | 2;
  http2Options?: Http2Options;
}

RequestInstance

interface RequestInstance {
  instance: AxiosInstance;
  request: <T>(url: string, options?: RequestMethodOptions) => Promise<T>;
  get: <T>(url: string, options?) => Promise<T>;
  post: <T>(url: string, data?, options?) => Promise<T>;
  put / patch / delete / head / options: ...;
  upload: <T>(url, data, options?) => Promise<T>;
  download: <T>(url, options?) => Promise<T>;
  graphql: <T>(url, query, variables?, options?) => Promise<T>;
  postForm: <T>(url, data, options?) => Promise<T>;
}

RequestPlugin

interface RequestPlugin {
  onRequest?: (config) => config | Promise<config>;
  onRequestError?: (error) => unknown;
  onResponse?: (response) => response | Promise<response>;
  transformResponse?: (response) => unknown;
  onResponseError?: (error) => unknown;
  wrapExecutor?: <T>(config, executor) => Promise<T>;
}

特性

  • 分层架构 — 传输层 / 核心 / 插件 / 预设,按需组合
  • xirang 开箱即用 — token、app_id、响应解包内置
  • REST 全覆盖 — GET / POST / PUT / PATCH / DELETE / HEAD / OPTIONS
  • 文件传输 — upload / download,支持进度回调
  • GraphQL / Form — 内置 graphql、postForm 方法
  • SSE 流式 — Server-Sent Events 解析与拉流
  • 插件扩展 — retry(指数退避)、cache(GET 缓存)、dedupe(并发去重)
  • 多传输层 — axios(默认)、fetch、http2(Node.js)

开发

使用 tsdown 打包,配置见 tsdown.config.ts

pnpm install
pnpm build      # tsdown
pnpm dev        # tsdown --watch
pnpm lint
pnpm check-types
pnpm test
pnpm test:run
pnpm test:coverage

许可证

MIT

相关链接