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

tools_dj

v1.0.88

Published

dj tools 工具库

Readme

DJ 工具库

一个全面的 JavaScript/TypeScript 工具函数集合,包含数据处理、时间格式化、树结构操作、DOM 操作等常用功能。

安装

npm install tools_dj

使用

基础使用

import { formatDate, is_empty, formatSize } from "tools_dj";

// 格式化日期
const date = formatDate(new Date(), 'day', '-'); // "2024-03-24"

// 检查空值
const isEmpty = is_empty(""); // true

// 格式化文件大小
const size = formatSize(1024); // "1 KB"

使用类模块

// 权限管理
import { auth } from "tools_dj";
const authManager = new auth(['read', 'write', 'delete']);

// 时间比较
import { carbon } from "tools_dj";
const timeCheck = carbon(new Date());

// HTTP请求
import Request from "tools_dj/request";
const http = new Request({
  headers: { 'Content-Type': 'application/json' }
}, { baseUrl: 'https://api.example.com' });

API 文档

数据类型判断

is(obj: any): string

判断数据类型,返回具体类型名称

is([1, 2, 3]); // "Array"
is({}); // "Object"
is("hello"); // "String"

is_empty(obj: any): boolean

判断值是否为空,支持所有数据类型

is_empty(null); // true
is_empty(""); // true
is_empty([]); // true
is_empty({}); // true

isNum(data: any): boolean

判断是否是数字(包括字符型数字)

isNum("123"); // true
isNum(456); // true
isNum("abc"); // false

数组操作

del_repeat(obj: any[]): any[]

删除数组重复元素

del_repeat([1, 2, 2, 3]); // [1, 2, 3]

unique(obj: any[]): any[] | false

去除数组重复元素(带空值检查)

unique([1, 2, 2, 3]); // [1, 2, 3]

first(obj: any): any

获取数组或对象的第一个元素

first([1, 2, 3]); // 1

last(obj: any): any

获取数组或对象的最后一个元素

last([1, 2, 3]); // 3

arrayGroup(arr: any[], groupKey: string): object

数组分组

arrayGroup([{type: 'A', value: 1}, {type: 'B', value: 2}], 'type');
// { A: [{type: 'A', value: 1}], B: [{type: 'B', value: 2}] }

时间处理

formatDate(time: Date, format: string, type: string): string

格式化时间

formatDate(new Date(), 'day', '-'); // "2024-03-24"
formatDate(new Date(), 'minute', '/'); // "2024/03/24/14/30"

formatTime(time: any, format: string, option?: object): string

高级时间格式化

formatTime('2024-03-24', 'YYYY年MM月DD日'); // "2024年03月24日"
formatTime(new Date(), 'YYYY-MM-DD week'); // "2024-03-24 周日"

getDaysBetween(date1: string, date2: string, negative?: boolean): number

计算两个日期之间的天数

getDaysBetween('2024-01-01', '2024-01-05'); // 4

isDateInRange(date: string, startDate: string, endDate: string): boolean

判断日期是否在指定范围内

isDateInRange('2024-02-15', '2024-01-01', '2024-12-31'); // true

对象操作

merge(obj1: any, obj2: any): any

合并数组或对象

merge([1, 2], [3, 4]); // [1, 2, 3, 4] (去重后)
merge({a: 1}, {b: 2}); // {a: 1, b: 2}

delObj(obj: object, keys?: string | string[]): void

删除对象属性

const obj = {a: 1, b: 2, c: 3};
delObj(obj, 'a'); // {b: 2, c: 3}
delObj(obj, ['b', 'c']); // {}

delObjEmptyKey(obj: object): void

删除对象中的空属性

const obj = {a: 1, b: '', c: null, d: 2};
delObjEmptyKey(obj); // {a: 1, d: 2}

树结构操作

arrToTree(data: any[], option?: object): any[]

平级数组转树形结构

const data = [
  {id: 1, parentId: 0, name: 'root'},
  {id: 2, parentId: 1, name: 'child1'}
];
arrToTree(data); // 树形结构

treeToArr(data: any[], option?: object): any[]

树形结构转平级数组

treeToArr(treeData); // 扁平化数组

handleTree(data: any[], id: string, parentId: string, children: string): any[]

构造树形结构数据

handleTree(data, 'id', 'parentId', 'children');

字符串处理

toGetQuery(data: object, option?: object): string

对象转URL查询参数

toGetQuery({name: 'test', age: 20}); // "?name=test&age=20"

