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 🙏

© 2025 – Pkg Stats / Ryan Hefner

soon-fetch

v3.1.2

Published

a request lib alternative to axios with timeout, request reusing, race, response cache ...

Readme

English | 中文 | Installation

soon-fetch

A lightweight http request lib , alternative to axios with timeout, request reusing, race, response cache ...

  • 🌐 automatic parse restful api url parameters
  • ⭐ rapid define a request api
  • ⌛ timeout disconnect
  • 📦 request reusing
  • 🚀 request race
  • 📝 response cache
  • 🔤 automatic serialization of JSON
  • 📏 .min size less than 6K, smaller after zip
  • 💡 smart type tips with Typescript

Example

github: soon-admin-vue3
github: soon-admin-react-nextjs

import { createSoon } from "soon-fetch";

const soon = createSoon(
  (url, options) => {
    const isGet = !options?.method || options?.method.toLocaleLowerCase() === "get"
    return {
      baseURL: '/api',
      baseOptions: {
        timeout: 20 * 1000,
        headers: new Headers({
          Authorization: "Bearer " + localStorage.getItem("token"),
        }),
        share: isGet ? true : false,
        staleTime: isGet ? 2 * 1000 : 0,
      },
    }
  },
  ({ parsed }) => {
    return <T>() => {
      return fetch(parsed.url, parsed.options).then((res) =>
        res.json()
      ) as Promise<T>;
    };
  }
);

/** GET */
soon.get("/user?id=123");
soon.get("/user", { query: { id: 123 } });
soon.get("/user/:id", { params: { id: 123 } });

/** POST */
soon.post("/login", { body: { username: "admin", password: "123456" } });

/**Define API */
export const login = soon
  .POST("/user/login")
  .Body<{ username: string; password: string }>()
  .Send<{ token: string }>();
//the develop tools will have type tips for request and response
login({ username: "admin", password: "123" }).then((res) => {
  localStorage.setItem("token", res.token);
});

Features

Shortcut
soon.get(url, options);
soon.post(url, options);
soon.put(url, options);
soon.patch(url, options);
soon.delete(url, options);
soon.head(url, options);
soon.options(url, options);
Restful Url Params

url like /:key , will handle the key

soon.get("/api/user/:id", { params: { id: 1 } });
// api/user/1
soon.get("/api/:job/:year", { params: { job: "engineer", year: 5 } });
//api/engineer/5
Timeout
//** the request level timeout, will override the instance level timeout  */
soon.get(url, { timeout: 1000 * 20 });
Share pending request

If a request is made again before the first completes, will reuse the first request instead of making a new request.

soon.get(url, { share: true });
Response cache

A cached response will be returned if the request is made again within the specified time.

soon.get(url, { staleTime: 1000 * 60 * 5 });
Request race

‌If a second request is made before the first completes, abort the first to avoid race conditions from out-of-order responses.

import { useEffect, useRef, useState } from "react";

type User = { name: string; job: string };
const api = soon.GET("/api/users").Query<{ page: number }>().Send<User[]>();
export default function App() {
  const refAbort = useRef([]);
  const [list, setList] = useState<User[]>([]);
  const [page, setPage] = useState(1);
  useEffect(() => {
    api({ page }, { aborts: refAbort.current })
      .then(setList)
      .catch(console.log);
  }, [page]);
  return (
    <div>
      <button onClick={() => setPage((pre) => pre + 1)}>next</button>
      <div>
        {list.map((item) => (
          <div key={item.name}>{item.name}</div>
        ))}
      </div>
    </div>
  );
}
Rapid Define APIs
//can be GET POST PATCH PUT DELETE
  soon.GET(url:string).Query<Query>().Send<Response>()
  soon.POST(url:string).Body<Body>().Send<Response>()
//define an api
export const getUserInfo = soon.GET("/user/:id").Send();
//then use in any where
getUserInfo({ id: 2 }).then((res) => console.log(res));

