utils-ok
v2.0.0
Published
useful utils
Readme
utils-ok
一站式 Node.js 工具库 —— 字符串处理、文件操作、异步工具、云存储、数据库、AI 对话、自动化测试,开箱即用。
特性
- 跨平台 —— macOS / Windows / Linux 全兼容
- 按需引用 —— 每个模块独立导出,tree-shaking 友好
- 内置日志 —— 自带
wLogger,零配置即可输出结构化日志 - 云原生 —— 集成阿里云 OSS / MinIO / MySQL / OpenAI / 钉钉机器人
- 工程化 —— 内置 ESLint / blacklint 检查、Git 工具、Hosts 管理等 CLI 辅助
安装
pnpm add utils-ok
# 或
npm install utils-ok
# 或
yarn add utils-ok快速开始
import { strUtil, fileUtil, asyncUtil, baseUtil } from 'utils-ok';
// 字符串处理
strUtil.md5('hello'); // MD5 哈希
strUtil.random(16); // 随机字符串
strUtil.md2html('# 标题'); // Markdown → HTML
// 文件操作
fileUtil.delete('/tmp/a.txt'); // 删除文件
fileUtil.tmpFile('.json'); // 获取临时文件路径
fileUtil.getJSON('/path/to/config.json');
// 异步工具
await asyncUtil.sleep(1000); // 延时 1 秒
// 加密 & 工具
baseUtil.encrypt('data', 'key'); // DES 加密
baseUtil.uuid(); // UUID v7
baseUtil.retry(fn, 3, 1000); // 重试 3 次,间隔 1 秒API 参考
📦 数据处理
strUtil — 字符串工具
| 方法 | 说明 |
|------|------|
| parseDBUri(uri) | 解析数据库 URI,提取 host/port/user/pass/db |
| isJsonStr(str) | 判断是否为合法 JSON 字符串 |
| safeIntNumber(val) | 安全转整数 |
| safeBoolean(val) | 安全转布尔值 |
| md5(str) | MD5 哈希 |
| hasUnicode(str) | 检测是否含 Unicode 字符 |
| isSimilar(str1, str2, opts) | 字符串相似度比较 |
| isSimilarCn(str1, str2) | 中文相似度比较 |
| md2html(markdown) | Markdown 转 HTML(带样式) |
| sqlStr(str) | 转义 SQL 字符串中的单引号 |
| regExp(str) | 字符串 → RegExp 对象 |
| random(len, prefix) | 生成随机字母数字字符串 |
| randomCn(len) | 生成中文数字字符串 |
| uid(n) | 生成唯一 ID |
| cutStrByLength(str, len) | 按长度切割字符串 |
| cutStrTail(length, str) | 截断尾部字符串 |
| cleanColor(str) | 清除 ANSI 颜色码 |
arrUtil — 数组工具
| 方法 | 说明 |
|------|------|
| sum(arr) | 数字数组求和 |
| getMostSimilar(target, list) | 从列表中找最相似项 |
| getUniq(list) | 字符串数组去重 |
| getUniqByKey(list, key) | 对象数组按 key 去重 |
| getUniqBySimilar(list, rate) | 按相似度去重 |
objUtil — 对象工具
| 方法 | 说明 |
|------|------|
| search(obj, key) | 递归搜索对象中的匹配项 |
| isRegExp(str) | 判断是否为合法正则 |
| clean(obj, keepEmptyStr) | 清除 null/undefined 键 |
| cleanKey(obj, key) | 递归删除指定键 |
| isObj(val) | 判断是否为普通对象 |
| isAsyncFunc(fn) | 判断是否为异步函数 |
numUtil — 数字工具
| 方法 | 说明 |
|------|------|
| randomInt(len) | 生成指定长度随机整数 |
dateUtil — 日期工具
| 方法 | 说明 |
|------|------|
| mm | moment 实例(中文 locale) |
| getTime(hours, sec) | 获取时间戳,可选偏移 |
| humanizeDuration(begin, end) | 人性化时长显示 |
| isWorkDay(date) | 是否工作日 |
| isFriday(date) | 是否周五 |
| isMonthEnd(date) | 是否月末 |
📁 文件 & Shell
fileUtil — 文件操作
| 方法 | 说明 |
|------|------|
| cp(from, to) | 拷贝文件或文件夹 |
| mockFile(target, sizeMb) | 生成指定大小的文件 |
| delete(file) | 删除文件或文件夹 |
| tmpFile(ext) | 获取临时文件路径 |
| tmpdir() | 系统临时目录路径 |
| getSizeKb(target) | 文件/文件夹大小 (KB) |
| checkPath(target) | 路径合法性检查 |
| clean(file) | 清空文件内容 |
| deleteOldFiles(dir, opts) | 按时间删除旧文件 |
| rename(old, new) | 重命名文件 |
| genEmptyFile(opts) | 创建空白文件 |
| cleanDir(dir) | 清空文件夹 |
| saveTempFile(urlOrStr) | 下载 URL 或保存字符串为临时文件 |
| saveTempFileSync(url) | 同步下载文件 |
| saveFileStr(str, dest) | 保存字符串到文件(异步) |
| saveFileStrSync(str, dest) | 保存字符串到文件(同步) |
| saveFileUrl(url, dest, name) | 通过 URL 保存文件 |
| getFileStr(target) | 读取文件字符串 |
| getFileRowCount(target) | 获取文件行数 |
| getMd5(file) | 计算文件 MD5(异步) |
| getMd5ByShell(file) | 计算文件 MD5(同步) |
| getFileBufferByUrl(url) | 通过 HTTP 获取文件 Buffer |
| getJsonByUrl(url) | 通过 HTTP 获取 JSON 数据 |
| getFirstLine(target) | 读取文件第一行 |
| getLines(target, limit) | 读取文件行数组 |
| getTailLinesStr(target, lines) | 读取末尾几行 |
| getHeadLinesStr(target, lines) | 读取开头几行 |
| createFile(target, data) | 创建文件并写入初始数据 |
| getJSON(target) | 读取 JSON 文件 |
| img2base64(target) | 图片转 base64 |
| dirWalker(dir) | 递归遍历文件夹 |
| lineOfCode(opts) | 代码行数统计(依赖 cloc) |
| savePressFileAndDeploy(url, dest) | 下载压缩包并自动解压 |
shUtil — Shell 工具
| 方法 | 说明 |
|------|------|
| processExist(name) | 进程是否存在(跨平台) |
| pidExist(pid) | 指定 PID 是否存在 |
| safeKill(pid) | 安全终止进程树 |
| cmdExist(cmd) | 命令是否存在(跨平台) |
| timeOut(cmd, sec) | 命令超时执行 |
| findFilesByText(opts) | 按内容搜索文件(跨平台) |
| getMacSysRunTimeInfo() | macOS 系统运行信息¹ |
| getMacAvailStorage() | macOS 剩余存储空间¹ |
| isHdpiDisplay() | 检测 Retina / 4K 显示器¹ |
| nohup(cmd, sec) | 后台运行命令(仅 Unix) |
| log(cmd, logname) | 命令输出重定向到日志 |
¹ 仅 macOS 可用,Windows/Linux 调用时返回
undefined并输出 warning。
hostUtil — Hosts 管理
| 方法 | 说明 |
|------|------|
| getHosts(format) | 获取 hosts 文件内容 |
| bak(bakFile) | 备份 hosts 文件 |
| restoreBak(bakFile) | 从备份恢复 |
| check(ip, host) | 检查 hosts 映射 |
| upsert(ip, host) | 插入或更新映射 |
| remove(host, ip) | 删除映射 |
| setHosts(hosts) | 批量设置映射 |
| cleanHosts(hosts) | 批量清理映射 |
| removeHosts(hosts) | 批量删除映射 |
⚡ 异步 & 基础工具
asyncUtil — 异步工具
| 方法 | 说明 |
|------|------|
| sleep(ms, tick) | 异步延时,可选每秒打印进度 |
baseUtil — 基础工具
| 方法 | 说明 |
|------|------|
| sleep(ms) | 异步延时(re-export) |
| deeplog(obj, depth) | 深度打印对象内容 |
| getEnv(key) | 获取环境变量 |
| getProcessBar(total) | 创建命令行进度条 |
| store(key, value) | 本地 KV 文件缓存读写 |
| encrypt(str, key, iv) | DES 加密 |
| decrypt(encrypted, key, iv) | DES 解密 |
| genRsaKeyPairByNodeRsa() | 生成 RSA 密钥对 |
| rsaEncrypt(pubKey, raw) | RSA 公钥加密 |
| rsaDecrypt(priKey, data) | RSA 私钥解密 |
| uuid() | 生成 UUID v7 |
| getLocalIP() | 获取本机局域网 IP |
| waitUntil(fn, waitMs, intervalMs) | 等待直到条件满足 |
| warpPromise(promise, timeout) | Promise 超时 + 中断 |
| retry(fn, count, interval) | 异步重试 |
| safeRequire(file) | 清除缓存后加载模块 |
| getCallerData() | 获取调用堆栈信息 |
| getDepsPkgVersion(path, name) | 获取依赖包版本号 |
| logRes(resp) | 格式化打印响应数据 |
resUtil — 响应构建
| 方法 | 说明 |
|------|------|
| success(data) | 成功响应 { code: 200 } |
| error(message) | 服务器错误 { code: 500 } |
| authError(message) | 认证错误 { code: 401 } |
| paramError(message) | 参数错误 { code: 400 } |
| formatRes(data, code, msg) | 自定义响应构建 |
🌐 网络 & 客户端
OssClient — 阿里云 OSS
import { OssClient } from 'utils-ok';
const oss = new OssClient({
region: 'oss-cn-hangzhou',
bucket: 'my-bucket',
accessKeyId: 'AK',
accessKeySecret: 'SK',
});
await oss.put('./local.txt', 'remote.txt'); // 上传
await oss.get('remote.txt', './download.txt'); // 下载
await oss.putTxt('hello', 'hello.txt'); // 上传字符串
await oss.putJSON({ key: 'value' }, 'data.json');// 上传 JSON
const content = await oss.getFileStr('file.txt');// 读取内容
await oss.postDir('./dist', 'oss-dist/'); // 上传整个目录| 方法 | 说明 |
|------|------|
| put(localFile, ossFile) | 上传本地文件 |
| putUrl(url, ossFile) | URL 转存 |
| putTxt(str, ossFile) | 上传字符串 |
| putJSON(obj, ossFile) | 上传 JSON 对象 |
| store(key, obj, merge) | 存储/更新 JSON 对象(支持合并) |
| get(ossFile, localFile) | 下载文件 |
| getFilesByPath(ossDir, destDir) | 下载文件夹 |
| getFileStr(ossFile) | 读取为字符串 |
| getJSON(ossFile) | 读取并解析 JSON |
| deleteFile(ossFile) | 删除文件 |
| deleteFolder(ossPath) | 递归清空文件夹 |
| exist(ossFile) | 检查是否存在 |
| getFiles(ossPath) | 获取文件列表 |
| getFolders(ossPath) | 获取子文件夹列表 |
| postDir(localPath, ossFile) | 递归上传目录 |
| postDirZip(localPath, ossFile) | 压缩为 ZIP 上传 |
| postDirTarGz(localPath, ossFile) | 压缩为 tar.gz 上传 |
| setLifeCycle(days) | 设置生命周期规则 |
| getLifeCycle() | 查询生命周期规则 |
| delLifeCycle() | 删除生命周期规则 |
MinioClient — MinIO 对象存储
API 与 OssClient 类似,额外支持:
| 方法 | 说明 |
|------|------|
| getTmpUrl(ossFile, expires) | 获取临时下载链接(默认 1h) |
| uploadFile(localFile, ossFile) | 上传本地文件 |
| uploadDir(localPath, ossDir) | 递归上传目录 |
| downloadDir(ossDir, destDir) | 下载目录 |
| downloadFile(ossFile, localFile) | 下载文件 |
| getStr(ossFile) | 读取为字符串 |
| uploadDirZip(localPath, ossFile) | 压缩为 ZIP 上传 |
| uploadDirTarGz(localPath, ossFile) | 压缩为 tar.gz 上传 |
| setBucketPolicyGetFree(bktName) | 设置 bucket 为公开读取 |
| ossExist(ossFile) | 检查文件或目录是否存在 |
MysqlClient / DBClient — MySQL 数据库
import { DBClient } from 'utils-ok';
const db = new DBClient({ uri: 'mysql://user:pass@host:3306/dbname' });
// 内部基于 Sequelize,支持 Model 定义
await db.close();DingClient — 钉钉机器人
import { DingClient } from 'utils-ok';
const ding = new DingClient('your-access-token', 'secret-key');
await ding.send('Hello, 钉钉!');
await ding.sendMd('通知标题', '## 正文内容');| 方法 | 说明 |
|------|------|
| send(msg, atMobiles, atUserIds) | 发送文本消息,支持 @ 用户 |
| sendMd(title, msg, atMobiles, atUserIds) | 发送 Markdown 消息 |
OpenAiClient — OpenAI 对话
import { OpenAiClient } from 'utils-ok';
const ai = new OpenAiClient({ apiKey: 'sk-xxx' });
const reply = await ai.chatCn('你好');| 方法 | 说明 |
|------|------|
| chat(prompt) | 简单对话 |
| chatCn(prompt) | 中文系统提示对话 |
| chatEn(prompt) | 英文系统提示对话 |
| createChatCompletion(messages, opts) | 创建聊天补全 |
| createCompletion(prompt, opts) | 创建补全请求 |
PopClient — 阿里云 POP SDK
封装阿里云 POP 通用调用客户端。
SlsClient — 阿里云 SLS 日志服务
封装阿里云 SLS 日志服务客户端。
YuqueClient — 语雀 API
封装语雀知识库 API 客户端。
🛠️ 工程辅助
gitUtil — Git 工具
| 方法 | 说明 |
|------|------|
| safeCheckout(opts) | 安全检出分支/commit(带超时重试) |
| getGitDir() | 获取 Git 仓库根目录 |
| getBranchName() | 获取当前分支名 |
| getBranchDiffFiles(opts) | 获取工作分支 diff 文件列表 |
| getBranchSourceCommit() | 获取当前分支起点 commit |
| getLastCommit(opts) | 获取最后一次 commit 详情 |
| formatGitHttpUrl(remote) | Git SSH URL → HTTP URL 转换 |
| getPRList(branch) | 查询分支上的 PR 列表 |
lintUtil — Lint 工具
| 方法 | 说明 |
|------|------|
| lintProj(opts) | 全量 lint(eslint + blacklint + tsc + 用例规范) |
| lintFixProj() | 自动修复 lint 问题 + 清除 .only() 标记 |
| eslint() | 单独执行 eslint 检查 |
| tscLint() | 单独执行 tsc 类型检查 |
| blackLint(dirs) | 单独执行 blacklint 检查 |
| testDirLint(testDir) | 用例命名规范检查 |
ProjUtil — 项目路径工具
import { ProjUtil } from 'utils-ok';
const proj = new ProjUtil(__dirname);
proj.getPkgVersion(); // 获取版本号
proj.getResourcePath(); // 获取 resource 目录
proj.bin('eslint', true); // 执行 node_modules/.bin 下的命令| 方法 | 说明 |
|------|------|
| getPkgVersion() | 获取 package.json 版本号 |
| getPkg() | 读取 package.json |
| getProjPath() | 获取项目路径 |
| getRootProjPath() | 获取项目根路径 |
| getResourcePath() | 获取 resource 目录 |
| getModulesPath() | 获取 node_modules 路径 |
| bin(cmd, async, silent) | 执行 .bin 下的命令 |
ffmpegUtil — 视频处理
| 方法 | 说明 |
|------|------|
| mov2mp4(fileMov, fileMp4) | MOV → MP4 转码 |
| addPoster(srcMp4, pngFile) | 插入封面首帧 |
| getVideoLastImg(srcMp4, destPng) | 提取视频最后一帧 |
| setVideoLastImgAsPoster(srcMp4) | 设置视频最后一帧为封面 |
🤖 浏览器自动化
WebDriver — Playwright 浏览器驱动
import { WebDriver } from 'utils-ok';
const driver = new WebDriver({ headless: true });
await driver.init();
await driver.goto('https://example.com');
await driver.clickOn('#submit');
await driver.checkText('提交成功');
await driver.stop();| 方法 | 说明 |
|------|------|
| init() | 初始化浏览器 |
| stop() | 关闭浏览器 |
| goto(url) | 导航到 URL |
| clickOn(selector) | 点击元素 |
| input(text, selector) | 输入文本 |
| check(selector) | 检查元素存在 |
| checkText(text) | 检查页面包含文本 |
| checkMulti(selectors) | 并行检查多个选择器 |
| checkNotExists(selector) | 检查元素不存在 |
| getText(selector) | 获取元素文本 |
| waitForElement(selector, timeout) | 等待元素出现 |
| waitForAny(selectors, opts) | 等待任意选择器出现 |
| waitForFocusByCSS(css) | 等待元素获得焦点 |
| getElement(selector, opts) | 查找单个元素 |
| getElementsCount(selector) | 获取匹配元素数量 |
| hover(selector) | 鼠标悬停 |
| pressKeys(key, ...more) | 键盘按键 |
| mouse(action, ...args) | 鼠标操作 |
| keyboard(action, ...args) | 键盘操作 |
| dragAndDrop(source, target, ...) | 拖拽元素 |
| elementScreenShot(opts) | 元素截图 |
| redirect(url) | JS 重定向 |
| curl(clean) | 获取当前 URL |
| execute(script, args) | 执行页面 JS |
| coverage(opts) | 代码覆盖率收集 |
| webFetch(opts) | 前端注入执行 fetch |
| mixin(api) | 混入自定义方法 |
RemoteLoginClient — 远程登录
import { RemoteLoginClient } from 'utils-ok';
const client = new RemoteLoginClient({
ip: '192.168.1.100',
username: 'root',
password: 'pass',
});
await client.ssh('ls -la'); // SSH 远程执行命令
await client.vnc(); // macOS 打开 VNC 连接| 方法 | 说明 |
|------|------|
| ssh(cmd) | SSH 远程执行命令 |
| vnc() | 打开 VNC 连接(macOS) |
📋 日志
项目内置 wLogger(基于 winston),支持多级别日志输出:
import { wLogger } from 'utils-ok';
const logger = wLogger();
logger.info('应用启动');
logger.debug('调试信息', { data: [1, 2, 3] });
logger.error('出错了', error);跨平台支持
| 模块 | macOS | Windows | Linux | |------|:-----:|:-------:|:-----:| | 数据处理 (strUtil/arrUtil/...) | ✅ | ✅ | ✅ | | 文件操作 (fileUtil) | ✅ | ✅ | ✅ | | Shell 工具 (shUtil) | ✅ | ✅¹ | ✅ | | Hosts 管理 (hostUtil) | ✅ | ✅ | ✅ | | Git 工具 (gitUtil) | ✅ | ✅² | ✅ | | 云存储 (OssClient/MinioClient) | ✅ | ✅ | ✅ | | 数据库 (DBClient) | ✅ | ✅ | ✅ | | 浏览器自动化 (WebDriver) | ✅ | ✅ | ✅ | | AI 对话 (OpenAiClient) | ✅ | ✅ | ✅ | | 钉钉机器人 (DingClient) | ✅ | ✅ | ✅ |
¹
getMacSysRunTimeInfo、isHdpiDisplay、nohup为 Unix/macOS 专属功能。 ² Windows 需要安装 Git for Windows。
版本历史
| 版本 | 说明 | |------|------| | 2.0.0 | 全面跨平台重构,支持 Windows/macOS/Linux | | 1.x | 初始版本,仅 macOS/Linux |
License
MIT
