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

@damoxing/datasource-manager

v0.4.0

Published

HTTP-agnostic multi-datasource lifecycle, routing, heartbeat, and recovery manager.

Readme

@damoxing/datasource-manager 中文文档

@damoxing/datasource-manager 是一个与 HTTP 框架无关的 Node.js 多数据源生命周期管理库。它负责数据源配置加载、路由、健康状态、连接池恢复、心跳、重试、优雅停机、运行期治理和基础可观测性。

它不是 ORM,也不负责实体映射、SQL 迁移、业务接口或 Web 路由。核心目标是把多数据库连接池管理从业务项目里独立出来,形成可发布、可测试、可复用的基础库。

功能概览

  • 多数据源配置加载和状态管理
  • 默认数据源、严格路由、route_keys 路由
  • 兼容老业务字段 jgbh_listgetByJgbh()
  • Oracle、达梦 DM、PostgreSQL、GaussDB/openGauss、Kingbase 适配器
  • 统一连接池治理配置和驱动字段映射
  • 心跳检查、连接池恢复、连接异常查询重试
  • 稳定健康输出 getHealth()
  • 指标输出 getMetrics()
  • 运行期新增、删除、更新和重载数据源
  • 读写分离和分组路由
  • 配置密钥解析和日志脱敏
  • 进程信号优雅停机
  • CJS、ESM 和 TypeScript 类型声明

安装

npm install @damoxing/datasource-manager

数据库驱动是可选 peer dependency,只需要安装实际使用的驱动:

npm install pg
npm install oracledb
npm install dmdb

pg 同时用于 PostgreSQL、GaussDB/openGauss 和 Kingbase。

基础使用

CommonJS:

const {
    DataSourceManager,
    createDefaultAdapterFactories
} = require('@damoxing/datasource-manager');

const manager = new DataSourceManager({
    config,
    logger,
    adapterFactories: createDefaultAdapterFactories({
        logger,
        logParams: 'redacted'
    }),
    shutdownSignals: ['SIGTERM', 'SIGINT']
});

await manager.initialize();

const db = manager.getByRouteKey('tenant-a');
const row = await db.get('SELECT 1 AS health_check');

await manager.closeAll();

ESM:

import {
    DataSourceManager,
    createDefaultAdapterFactories
} from '@damoxing/datasource-manager';

const manager = new DataSourceManager({
    config,
    adapterFactories: createDefaultAdapterFactories()
});

配置结构

{
    "strict_routing": true,
    "default_datasource": "pg_main",
    "datasources": [
        {
            "id": "pg_main",
            "type": "pg",
            "jgbh_list": ["1001"],
            "route_keys": ["tenant-a"],
            "config": {
                "host": "127.0.0.1",
                "port": 5432,
                "database": "app",
                "user": "app",
                "password": "env:DB_PASSWORD"
            }
        }
    ]
}

字段说明:

  • strict_routing:开启后,未知路由会直接抛错,不回落默认库。
  • default_datasource:没有传路由 key 时使用的默认数据源。
  • datasources[].id:数据源唯一标识。
  • datasources[].type:数据源类型,支持 oracledmpggaussopengausskingbase
  • jgbh_list:兼容业务机构编号路由。
  • route_keys:通用路由 key,推荐新代码优先使用。
  • config:传给具体数据库驱动的连接配置。

路由使用

推荐新代码使用通用路由:

const db = manager.getByRouteKey('tenant-a');

老业务可以继续使用机构编号:

const db = manager.getByJgbh('1001');

默认库:

const db = manager.getDefaultHandle();

直接按数据源 ID 获取:

const db = manager.getHandle('pg_main');

Codex MCP Server

本包内置 stdio MCP server,Codex 可以通过同一套 DataSourceManager 和数据库适配器检查指定数据源:

npm run build
DAMOXING_MCP_CONFIG=/absolute/path/to/datasources.json node dist/cjs/mcp/server.js

安装包后也可以使用 bin 入口:

damoxing-datasource-mcp

