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

asai-nodejs-db

v0.2.8

Published

asai for you

Readme

asai-nodejs-db

统一 SQL 风格的数据库操作插件。通过同一套 Idb 数据结构与 sqlDb() 接口,对接 MySQL、SQLite、Excel、本地文件四种存储后端。


快速开始

import initDb from './src/plugs/asai-nodejs-db/db';

// 创建驱动实例(默认 file)
const db = initDb('sqlite', {
  database: './data/app.db',
  create: 1,
  poolMin: 2,
  poolMax: 10,
});

// 统一查询
const users = await db.sqlDb({
  type: 'select',
  table: 'users',
  field: ['id', 'name'],
  where: [['age', '>', 18]],
  order: [['id', 'desc']],
  limit: 10,
});

架构概览

asai-nodejs-db/
├── db.ts                 # 工厂入口 initDb(type, config)
└── src/
    ├── type.ts           # Idb 接口定义
    ├── common.ts         # 公共工具(Promise 封装、条件解析等)
    ├── Sql.ts            # SQL 字符串生成器
    ├── mysql/Index.ts    # MySQL 连接池驱动
    ├── sqlite/Index.ts   # SQLite 连接池 / 单连接驱动
    ├── excel/Index.ts    # Excel 文件驱动
    └── file/Index.ts     # 本地文件系统驱动

调用链路:

initDb(type, config)
    → new XxxDriver(config)
        → sqlDb(Idb)
            → Sql.makeSql(Idb)   [mysql / sqlite]
            → 文件 / Excel 专有逻辑   [file / excel]

驱动对比

| 类型 | npm 依赖 | 存储介质 | 适用场景 | |------|----------|----------|----------| | mysql | mysql | MySQL 8 数据库 | 正式业务库 | | sqlite | sqlite3 | 本地 .db 文件 | 嵌入式、单机、测试 | | excel | xlsx | .xlsx / .xls | 报表、轻量表格数据 | | file | 无(Node fs) | 目录 + JSON 文件 | 配置、轻量 CMS 数据 |


Idb 接口说明

所有驱动共用 Idb 对象描述一次操作:

| 字段 | 类型 | 说明 | |------|------|------| | type | string | select / insert / update / delete;file 额外支持 re(恢复软删除) | | table | string | 表名;file 类型为相对目录名(如 config 对应 dir/config/) | | field | string[] | string | 字段列表,如 ['id','name']'id,name' | | value | [][] | string | 插入行,如 [['Tom', 20], ['Jerry', 18]] | | set | [][] | string | 更新赋值,如 [['name','Tom']][['count','+',1]] | | where | [][] | string | 条件,支持 or/and[字段, 运算符, 值] 混排 | | order | [][] | string | 排序,如 [['id','desc']] | | limit | number | 限制返回行数(select) | | list | number | file:列表模式,返回 { open, delete } | | deltrue | any | file:软删除模式下传 1 表示物理删除 | | filename | string | file:目录模式下的子文件名 | | as | number | file:1 单文件 JSON 解析;2 目录 JSON 聚合查询 |

WHERE 条件示例

// 简单条件
where: [['id', '=', 1]]

// 组合条件(or/and 会生成括号分组)
where: ['or', ['name', 'like', '%张%'], 'and', ['age', '>', 18]]

// 原始 SQL 片段
where: 'status = 1 AND deleted = 0'

SET 更新示例

// 直接赋值
set: [['name', '新名称']]

// 自增(mysql/sqlite 生成 field=field+1)
set: [['count', '+', 1]]

// 字符串拼接(mysql CONCAT)
set: [['title', 'CONCAT', '后缀']]

各驱动配置

MySQL

const db = initDb('mysql', {
  host: 'localhost',
  user: 'root',
  password: '123456',
  database: 'mydb',
  create: 1,          // 表不存在时自动建库建表
});

| 参数 | 说明 | |------|------| | host / user / password / database | 标准 MySQL 连接参数 | | create | 非 0 / true 时,insert 遇「表不存在」自动建库建表 |

方法:

| 方法 | 说明 | |------|------| | sqlDb(sql) | Promise 查询 | | query(sql, callback) | 回调风格查询 | | close(callback?) | 关闭连接池 |

安装说明见 src/mysql/MYSQL.md


SQLite

const db = initDb('sqlite', {
  database: './data/app.db',
  create: 1,
  usePool: true,       // 默认 true,false 为单连接模式
  poolMin: 2,
  poolMax: 10,
  idleTimeout: 30000,
  acquireTimeout: 5000,
  $asai: globalAsai,  // 可选,注入日志对象
});

| 参数 | 默认值 | 说明 | |------|--------|------| | database | — | .db 文件路径(自动创建目录) | | usePool | true | 是否启用连接池 | | poolMin | 2 | 最小连接数 | | poolMax | 10 | 最大连接数 | | idleTimeout | 30000 | 空闲连接回收时间(ms) | | acquireTimeout | 5000 | 获取连接超时(ms) | | create | — | 非 0 时 insert 遇「表不存在」自动建表 |

方法:

| 方法 | 说明 | |------|------| | sqlDb(sql) | Promise 查询 | | query(sql, callback) | 回调风格查询 | | getPoolStatus() | 连接池状态 { total, inUse, idle, waiting, min, max } | | close() | 关闭连接池或单连接 |