//with typescript,
export const login = soon
  .POST("/user/login")
  .Body<{ username: string; password: string }>()
  .Send<{ token: string }>();
//the develop tools will have type tips for request and response
login({ username: "admin", password: "123" }).then((res) => {
  localStorage.setItem("token", res.token);
});

API

SoonOptions

// function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>
// RequestInit  is fetch's init options
type SoonOptions = Omit<RequestInit, "body"> & {
  body?: RequestInit["body"] | object;
  query?:
    | Record<
        string,
        | string
        | number
        | boolean
        | null
        | undefined
        | (string | number | boolean | null | undefined)[]
      >
    | URLSearchParams;
  params?: Record<string, string | number>;
  timeout?: number;
  aborts?: AbortController[] | never[];
  share?: boolean;
  staleTime?: number;
};

createSoon

Create a soon request instance.

Parameters:

  • getConfig: A function to get request configuration, receives url and options, returns an object containing url, options, baseURL, and baseOptions
  • wrapper: A wrapper function to handle request logic

Returns: An object containing request method and various shortcut methods

Example:

const soon = createSoon(
  (url, options) => ({ url, options,baseURL:'/api', baseOptions:{timeout: 5000} }),
  ({ parsed }) =>
    async (url, options) => {
      const response = await fetch(parsed.url, parsed.options);
      return response.json();
    }
);

// Usage example
const data = await soon.get("/api/users");

createShortApi

Factory function to create API shortcut methods. Used to generate type-safe API calling methods, supporting path parameters, query parameters, and request body.

Parameters:

  • wrapper: Wrapper function to handle actual request logic

Returns: An object containing GET, POST, PUT, DELETE, PATCH and other methods, each method supports chain calling

Example:

const API = createShortApi(
  async (url, method, params, query, body, options) => {
    // Handle request logic
    const _url = mergeUrl(url, { params, query });
    const response = await fetch(_url, { ...options, method, body });
    return response.json();
  }
);

// Usage example
const getUser = API.GET("/api/users/:id").Send();
const userData = await getUser({ id: 1 });

createShortMethods

Factory function to create shortcut methods.

Parameters:

  • methods: HTTP methods array
  • wrapper: Wrapper function that receives method name and returns a function to process requests

Returns: Shortcut call object containing specified methods

Example:

const methods = createShortMethods(["get", "post"], (method) => {
  return (url, options) => fetch(url, { ...options, method });
});
// Usage: methods.get('/api/users')

parseUrlOptions

Parse URL options.

Parameters:

  • urlOptions: Object containing url, options, baseURL and baseOptions

Returns: Tuple of processed url and options

Example:

const [url, options] = parseUrlOptions({
  url: "/api/users/:id",
  options: { params: { id: "123" } },
  baseURL: "https://api.example.com",
});
// Returns: ['https://api.example.com/api/users/123', options]

mergeHeaders

Merge multiple Headers objects.

Parameters:

  • headersList: List of Headers objects to merge

Returns: Merged Headers object, later ones will overwrite earlier ones with the same name

Example:

const headers1 = { "Content-Type": "application/json" };
const headers2 = { Authorization: "Bearer token" };
const mergedHeaders = mergeHeaders(headers1, headers2);

mergeSignals

Merge multiple AbortSignal signals.

Parameters:

  • signals: Array of AbortSignals to merge
  • timeout: Optional timeout time (milliseconds)

Returns: Merged AbortSignal, any signal termination will trigger termination

Example:

const controller1 = new AbortController();
const controller2 = new AbortController();
const mergedSignal = mergeSignals(
  [controller1.signal, controller2.signal],
  5000
);

mergeUrl

Merge URL and its related parameters. Handle baseURL, path parameters and query parameters to generate complete URL.

Parameters:

  • url: Original URL
  • config: Configuration object, including query parameters, path parameters and base URL

Returns: Processed complete URL

Example:

const url = mergeUrl("/api/users/:id", {
  params: { id: "123" },
  query: { filter: "active" },
  baseURL: "https://api.example.com",
});
// Returns: 'https://api.example.com/api/users/123?filter=active'

mergeOptions

Merge multiple option objects. Merge request options, including special handling of headers and signals.

Parameters:

  • optionsList: List of option objects to merge

Returns: Merged option object

Example:

const defaultOptions = {
  timeout: 5000,
  headers: { "Content-Type": "application/json" },
};
const requestOptions = {
  method: "POST",
  body: JSON.stringify({ name: "John" }),
};
const mergedOptions = mergeOptions(defaultOptions, requestOptions);

isBodyJson

Determine if the request body is a JSON object. Check if body is a plain object, not special types like FormData or Blob.

Parameters:

  • body: Request body

Returns: Returns true if it is a JSON object, otherwise false

Example:

isBodyJson({ name: "John" }); // true
isBodyJson(new FormData()); // false
isBodyJson("string"); // false

genRequestKey

Generate a unique identification key for the request. Generate a unique key value based on the request's URL, method, headers, body, query parameters, etc., used for caching and request sharing.

Parameters:

  • req: Request object containing url and options

Returns: Unique identification string of the request

Example:

const key = genRequestKey({
  url: "/api/users",
  options: { method: "GET", params: { id: 1 } },
});

raceAbort

Race condition handling function. Used to handle request race conditions, terminating previous requests.

Parameters:

  • abortController: Controller of the current request
  • controllers: Array of existing controllers

Example:

const controller = new AbortController();
const controllers = [];
raceAbort(controller, controllers); // Terminate previous requests and add current controller

createCache

Create cache instance. Provides request result caching function, supports expiration time.

Returns: Cache object containing get, set, remove methods

Example:

const cache = createCache();
cache.set("key", { data: "value" }, Date.now() + 60000); // Cache for 1 minute
const data = cache.get("key");
cache.remove("key");

deepSort

Deep sort object keys. Recursively sort the keys of an object to generate a stable object serialization result.

Parameters:

  • obj: Object to sort

Returns: Object with sorted keys

Example:

const obj = { b: 2, a: 1, c: { z: 3, y: 2 } };
const sorted = deepSort(obj);
// Returns: { a: 1, b: 2, c: { y: 2, z: 3 } }

createShare

Create request sharing instance. Used to share the same request to avoid duplicate requests.

Returns: Sharing object containing get and set methods

Example:

const share = createShare();
const promise = fetch("/api/data");
share.set("key", promise);
const sharedPromise = share.get("key"); // Get the same promise

createSilentRefresh

Create silent refresh instance. Used to handle silent refresh functionality when token expires.

Parameters:

  • refresh_token_fn: Function to refresh token

Returns: Function that accepts success and failure callbacks

Example:

const silentRefresh = createSilentRefresh(async () => {
  // Refresh token logic
  await refreshToken();
});

// Usage example
silentRefresh(
  () => console.log("Refresh successful"),
  () => console.log("Refresh failed")
);

parseWithBase

Parse base URL configuration. Process baseURL, headers, body and other configuration items to generate final request configuration.

Parameters:

  • urlOptions: Object containing url, options, baseURL and baseOptions

Returns: Processed url, options, is_body_json and abortController

Example:

const result = parseWithBase({
  url: "/api/users",
  options: { method: "GET" },
  baseURL: "https://api.example.com",
});

toFormData

Convert object to FormData. Used to convert plain objects to FormData format, supports files and regular values.

Parameters:

  • body: Object to convert

Returns: Converted FormData object

Example:

const formData = toFormData({
  name: "John",
  avatar: fileBlob,
  age: 30,
});

English | 中文 | Installation

soon-fetch