MCP server 当前提供:

  • damoxing_health:查看脱敏健康状态和指标。
  • damoxing_query:只读 SQL 查询。
  • damoxing_list_tables / damoxing_describe_table:查看表、字段、索引、约束。
  • damoxing_list_routines / damoxing_get_routine_definition:查看函数、过程、包等对象。
  • damoxing_explain:查看只读 SQL 执行计划。
  • damoxing_exec:显式 SQL 执行。
  • damoxing_open_session:打开 MCP 专用固定物理连接会话。
  • damoxing_session_query / damoxing_session_exec:在同一个 sessionId 和同一个物理连接上执行 SQL。
  • damoxing_session_commit / damoxing_session_rollback:提交或回滚固定会话事务。
  • damoxing_cancel_session_operation:在驱动支持时取消当前会话操作。
  • damoxing_get_notices:获取并清空固定会话捕获的 NOTICE。
  • damoxing_get_audit_events:获取经过脱敏的有界固定会话审计事件。
  • damoxing_close_session:回滚未提交事务并释放固定连接。

同一个固定会话内的操作会串行执行,不会并发使用同一个连接。PostgreSQL 兼容数据库的固定会话会显式开启事务;关闭会话或连接异常时会先回滚再释放连接。固定连接丢失后不会自动切换连接重试,而是返回结构化的 SESSION_CONNECTION_LOST 错误。

默认只允许只读会话。读写会话必须同时设置 DAMOXING_MCP_ALLOW_WRITE=true,并在打开会话和写操作时传 confirmWrite=trueDROPTRUNCATEDELETEUPDATEALTER 等破坏性 SQL 还需要额外设置 DAMOXING_MCP_ALLOW_DESTRUCTIVE=trueconfirmDestructive=true

需要由运维方把生产数据源 ID 配置到 DAMOXING_MCP_PRODUCTION_DATASOURCES;这些数据源默认拒绝调试。只有同时设置 DAMOXING_MCP_ALLOW_PRODUCTION_DEBUG=true,且打开会话时传 confirmProduction=true,才允许建立固定会话。

固定会话限制可通过以下环境变量设置:

  • DAMOXING_MCP_MAX_SESSIONS:全局最大会话数,默认 5
  • DAMOXING_MCP_MAX_SESSIONS_PER_DATASOURCE:单数据源最大会话数,默认 2
  • DAMOXING_MCP_SESSION_IDLE_TIMEOUT_MS:空闲超时,默认 300000 毫秒。
  • DAMOXING_MCP_SESSION_MAX_LIFETIME_MS:绝对生命周期,默认 1800000 毫秒。
  • DAMOXING_MCP_SESSION_CLEANUP_INTERVAL_MS:过期清理间隔,默认 30000 毫秒。
  • DAMOXING_MCP_AUDIT_MAX_EVENTS:内存审计事件上限,默认 1000

固定会话注册表会保留有界的内存审计记录,内容包括动作、结果、数据源/会话标识、耗时、行数、SQL 类型、归一化 SQL 指纹以及参数数量/参数名。审计记录不会保存 SQL 原文和参数值,可通过 damoxing_get_audit_events 查询。

固定会话使用独立且延迟初始化的 MCP 数据源管理器。直接 import / require('@damoxing/datasource-manager') 不会加载 MCP SDK、创建 MCP 定时器或预留调试连接,因此不改变 Node.js 项目的直接使用方式。

2026 年 7 月 15 日使用本地 OrbStack 数据库完成的固定会话实测结果:

| 数据库 | 固定连接/事务 | 会话状态 | NOTICE | 超时/取消 | | --- | --- | --- | --- | --- | | PostgreSQL | 已通过 | 临时表、会话变量已通过 | 已通过 | statement_timeout 和显式取消已通过 | | openGauss | 已通过 | 临时表、会话变量已通过 | 已通过 | statement_timeout 和显式取消已通过 | | Oracle | 已通过 | SID、CLIENT_INFO 已通过 | 不支持 PostgreSQL NOTICE 语义 | callTimeout 已通过,超时后连接仍可用 | | 达梦 DM | 已通过 | 会话 ID、全局临时表已通过 | 当前驱动不支持 | 当前 dmdb 驱动不提供可靠取消/操作超时,MCP 会明确返回不支持 | | Kingbase | 未完成 | 本地容器因开发许可证过期无法启动数据库进程 | 未验证 | 未验证 |

