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

tool-utils-kit

v1.0.5

Published

TypeScript 工具函数库,统一通过 ToolUtils 命名空间访问

Readme

tool-utils-kit

TypeScript 工具函数库,统一通过 ToolUtils 命名空间访问,支持 ESM、类型提示与 Vite 自动导入。

安装

npm install tool-utils-kit

快速开始

import ToolUtils, { LOG_LEVEL, WS_STATUS } from 'tool-utils-kit'

// 字符串 / 时间 / 对象
ToolUtils.String._getUrlParam('https://example.com?id=1', 'id')
ToolUtils.String._camelToSnake('userName') // 'user_name'
ToolUtils.Time._dateToStr(new Date(), 'YYYY-MM-DD')
ToolUtils.Object._deepClone({ a: { b: 1 } })

// 事件总线 / 定时队列(全局单例,模块加载即就绪)
ToolUtils.Bus._on('user:login', (name) => console.log(name))
ToolUtils.Bus._emit('user:login', 'Tom')
ToolUtils.Queue._enqueue({ id: 1 })

// 日志(全局单例,入口可 _init 替换配置)
ToolUtils.Log._info('[App]', 'started')

// 存储 / WebSocket(须先 _init)
ToolUtils.Storage._init({
  appKey: 'app',
  localDefaults: {},
  sessionDefaults: {}
})
ToolUtils.Socket._init({
  Url: 'wss://example.com/ws',
  Interceptors: {
    onOpenRes: () => {},
    onMessageRes: ({ Data }) => console.log(Data),
    onCloseRes: () => {},
    onErrorRes: () => {}
  }
})
ToolUtils.Storage._setLocal('pubKey', 'abc')
ToolUtils.Socket._sendCmd({ Cmd: 1, Key: 'ping' })

// HTTP 网络(须先 _init)
ToolUtils.Network._init({
  baseURL: 'https://api.example.com',
  timeout: 10000,
  interceptors: {
    requestInterceptors: (config) => config,
    responseInterceptors: (res) => res
  }
})
ToolUtils.Network._request({ url: '/user', method: 'GET' })

API 结构

ToolUtils
├── String          … 函数集合(_ 前缀)
├── Time            … 函数集合(_ 前缀,基于 moment)
├── Object          … 函数集合(_ 前缀)
├── Bus             … 事件总线单例(_ 前缀方法)
├── Queue           … 定时队列单例(_ 前缀方法)
├── Storage         … 存储单例(_init 初始化)
├── Log             … 日志单例(_ 前缀方法)
├── Socket          … WebSocket 单例(_init 初始化)
└── Network         … HTTP 单例(_init 初始化,axios 二次封装)

| 命名空间 | 类型 | 说明 | |---------|------|------| | String | 函数集合 | URL、格式化、校验等 | | Time | 函数集合 | 日期解析、格式化、差值计算 | | Object | 函数集合 | 深拷贝、合并、取值,含原型污染防护 | | Bus | 全局单例 | 发布/订阅,跨组件通信 | | Queue | 全局单例 | 闲置超时自动清空的队列(默认 60 秒) | | Storage | 全局单例 | 类型安全的 localStorage / sessionStorage | | Log | 全局单例 | 控制台日志,支持级别、颜色、分组、过滤 | | Socket | 全局单例 | WebSocket 客户端,支持断线队列与重连 | | Network | 全局单例 | axios 二次封装,支持并发队列、拦截器与按 URL 取消请求 |

所有对外方法均以 _ 开头;初始化统一使用 _init(无返回值,仅替换/创建实例)。

单例 vs 独立实例

| | 全局单例 | 初始化 | 独立实例 | |---|---------|--------|---------| | Bus | ToolUtils.Bus | 模块加载即就绪 | ToolUtils.Bus._init() | | Queue | ToolUtils.Queue | 模块加载即就绪 | ToolUtils.Queue._init(seconds) | | Log | ToolUtils.Log | ToolUtils.Log._init(level, filters) | — | | Storage | ToolUtils.Storage | ToolUtils.Storage._init(options) | — | | Socket | ToolUtils.Socket | ToolUtils.Socket._init(config) | — | | Network | ToolUtils.Network | ToolUtils.Network._init(options) | — |

Storage / Socket / Network_init 就调用方法时,会通过 ToolUtils.Log._error 记录并抛出异常。

// 独立 Bus / Queue 实例(与全局单例互不影响)
const localBus = ToolUtils.Bus._init()
const fastQueue = ToolUtils.Queue._init(10)

// 配置全局 log / storage
ToolUtils.Log._init(LOG_LEVEL.WARN, ['Socket'])
ToolUtils.Storage._init({ appKey: 'app', localDefaults: {}, sessionDefaults: {} })

Storage 用法

interface ILocalCache {
  pubKey: string
  playerSearch: string[]
}

interface ISessionCache {
  appRoot: string
}

ToolUtils.Storage._init<ILocalCache, ISessionCache>({
  appKey: import.meta.env.VITE_APP_KEY ?? 'app',
  localDefaults: { pubKey: '', playerSearch: [] },
  sessionDefaults: { appRoot: '' }
})

ToolUtils.Storage._setLocal('pubKey', 'abc')
ToolUtils.Storage._getLocal('pubKey') // 'abc'
ToolUtils.Storage._setSession('appRoot', '/home')
ToolUtils.Storage._removeLocal('pubKey')
ToolUtils.Storage._clearCache()

Log 用法