isLink(str: string): boolean

判断字符串是否为有效链接

isLink('https://example.com'); // true
isLink('not-a-link'); // false

repalce(str: string, index: number, char: string): string

字符串指定位置替换

repalce('hello', 1, 'a'); // "hallo"

数字处理

formatSize(num: number, option?: object): string

转换大小默认是文件可以是别的

formatSize(1024); // "1 KB"
formatSize(1048576, {decimals: 1}); // "1.0 MB"

numberFixed(number: number, decimalPlaces?: number): number

数字保留小数位(截取不四舍五入)

numberFixed(3.14159, 2); // 3.14

numberRepair(str: string, n: number, k: string, d: boolean): string

数字前置补位

numberRepair('5', 3, '0'); // "005"

randomNumber(min: number, max: number): number

生成随机数

randomNumber(1, 100); // 1-100之间的随机数

工具函数

throttle(fn: Function, delay?: number, immediate?: boolean): Function

节流函数

const throttled = throttle(() => console.log('throttled'), 1000);

debounce(fn: Function, delay: number): Function

防抖函数

const debounced = debounce(() => console.log('debounced'), 300);

memoize(func: Function, options?: object): Function

函数缓存

const cachedFn = memoize(expensiveFunction, {ttl: 5000});

DOM 相关

isMobile(): boolean

检测是否为移动设备

isMobile(); // true/false

setMeta(meta: object): void

设置页面meta信息

setMeta({title: "页面标题", cZoom: {mobile: 0.8}});

转换工具

pxToRem(pxValue: string | number, baseRem?: number): string

px转rem

pxToRem('16px'); // "0.43rem"
pxToRem(32, 16); // "2.00rem"

base64Img(base64: string, imgName: string): File

base64转文件对象

const file = base64Img(base64String, 'image.png');

objToFormData(obj: object, simplify?: boolean): FormData

对象转FormData

  • obj - 要转换的对象
  • simplify - 是否简化(简化后第一层数组将省略索引),默认true
const formData = objToFormData({name: 'test', files: [file1, file2]});

数组高级操作

findByIndex(array: any[], key: string, data: any): number

二维数组查找返回下标

const users = [{id: 1, name: 'Tom'}, {id: 2, name: 'Jerry'}];
findByIndex(users, 'id', 2); // 1

setObjData(source: any[], sourceKey: string, sourceData: any, nowKey: string, nowData: any): boolean

设置二维数组的值

const data = [{id: 1, name: 'old'}];
setObjData(data, 'id', 1, 'name', 'new'); // true
// data: [{id: 1, name: 'new'}]

selectObjData(source: any[], sourceKey: string, sourceData: any): any

查找二维数组数据

const users = [{id: 1, name: 'Tom'}, {id: 2, name: 'Jerry'}];
selectObjData(users, 'id', 2); // {id: 2, name: 'Jerry'}

arrSet(arr: any[], index: number, data: any): void

在数组任意位置插入数据

const arr = [1, 2, 4];
arrSet(arr, 2, 3); // [1, 2, 3, 4]

sArrMove(arr: any[], startIndex: number, endIndex: number): void

源数组移动元素(直接修改原数组)

const arr = [1, 2, 3, 4];
sArrMove(arr, 0, 2); // arr变为 [2, 3, 1, 4]

rArrMove(arr: any[], startIndex: number, endIndex: number): any[]

数组元素位置移动返回新数组(不修改原数组)

const arr = [1, 2, 3, 4];
const newArr = rArrMove(arr, 0, 2); // [2, 3, 1, 4]
// arr仍为 [1, 2, 3, 4]

inArr(arr: any[], str: any, force?: boolean): number

判断字符是否在数组中,返回索引

  • force - 是否强制类型检查,默认false(使用==比较)
inArr([1, 2, 3], '2'); // 1 (非强制模式)
inArr([1, 2, 3], '2', true); // -1 (强制模式)

树结构高级操作

treeFor(data: any[], callBack: Function, option?: object): void

树循环返回子项(叶子节点)

  • option.cKey - 子节点字段名,默认'children'
treeFor(treeData, (node) => {
  console.log('叶子节点:', node);
});

treeStack(data: any[], callBack: Function, option?: object): void

树栈循环返回子项

treeStack(treeData, (node) => {
  console.log('节点:', node);
});

treeRecursion(data: any[], callBack: Function, option?: object): void

树递归循环返回子项

treeRecursion(treeData, (node) => {
  console.log('节点:', node);
});