极轻量的请求库,不到 6K

  • 🌐 自动解析 rest Url 的参数
  • ⭐ 快捷定义请求 api
  • ⌛ 超时断开
  • 📦 请求复用
  • 🚀 请求竞态
  • 📝 响应缓存
  • 🔤 自动处理 JSON
  • 📏 不到 6K , zip 后会更小
  • 💡 用 typescript 有智能类型提醒

示例

github: soon-admin-vue3
github: soon-admin-react-nextjs

const soon = createSoon(
  (url, options) => {
    const isGet = !options?.method || options?.method.toLocaleLowerCase() === "get"
    return {
      baseURL: '/api',
      baseOptions: {
        timeout: 20 * 1000,
        headers: new Headers({
          Authorization: "Bearer " + localStorage.getItem("token"),
        }),
        share: isGet ? true : false,
        staleTime: isGet ? 2 * 1000 : 0,
      },
    }
  },
  ({ parsed }) => {
    return <T>() => {
      return fetch(parsed.url, parsed.options).then((res) =>
        res.json()
      ) as Promise<T>;
    };
  }
);

/** GET */
soon.get("/user?id=123");
soon.get("/user", { query: { id: 123 } });
soon.get("/user/:id", { params: { id: 123 } });

/** POST */
soon.post("/login", { body: { username: "admin", password: "123456" } });

/**定义 API */
export const login = soon
  .POST("/user/login")
  .Body<{ username: string; password: string }>()
  .Send<{ token: string }>();

//开发工具会有请求和响应的智能提醒
login({ username: "admin", password: "123" }).then((res) => {
  localStorage.setItem("token", res.token);
});

特别功能

快捷方法
soon.get(url, options);
soon.post(url, options);
soon.put(url, options);
soon.patch(url, options);
soon.delete(url, options);
soon.head(url, options);
soon.options(url, options);
Restful Url 参数自动处理

url 包含 /:key 会解析匹配 key

soon.get("/api/user/:id", { params: { id: 1 } });
// api/user/1
soon.get("/api/:job/:year", { params: { job: "engineer", year: 5 } });
//api/engineer/5
超时
//** 请求级超时, 会覆盖实例级超时  */
soon.get(url, { timeout: 1000 * 20 });
共享未完成的请求

如果在第一个请求完成之前再次发起相同的请求,则会复用第一个请求,而不是发起新的请求。

soon.get(url, { share: true });
响应缓存

如果在指定时间内再次发起相同的请求,则会返回缓存的响应。

soon.get(url, { staleTime: 1000 * 60 * 5 });
请求竞态

如果在第一个请求完成之前发起第二个请求,则会中止第一个请求,以避免因响应顺序错乱导致的问题。

import { useEffect, useRef, useState } from "react";

type User = { name: string; job: string };
const api = soon.GET("/api/users").Query<{ page: number }>().Send<User[]>();
export default function App() {
  const refAbort = useRef([]);
  const [list, setList] = useState<User[]>([]);
  const [page, setPage] = useState(1);
  useEffect(() => {
    api({ page }, { aborts: refAbort.current })
      .then(setList)
      .catch(console.log);
  }, [page]);
  return (
    <div>
      <button onClick={() => setPage((pre) => pre + 1)}>next</button>
      <div>
        {list.map((item) => (
          <div key={item.name}>{item.name}</div>
        ))}
      </div>
    </div>
  );
}
快速定义 API
  //可以是 GET POST PATCH PUT DELETE
  //GET 请求数据传递至query,其他方法请求数据传递至body
  soon.GET(url:string).Query<Query>().Send<Response>()
  soon.POST(url:string).Body<Body>().Send<Response>()

  //定义一个api
 export const getUserInfo=soon.GET('/user/:id').Send()
  //使用
  getUserInfo({id:2}).then(res=>console.log(res))

  //用typescript,
 export const login=soon
  .POST('/user/login')
  .Body<{username:string,password:string}>()
  .Send<{token:string}>()
 //开发工具会有请求和响应的智能提醒
  login({username:'admin',password:'123'}).then(res=>{
    localStorage.setItem('token', res.token);
  })