ToolUtils.Log._debug('debug message')
ToolUtils.Log._info('[App]', 'info message')
ToolUtils.Log._warn('warn message')
ToolUtils.Log._error('[App]', 'error message')
ToolUtils.Log._network('GET /api/user')
ToolUtils.Log._socket('socket connected')
ToolUtils.Log._stack('call stack')
ToolUtils.Log._trace()
ToolUtils.Log._groupStart('[Group]', 'start')
ToolUtils.Log._groupEnd()

// 入口替换全局 log 配置
ToolUtils.Log._init(LOG_LEVEL.DEBUG, ['Socket'])
ToolUtils.Log._info('[App]', 'visible')

Socket 用法

import ToolUtils, { LOG_LEVEL, WS_STATUS, type ICmd } from 'tool-utils-kit'

ToolUtils.Socket._init({
  Url: import.meta.env.VITE_WS_URL,
  ReconnectIntervalMs: 3000,
  Interceptors: {
    onOpenRes: () => console.log('connected'),
    onMessageRes: ({ Data }) => console.log('message', Data),
    onCloseRes: ({ Status }) => {
      if (Status === WS_STATUS.CLOSED) {
        console.log('disconnected, auto reconnecting...')
      }
    },
    onErrorRes: () => console.error('socket error')
  }
})

const cmd: ICmd = { Cmd: 1001, Key: 'login', Data: '{}' }
ToolUtils.Socket._sendCmd(cmd)

断线或出错时会按 ReconnectIntervalMs(默认 3000ms)定时重连;Url 为空时回调 onErrorRes({ Status: WS_STATUS.INVALID })

Network 用法

import ToolUtils, { type INetworkRequestConfig } from 'tool-utils-kit'

ToolUtils.Network._init({
  baseURL: import.meta.env.VITE_API_BASE,
  timeout: 15000,
  maxConcurrency: 10,
  interceptors: {
    requestInterceptors: (config) => {
      config.headers.set('Authorization', 'Bearer token')
      return config
    },
    responseInterceptors: (res) => res,
    responseInterceptorsCatch: (error) => Promise.reject(error)
  }
})

// 便捷方法
await ToolUtils.Network._get('/user/info', { params: { id: 1 } })
await ToolUtils.Network._post('/order/list', { page: 1 })
await ToolUtils.Network._put('/user/profile', { name: 'Tom' })
await ToolUtils.Network._patch('/user/profile', { name: 'Tom' })
await ToolUtils.Network._delete('/order/1')

// 通用 _request(支持单请求级拦截器)
const config: INetworkRequestConfig = {
  url: '/order/list',
  method: 'POST',
  data: { page: 1 },
  interceptors: {
    responseInterceptors: (res) => res
  }
}
await ToolUtils.Network._request(config)

// 按 URL 取消 / 取消全部
ToolUtils.Network._cancelRequest('/order/list')
ToolUtils.Network._cancelAllRequest()

Network 为纯 axios 封装,内置并发队列(默认最多 10 个并行请求,可通过 maxConcurrency 配置),提供 _get / _post / _put / _patch / _delete 等便捷方法,不含业务 API 或 Store 逻辑。

注意事项 · 内部日志

以下模块内部使用全局 ToolUtils.Log 输出日志:

| 模块 | 方法 | 场景 | |------|------|------| | Bus | _error | 事件回调执行异常 | | Queue | _error | 清空回调执行异常 | | Storage | _error | localStorage / sessionStorage 读写失败 | | Socket | _socket | 连接、重连、发送等业务日志 | | Network | _network | 取消请求等业务日志 |

若需控制内部日志级别或过滤,须在 _init Storage / Socket / Network 之前调用:

ToolUtils.Log._init(LOG_LEVEL.WARN, ['Socket'])
ToolUtils.Socket._init({ Url: 'wss://...', Interceptors: { ... } })

类型与枚举

API 走 ToolUtils;枚举与类型从主入口按需导入:

import ToolUtils, {
  LOG_LEVEL,
  LOG_TAG,
  WS_STATUS,
  type IToolUtils,
  type ILogUtils,
  type ISocketUtils,
  type INetworkUtils,
  type INetworkRequestConfig,
  type ICreateNetworkOptions,
  type IWSConfig,
  type ICmd,
  type ICreateStorageUtilOptions
} from 'tool-utils-kit'

ToolUtils.Log._init(LOG_LEVEL.WARN, ['Socket'])
// LOG_LEVEL.WARN、WS_STATUS.CLOSED 等可直接使用

包入口

| 入口 | 说明 | |------|------| | tool-utils-kit | 默认导出 ToolUtils | | tool-utils-kit/vite | Vite unplugin-auto-import 预设 | | tool-utils-kit/auto-imports | 全局类型:ToolUtils |

Time 模块基于 moment,安装本包时会自动安装 moment 依赖。
Network 模块基于 axios,安装本包时会自动安装 axios 依赖。
Storage 基于原生 localStorage / sessionStorage无 Vue 依赖
Socket 基于浏览器原生 WebSocket,适用于前端项目。

Vite 自动导入

1. 安装插件

npm install -D unplugin-auto-import

2. 配置 vite.config.ts

import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import { ToolUtilsAutoImport } from 'tool-utils-kit/vite'

export default defineConfig({
  plugins: [
    AutoImport({
      imports: [ToolUtilsAutoImport],
      dts: 'src/auto-imports.d.ts'
    })
  ]
})

配置后可直接使用:

ToolUtils.String._camelToSnake('userName')
ToolUtils.Bus._emit('app:ready')
ToolUtils.Log._info('[App]', 'ready')

3. 类型声明

env.d.tstsconfig 中引用:

/// <reference types="tool-utils-kit/auto-imports" />

开发与发布

# 类型检查
npm run typecheck

# 构建 pack 产物
npm run build

# 发布到 npm
npm run release

License

ISC