treeFind(data: any[], option?: object): any[]

树中查找节点

  • option.cKey - 子节点字段名,默认'children'
  • option.key - 查找的字段名,默认'id'
  • option.value - 查找的值
  • option.copy - 是否复制(去除children),默认true
treeFind(treeData, {key: 'id', value: 5});

arrToAryTree(items: any[], option?: object): any[]

层级树转换成多叉树(带左右值的嵌套集合模型)

  • option.idKey - ID字段,默认'id'
  • option.pidKey - 父ID字段,默认'pid'
  • option.rKey - 右值字段,默认'rgt'
  • option.lKey - 左值字段,默认'lft'
  • option.levelKey - 层级字段,默认'level'
const tree = arrToAryTree(flatData);
// 返回带有lft、rgt、level字段的数组

颜色处理

colorMix(color1: string, color2: string, weight: number): string

色阶取值(颜色混合)

  • weight - 权重0-1,越接近1越接近color2
colorMix('#ff0000', '#0000ff', 0.5); // "#7f007f" (混合紫色)

randomColor(): string

生成随机颜色(rgba格式)

randomColor(); // "rgba(150,200,180,1)"

排序

compare(prop: string, type?: string): Function

数字排序比较函数

  • type - 'up'升序(默认)或'down'降序
const users = [{age: 25}, {age: 18}, {age: 30}];
users.sort(compare('age', 'up')); // 按age升序

compareDate(prop: string, type?: string): Function

时间排序比较函数

const events = [
  {date: '2024-03-20'},
  {date: '2024-01-15'}
];
events.sort(compareDate('date', 'up')); // 按日期升序

函数工具

throttle1(func: Function, delay: number): Function

节流函数(备选实现)

const throttled = throttle1(() => {
  console.log('执行');
}, 1000);

fnRuntime(fn: Function, iterations?: number): void

测量函数执行时间

  • iterations - 迭代次数,默认1
fnRuntime(() => {
  // 需要测试的代码
}, 100);
// 控制台输出: "平均执行时间 100 次数: 0.123456 ms"

mergeObj(obj: object[], callbackCon?: object): object

深层次对象合并

  • callbackCon.callback - 回调函数
  • callbackCon.callType - 回调类型
  • callbackCon.afterBack - 后置回调
const merged = mergeObj([
  {a: {b: 1}},
  {a: {c: 2}}
]);
// {a: {b: 1, c: 2}}

其他工具

time_change(data: string): number

时间格式转时间戳

time_change('2024-03-24 10:30'); // 1711252200000

类模块

权限管理 (auth)

基于位运算的高性能权限管理系统

import { auth } from "tools_dj";

// 创建权限管理实例
const authManager = new auth(['read', 'write', 'delete', 'update']);

// 初始权限为0
let userAuth = 0;

// 添加权限
userAuth = authManager.add(userAuth, ['read', 'write']);

// 删除权限
userAuth = authManager.del(userAuth, ['write']);

// 判断权限(必须全部存在)
authManager.andHave(userAuth, ['read', 'write']); // false

// 判断权限(只要有一个存在)
authManager.orHave(userAuth, ['read', 'write']); // true

// 获取权限列表
authManager.getTxt(userAuth); // ['read']

API说明:

  • constructor(authList: string[]) - 创建权限管理实例
  • add(base: number, arr: string[]): number - 添加权限
  • del(base: number, arr: string[]): number - 删除权限
  • andHave(base: number, arr: string[]): boolean - AND判断(全部存在)
  • orHave(base: number, arr: string[]): boolean - OR判断(至少一个存在)
  • getTxt(number: number): string[] - 获取权限名称列表

时间比较 (date)

提供链式时间比较操作

import { carbon, contrast } from "tools_dj";

// 方式1: 使用carbon函数
const timeCheck = carbon(new Date('2024-03-24'));

// 方式2: 使用contrast类
const timeCheck2 = new contrast(new Date('2024-03-24'));

// 大于
timeCheck.Gt(new Date('2024-03-20')); // true

// 小于
timeCheck.Lt(new Date('2024-03-30')); // true

// 等于
timeCheck.Eq(new Date('2024-03-24')); // true

// 不等于
timeCheck.Ne(new Date('2024-03-25')); // true

// 大于等于
timeCheck.Gte(new Date('2024-03-24')); // true

// 小于等于
timeCheck.Lte(new Date('2024-03-24')); // true

// 判断是否在时间段内
timeCheck.Between(
  new Date('2024-03-20'),
  new Date('2024-03-30')
); // true