API

SoonOptions

// function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>
// RequestInit  为原生 fetch 的 init 选项
type SoonOptions = Omit<RequestInit, "body"> & {
  body?: RequestInit["body"] | object;
  query?:
    | Record<
        string,
        | string
        | number
        | boolean
        | null
        | undefined
        | (string | number | boolean | null | undefined)[]
      >
    | URLSearchParams;
  params?: Record<string, string | number>;
  timeout?: number;
  aborts?: AbortController[] | never[];
  share?: boolean;
  staleTime?: number;
};

createSoon

创建一个 soon 请求实例。

参数:

  • getConfig: 用于获取请求配置的函数,接收 url 和 options,返回包含 url、options、baseURL 和 baseOptions 的对象
  • wrapper: 包装器函数,用于处理请求逻辑

返回: 包含 request 方法和各种快捷方法的对象

示例:

const soon = createSoon(
  (url, options) => ({ url, options,baseURL:'/api', baseOptions:{timeout: 5000} }),
  ({ parsed }) =>
    async (url, options) => {
      const response = await fetch(parsed.url, parsed.options);
      return response.json();
    }
);
// 使用示例
const data = await soon.get("/api/users");

createShortApi

创建 API 快捷方法的工厂函数。 用于生成类型安全的 API 调用方法,支持路径参数、查询参数和请求体。

参数:

  • wrapper: 包装函数,用于处理实际的请求逻辑

返回: 包含 GET、POST、PUT、DELETE、PATCH 等方法的对象,每个方法都支持链式调用

示例:

const API = createShortApi(
  async (url, method, params, query, body, options) => {
    // 处理请求逻辑
    const _url = mergeUrl(url, { params, query });
    const response = await fetch(_url, { ...options, method, body });
    return response.json();
  }
);

// 使用示例
const getUser = API.GET("/api/users/:id").Send();
const userData = await getUser({ id: 1 });

createShortMethods

创建快捷方法的工厂函数。

参数:

  • methods: HTTP 方法数组
  • wrapper: 包装函数,接收方法名,返回处理请求的函数

返回: 包含指定方法的快捷调用对象

示例:

const methods = createShortMethods(["get", "post"], (method) => {
  return (url, options) => fetch(url, { ...options, method });
});
// 使用: methods.get('/api/users')

parseUrlOptions

解析 URL 选项。

参数:

  • urlOptions: 包含 url、options、baseURL 和 baseOptions 的对象

返回: 处理后的 url 和 options 元组

示例:

const [url, options] = parseUrlOptions({
  url: "/api/users/:id",
  options: { params: { id: "123" } },
  baseURL: "https://api.example.com",
});
// 返回: ['https://api.example.com/api/users/123', options]

mergeHeaders

合并多个 Headers 对象。

参数:

  • headersList: 要合并的 Headers 对象列表

返回: 合并后的 Headers 对象,后面的会覆盖前面的同名 header

示例:

const headers1 = { "Content-Type": "application/json" };
const headers2 = { Authorization: "Bearer token" };
const mergedHeaders = mergeHeaders(headers1, headers2);

mergeSignals

合并多个 AbortSignal 信号。

参数:

  • signals: 要合并的 AbortSignal 数组
  • timeout: 可选的超时时间(毫秒)

返回: 合并后的 AbortSignal,任意一个信号终止都会触发终止

示例:

const controller1 = new AbortController();
const controller2 = new AbortController();
const mergedSignal = mergeSignals(
  [controller1.signal, controller2.signal],
  5000
);

mergeUrl

合并 URL 及其相关参数。 处理 baseURL、路径参数和查询参数,生成完整 URL。

参数:

  • url: 原始 URL
  • config: 配置对象,包含查询参数、路径参数和基础 URL

返回: 处理后的完整 URL

示例:

const url = mergeUrl("/api/users/:id", {
  params: { id: "123" },
  query: { filter: "active" },
  baseURL: "https://api.example.com",
});
// 返回: 'https://api.example.com/api/users/123?filter=active'

mergeOptions

合并多个选项对象。 合并请求选项,包括 headers 和 signal 等特殊处理。

参数:

  • optionsList: 要合并的选项对象列表

返回: 合并后的选项对象

示例:

const defaultOptions = {
  timeout: 5000,
  headers: { "Content-Type": "application/json" },
};
const requestOptions = {
  method: "POST",
  body: JSON.stringify({ name: "John" }),
};
const mergedOptions = mergeOptions(defaultOptions, requestOptions);

isBodyJson

判断请求体是否为 JSON 对象。 检查 body 是否为普通对象,而不是 FormData、Blob 等特殊类型。

参数:

  • body: 请求体

返回: 如果是 JSON 对象返回 true,否则返回 false

示例:

isBodyJson({ name: "John" }); // true
isBodyJson(new FormData()); // false
isBodyJson("string"); // false

genRequestKey

生成请求的唯一标识键。 根据请求的 URL、方法、headers、body、查询参数等生成唯一键值,用于缓存和请求共享。

参数:

  • req: 包含 url 和 options 的请求对象

返回: 请求的唯一标识字符串

示例:

const key = genRequestKey({
  url: "/api/users",
  options: { method: "GET", params: { id: 1 } },
});

raceAbort

竞态处理函数。 用于处理请求竞态,终止之前的请求。

参数:

  • abortController: 当前请求的控制器
  • controllers: 已存在的控制器数组

示例:

const controller = new AbortController();
const controllers = [];
raceAbort(controller, controllers); // 终止之前的请求并添加当前控制器

createCache

创建缓存实例。 提供请求结果缓存功能,支持过期时间。

返回: 包含 get、set、remove 方法的缓存对象

示例:

const cache = createCache();
cache.set("key", { data: "value" }, Date.now() + 60000); // 缓存1分钟
const data = cache.get("key");
cache.remove("key");

deepSort

深度排序对象键。 递归地对对象的键进行排序,用于生成稳定的对象序列化结果。

参数:

  • obj: 要排序的对象

返回: 键排序后的对象

示例:

const obj = { b: 2, a: 1, c: { z: 3, y: 2 } };
const sorted = deepSort(obj);
// 返回: { a: 1, b: 2, c: { y: 2, z: 3 } }

createShare

创建请求共享实例。 用于共享相同请求,避免重复请求。

返回: 包含 get 和 set 方法的共享对象

示例:

const share = createShare();
const promise = fetch("/api/data");
share.set("key", promise);
const sharedPromise = share.get("key"); // 获取相同 promise

createSilentRefresh

创建静默刷新实例。 用于处理 token 过期时的静默刷新功能。

参数:

  • refresh_token_fn: 刷新 token 的函数

返回: 接收成功和失败回调的函数

示例:

const silentRefresh = createSilentRefresh(async () => {
  // 刷新token逻辑
  await refreshToken();
});

// 使用示例
silentRefresh(
  () => console.log("刷新成功"),
  () => console.log("刷新失败")
);

parseWithBase

解析基础 URL 配置。 处理 baseURL、headers、body 等配置项,生成最终的请求配置。

参数:

  • urlOptions: 包含 url、options、baseURL 和 baseOptions 的对象

返回: 处理后的 url、options、is_body_json 和 abortController

示例:

const result = parseWithBase({
  url: "/api/users",
  options: { method: "GET" },
  baseURL: "https://api.example.com",
});

toFormData

将对象转换为 FormData。 用于将普通对象转换为 FormData 格式,支持文件和普通值。

参数:

  • body: 要转换的对象

返回: 转换后的 FormData 对象

示例:

const formData = toFormData({
  name: "John",
  avatar: fileBlob,
  age: 30,
});

English | 中文 | Installation

安装 Installation
    npm install soon-fetch