可分别运行 npm run test:integration:session:pgnpm run test:integration:session:opengaussnpm run test:integration:session:oraclenpm run test:integration:session:dm 复验。测试只创建隔离的临时或探针对象,并在结束时清理。

当前阶段只是“固定会话调试基础”,还不是完整的存储过程运行时调试。结构化 OUT/INOUT、游标句柄与 FETCH、过程性能 Trace、断点和单步能力仍按路线图后续阶段实现。

仓库内置 Codex skill 位于 skills/damoxing-database-mcp

连接池治理

可以在 datasource 顶层配置统一 pool 参数:

{
    "id": "pg_main",
    "type": "pg",
    "pool": {
        "minPoolSize": 1,
        "maxPoolSize": 10,
        "acquireTimeoutMs": 3000,
        "connectTimeoutMs": 3000,
        "validationTimeoutMs": 1000,
        "idleTimeoutMs": 60000,
        "maxLifetimeMs": 1800000,
        "keepaliveMs": 30000
    },
    "config": {}
}

也可以写在 config.pool 里。管理器会把统一字段映射到不同驱动的字段,并在不支持某个字段时通过结构化日志输出 unsupportedPoolOptions

当前映射重点:

  • Oracle:poolMinpoolMaxqueueTimeoutconnectTimeoutpoolTimeoutmaxLifetimeSessionpoolPingInterval
  • DM:poolMinpoolMax
  • PostgreSQL/Gauss/Kingbase:minmaxconnectionTimeoutMillisidleTimeoutMillismaxLifetimeSeconds

如果 minPoolSize > maxPoolSize,初始化配置时会直接抛错。

也可以直接调用工具函数做诊断:

const { applyPoolGovernance } = require('@damoxing/datasource-manager');

const result = applyPoolGovernance('pg', {}, {
    minPoolSize: 1,
    maxPoolSize: 5
});

健康状态

getHealth() 返回稳定、脱敏的健康结构:

const health = manager.getHealth();

核心字段:

  • initialized
  • strictRouting
  • defaultDatasourceId
  • routeCount
  • heartbeat.enabled
  • heartbeat.running
  • shutdownHooks.installed
  • summary.total
  • summary.ready
  • summary.failed
  • summary.unhealthy
  • summary.byStatus
  • datasources[].id
  • datasources[].type
  • datasources[].status
  • datasources[].lastError

健康输出不会包含 datasource 原始配置,因此不会暴露密码和连接串。

指标输出

getMetrics() 用于生产可观测性:

const metrics = manager.getMetrics();

当前包含:

  • 初始化成功和失败次数
  • 心跳成功和失败次数
  • 恢复尝试、成功和失败次数
  • 查询成功和失败次数
  • 查询连接异常次数
  • 查询重试次数
  • 事务连接异常次数
  • 初始化、心跳、恢复、查询延迟摘要

指标标签保持有限且安全,只包含 idtypestatus 等字段,不包含 SQL、参数、密码或连接串。

心跳和恢复

初始化成功后,心跳会执行轻量 SQL:

  • Oracle/DM:SELECT 1 AS health_check FROM DUAL
  • 其他:SELECT 1 AS health_check

当 heartbeat 发现连接异常时,会关闭旧 adapter,重新创建 pool,并再次 ping。查询过程中遇到连接类异常时,会恢复 pool 并重试一次。

事务不会自动重放。如果事务执行中出现连接异常,管理器会恢复 pool,但会把原始异常抛出,避免重复提交或业务状态不一致。

运行期数据源治理

可以在服务运行中变更数据源:

await manager.addDatasource({
    id: 'tenant_a',
    type: 'pg',
    route_keys: ['TENANT_A'],
    config: {}
});

await manager.updateDatasource('tenant_a', {
    id: 'tenant_a',
    type: 'pg',
    route_keys: ['TENANT_A'],
    config: {}
});

await manager.removeDatasource('tenant_a');