性能说明: 连接池在 acquire 时仅对长时间空闲的连接执行 SELECT 1 检测,刚释放的连接直接复用,降低高频查询开销。

安装说明见 src/sqlite/SQLite.md


Excel

const db = initDb('excel', {
  database: './data/report.xlsx',
});

| 方法 | 说明 | |------|------| | sqlDb(sql) | 通过 Idb 操作工作表(table 为 sheet 名,空则用首个 sheet) | | readSheet(where, order, top, sheetName) | 直接读取并过滤 | | addData(data, sheetName) | 追加行 | | editData(data, where, sheetName) | 更新首条匹配行 | | deleteData(where, sheetName) | 删除首条匹配行 |

限制: WHERE 仅支持等值匹配(字段 === 值);ORDER 按数值字段排序。


File(文件系统)

const db = initDb('file', {
  dir: './webdata/webdb/',
  ext: '.json',
  create: 1,
  del: 1,             // 启用软删除(重命名为 .delete.ext)
});

| 参数 | 默认值 | 说明 | |------|--------|------| | dir | — | 数据根目录(相对 process.cwd()) | | ext | '' | 文件扩展名,.* 表示无扩展名 | | del | 0 | 非 0 启用软删除 | | create | false | 自动创建不存在的目录 |

sqlDb 路由:

| type | 行为 | |--------|------| | insert | value[0][文件名, 内容],写入 table/文件名 | | delete | 从 where 取文件名并删除 | | re | 恢复软删除文件 | | update | 从 where 取文件名,set[0][1] 为新内容 | | select | 有 whereas !== 2 → 读单文件;as === 2 → 目录 JSON 聚合;否则 → 列表 |

安全: 路径解析限制在 dir 根目录内,阻止 ../ 路径穿越。

跨平台: 路径统一使用 Node.js path 模块(path.resolve / path.join),兼容 Windows 正反斜杠、Linux/macOS 路径及不同盘符场景。table 支持 URL 风格的 / 分隔(如 cocontrol/projectconfig)。


使用示例

增删改查(mysql / sqlite)

// 查询
await db.sqlDb({
  type: 'select',
  table: 'users',
  field: ['id', 'name', 'age'],
  where: [['age', '>', 18]],
  order: [['id', 'DESC']],
  limit: 10,
});

// 批量插入
await db.sqlDb({
  type: 'insert',
  table: 'users',
  field: ['name', 'age'],
  value: [['张三', 25], ['李四', 30]],
});

// 更新
await db.sqlDb({
  type: 'update',
  table: 'users',
  set: [['name', '王五']],
  where: [['id', '=', 1]],
});

// 删除
await db.sqlDb({
  type: 'delete',
  table: 'users',
  where: [['id', '=', 1]],
});

File 目录 JSON 查询(as=2)

const list = await db.sqlDb({
  type: 'select',
  table: 'config',
  as: 2,
  field: ['key', 'value', 'title'],
  where: [['title', 'like', '设置']],
  order: [['key', 'ASC']],
});

在 asai-host 中使用

// app.ts 中已挂载
$asai.dataserver = initDb;

// 业务代码
const DataServer = $asai.dataserver('file', { dir: './webdata/', ext: '.json', create: 1 });
const data = await DataServer.sqlDb({ type: 'select', table: 'articles', as: 2 });

Sql.ts 生成规则

Sql.makeSql(Idb) 将操作对象转为 SQL 字符串:

| type | 生成示例 | |------|----------| | insert | insert into users (name,age) values ('Tom',20) | | delete | delete from users where id = 1 | | update | update users set name='Tom' where id = 1 | | select | select id,name from users where age > 18 order by id desc limit 10 |

Sql.createSql(Idb, dialect) 自动建表,补充 id 主键与 asdate 时间戳列。

注意: SQL 由字符串拼接生成,适用于受信任的内部数据。对外部输入应自行校验或改用参数化查询。


返回值约定

sqlDb() 统一约定:

  • 查询成功且有数据 → 返回结果数组或对象
  • 查询成功但无数据 → 返回空字符串 ''
  • 失败 → Promise.reject(错误信息)

file 驱动 selectlist 模式下返回 { open: [], delete: [] }


依赖安装

# MySQL 驱动
npm install mysql

# SQLite 驱动(Windows 可能需要 node-gyp,见 SQLite.md)
npm install sqlite3

# Excel 驱动
npm install xlsx

跨平台验证

在项目根目录(webserver/)执行冒烟测试,自动覆盖 Sql 生成、路径安全、file/sqlite 读写:

npx tsx src/plugs/asai-nodejs-db/verify.mjs

支持 Windows / Linux / macOS(含 pkg 打包目标 node20-win-x64node20-linux-x64node20-linux-arm64)。


版本优化记录

本次优化在保持 API 与行为兼容的前提下:

  1. 提取 common.ts 公共模块,消除 sqlDb Promise 包装重复代码
  2. 重构 Sql.ts,用 join 替代循环拼接,修复 field 子句冗余逻辑
  3. MySQL:修复连接错误时回调未触发、连接未释放问题;新增 close();仅在表不存在时自动建表
  4. SQLite:空闲连接按需检测,减少每次 acquireSELECT 1 开销
  5. Excel:补全 sqlDbinsert/update/delete/select 的 Idb 映射
  6. File:增加路径穿越防护
  7. 完善 TypeScript 类型与关键注释