API说明:

  • Gt(date: Date): boolean - 大于
  • Lt(date: Date): boolean - 小于
  • Eq(date: Date): boolean - 等于
  • Ne(date: Date): boolean - 不等于
  • Gte(date: Date): boolean - 大于等于
  • Lte(date: Date): boolean - 小于等于
  • Between(date1: Date, date2: Date): boolean - 是否在时间段内

消息通信 (msg)

提供跨页面和页面内的消息通信

import msg from "tools_dj/msg";

// 跨页面消息发送(使用BroadcastChannel)
msg.pageSend('userUpdate', {id: 1, name: 'Tom'});

// 跨页面消息接收
msg.pageRead('userUpdate', (data) => {
  console.log('收到消息:', data);
});

// 页面内消息发送(使用mitt)
msg.busSend('event1', {data: 'test'});

// 页面内消息接收
msg.busRead('event1', (data) => {
  console.log('收到事件:', data);
});

// 取消特定监听器
const handler = (data) => console.log(data);
msg.busRead('event1', handler);
msg.busOff('event1', handler);

// 取消所有同名监听
msg.busDown('event1');

// store消息监听(适用于Vue的Pinia store)
msg.storeRead(store, (state) => {
  console.log('store变化:', state);
});

API说明:

  • pageSend(type: string, data: any): void - 跨页面消息发送
  • pageRead(type: string, callback: Function): void - 跨页面消息接收
  • busSend(type: string, data: any): void - 页面内消息发送
  • busRead(type: string, callback: Function): void - 页面内消息接收
  • busOff(type: string, callback: Function): void - 取消特定监听
  • busDown(type: string): void - 取消所有同名监听
  • storeRead(store: any, callback: Function): void - store变化监听

HTTP请求 (request)

基于Fetch API的HTTP请求封装

import Request from "tools_dj/request";

// 创建请求实例
const http = new Request(
  // 默认请求配置
  {
    headers: {
      'Content-Type': 'application/json'
    },
    mode: 'cors',
    credentials: 'include'
  },
  // 全局配置
  {
    baseUrl: 'https://api.example.com',
    timeout: 10000,
    // 成功回调
    callback: async (response) => {
      return await response.json();
    },
    // 失败回调
    errBack: (error) => {
      console.error('请求失败:', error);
    },
    // 请求前回调
    beforeBack: (options) => {
      console.log('发送请求:', options);
    },
    // 获取中断控制器
    abController: (controller) => {
      // 可以手动中断请求
      // controller.abort();
    }
  }
);

// 发送GET请求
http.serve('/users', {
  method: 'GET'
}).then(data => {
  console.log(data);
});

// 发送POST请求
http.serve('/users', {
  method: 'POST',
  body: JSON.stringify({name: 'Tom', age: 20})
}, {
  // 单次请求配置
  timeout: 5000,
  callback: async (res) => await res.json()
}).then(data => {
  console.log(data);
});

// 请求完整URL(会自动检测,不添加baseUrl)
http.serve('https://other-api.com/data');

配置参数说明:

构造函数参数:

  • option - Fetch请求配置对象

    • method - 请求方法 (GET, POST, PUT, DELETE等)
    • mode - 跨域策略 ("cors", "same-origin", "no-cors")
    • cache - 缓存策略 ("no-cache", "default", "reload", "force-cache")
    • credentials - 凭证策略 ("same-origin", "include", "omit")
    • headers - 请求头对象
    • redirect - 重定向处理 ("follow", "manual", "error")
    • referrerPolicy - 引用策略
    • body - 请求体
  • conf - 全局配置对象

    • baseUrl - 基础URL前缀
    • timeout - 超时时间(毫秒),默认6000
    • callback(response) - 成功回调,处理响应
    • errBack(error) - 失败回调
    • abController(controller) - 获取中断控制器
    • beforeBack(options) - 请求前回调

serve方法参数:

  • url - 请求地址(相对路径或完整URL)
  • options - 本次请求的fetch配置(会与构造函数的option合并)
  • conf - 本次请求的配置(会与构造函数的conf合并)

特性

  • 🚀 轻量高效 - 优化的算法实现
  • 📦 TypeScript 支持 - 完整的类型定义
  • 🔧 模块化设计 - 按需引入,减少包体积
  • 🌍 跨平台兼容 - 支持浏览器和 Node.js 环境
  • 📚 完整文档 - 详细的使用示例和API说明

许可证

MIT License