await manager.reloadConfig(nextConfig);

updateDatasource() 会先初始化并 ping 新配置,确认 ready 后才关闭旧 pool。如果新配置失败,旧数据源继续保留。

reloadConfig() 会重建数据源集合,适合配置中心刷新或管理后台变更。

读写分离和分组路由

配置示例:

{
    "datasources": [
        { "id": "tenant_a_master", "type": "pg", "config": {} },
        { "id": "tenant_a_read_1", "type": "pg", "config": {} },
        { "id": "tenant_a_read_2", "type": "pg", "config": {} }
    ],
    "groups": {
        "tenant_a": {
            "write": "tenant_a_master",
            "read": [
                "tenant_a_read_1",
                { "id": "tenant_a_read_2", "weight": 2 }
            ],
            "strategy": "round-robin",
            "fallbackToWrite": true
        }
    }
}

使用:

const readDb = manager.getReadHandle('tenant_a');
const writeDb = manager.getWriteHandle('tenant_a');

支持的读路由策略:

  • round-robin
  • random
  • weighted
  • first-ready

不健康的读库会被跳过。如果全部读库不可用,并且 fallbackToWrite !== false,读请求会回落到写库。

配置安全

支持四种常用方式:

{
    "password": "env:DB_PASSWORD",
    "token": "secret:database/token",
    "connectString": "postgres://app:${DB_PASSWORD}@localhost/db",
    "encrypted": "ENC(ciphertext)"
}

初始化:

const manager = new DataSourceManager({
    env: process.env,
    secretResolver: async key => loadSecretFromVault(key),
    decryptor: async value => decrypt(value),
    config
});

说明:

  • ${DB_PASSWORD}:从 env 中插值。
  • env:DB_PASSWORD:整个字段从环境变量读取。
  • secret:database/token:通过 secretResolver 读取。
  • ENC(ciphertext):通过 decryptor 解密。

解析出来的密钥会从健康状态、指标、结构化错误和管理器日志中脱敏。

日志

数据源异常日志会带结构化上下文:

{
    datasourceId,
    type,
    jgbh,
    jgbhList,
    routeKeys,
    status,
    lastError,
    error
}

SQL 文本默认记录,SQL 参数默认不记录。可以按需开启参数脱敏日志:

const adapterFactories = createDefaultAdapterFactories({
    logger,
    logSql: true,
    logParams: 'redacted',
    redactKeys: ['password', 'token', 'secret'],
    redactValue: '[REDACTED]'
});

logParams 可选值:

  • false'off':不记录参数。
  • true'redacted':记录脱敏参数。
  • 'raw':记录原始参数,只建议本地调试使用。

优雅停机

const manager = new DataSourceManager({
    shutdownSignals: ['SIGTERM', 'SIGINT'],
    exitOnShutdownSignal: true,
    adapterFactories,
    config
});

收到信号后,管理器会停止 heartbeat,移除 shutdown hook,关闭全部 pool,并把数据源状态标记为 closed

也可以手动调用:

await manager.closeAll();

发布和验证

本地验证:

npm test
npm run release:check

release:check 会执行:

  • TypeScript 构建
  • CJS smoke test
  • ESM smoke test
  • TypeScript 类型 smoke test
  • npm pack --dry-run

发布到 npm 前,应确认:

  • package.json 版本已更新。
  • CHANGELOG.md 已记录版本。
  • npm test 通过。
  • npm run release:check 通过。
  • npm Trusted Publisher 已配置。
  • GitHub Release 使用新版本 tag。

当前边界

本库当前不做:

  • ORM 实体映射
  • SQL migration
  • 自动重放事务
  • HTTP 路由绑定
  • 业务权限判断
  • 分布式事务核心实现

这些能力可以通过独立 adapter 或上层应用接入,不建议塞进核心包。

后续路线

后续待办见 ROADMAP.md。当前 P0/P1 中,连接池治理、metrics、运行期数据源治理、读写分组和配置安全已经具备基础实现;Prometheus/OpenTelemetry adapter、真实数据库 idle/maxLifetime 集成测试、DM worker 隔离仍在后续迭代中。