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-chain/db

v1.0.3

Published

数据库链式操作库 - 基于 @tool-chain/core,支持 Kysely、TypeORM、Drizzle ORM、Prisma等多种 ORM 框架,实现统一的链式数据库操作体验。

Readme

@tool-chain/db

npm version npm downloads Node.js Version License: MIT

基于 @tool-chain/core 的数据库链式操作库,专为构建可组合的数据库操作而设计,支持多种 ORM 框架。

English | 日本語ドキュメント

特性

多 ORM 支持 - 支持 Kysely、TypeORM、Prisma 和 Drizzle ORM 🔗 链式 API - 使用流畅的接口构建复杂的数据库操作 🔄 事务管理 - 内置事务支持,自动提交/回滚 📦 结果传递 - 在后续步骤中访问前一步的操作结果 🎯 类型安全 - 完整的 TypeScript 支持,优秀的类型推断 🛡️ 错误处理 - 集成错误处理,支持 withoutThrow 选项 ⚡ 高级特性 - 支持重试、超时等来自 @tool-chain/core 的功能 🎨 Service 模式 - 高阶函数模式,打造清晰的服务层设计

安装

npm install @tool-chain/db @tool-chain/core

然后安装你喜欢的 ORM(一个或多个):

# Kysely
npm install kysely

# TypeORM
npm install typeorm

# Prisma
npm install @prisma/client

# Drizzle ORM
npm install drizzle-orm

导入

为了避免加载不必要的依赖,适配器应该从其特定子路径导入:

// 导入核心类和类型
import { Chains } from '@tool-chain/db';
import { ChainsWithDrizzle, DrizzleAdapter } from '@tool-chain/db/drizzle';
// 导入特定适配器(仅导入需要的)
import { ChainsWithKysely, KyselyAdapter } from '@tool-chain/db/kysely';
import { ChainsWithPrisma, PrismaAdapter } from '@tool-chain/db/prisma';
import { ChainsWithTypeORM, TypeORMAdapter } from '@tool-chain/db/typeorm';

这确保如果你仅使用 Kysely,TypeORM 不会被加载,你也不会因为缺少 TypeORM 依赖而出错。

快速开始

基础用法

本库提供两种使用方式:

方式一:使用便利类(推荐)

import { ChainsWithKysely } from '@tool-chain/db/kysely';
import { Kysely } from 'kysely';

// 定义你的 service 函数
function getUser(id: number) {
  return (db: Kysely<Database>) => {
    return db.selectFrom('user').where('id', '=', id).selectAll().executeTakeFirstOrThrow();
  };
}

// 执行链式操作 - 无需手动传递 adapter
const user = await new ChainsWithKysely<Database>().use(db).chain(getUser(123)).invoke();

方式二:使用通用 Chains 类

import { Chains } from '@tool-chain/db';
import { KyselyAdapter } from '@tool-chain/db/kysely';
import { Kysely } from 'kysely';

// 定义你的 service 函数
function getUser(id: number) {
  return (db: Kysely<Database>) => {
    return db.selectFrom('user').where('id', '=', id).selectAll().executeTakeFirstOrThrow();
  };
}

// 执行链式操作 - 需要显式传递 adapter
const user = await new Chains().use(db, new KyselyAdapter()).chain(getUser(123)).invoke();

使用事务

使用便利类:

import { ChainsWithKysely } from '@tool-chain/db/kysely';

function createUser(data: { name: string; email: string }) {
  return (db: Kysely<Database>) => {
    return db.insertInto('user').values(data).returningAll().executeTakeFirstOrThrow();
  };
}

function createProfile(userId: number) {
  return (db: Kysely<Database>) => {
    return db.insertInto('profile').values({ userId }).returningAll().executeTakeFirstOrThrow();
  };
}

const result = await new ChainsWithKysely<Database>()
  .transaction(db)
  .chain(createUser({ name: 'Alice', email: '[email protected]' }))
  .chain((results) => createProfile(results.r1.id))
  .invoke();

使用通用 Chains 类:

import { Chains } from '@tool-chain/db';
import { KyselyAdapter } from '@tool-chain/db/kysely';

const result = await new Chains()
  .transaction(db, new KyselyAdapter())
  .chain(createUser({ name: 'Alice', email: '[email protected]' }))
  .chain((results) => createProfile(results.r1.id))
  .invoke();

各 ORM 的使用示例

Kysely

import { Chains } from '@tool-chain/db';
import { KyselyAdapter } from '@tool-chain/db/kysely';
import { Kysely, PostgresDialect } from 'kysely';
import { Pool } from 'pg';

interface Database {
  user: {
    id: number;
    name: string;
    email: string;
  };
  post: {
    id: number;
    userId: number;
    title: string;
    content: string;
  };
}

// 初始化 Kysely
const db = new Kysely<Database>({
  dialect: new PostgresDialect({
    pool: new Pool({
      host: 'localhost',
      database: 'mydb',
    }),
  }),
});

const adapter = new KyselyAdapter<Database>();

// 定义 service 函数
function getUser(id: number) {
  return (db: Kysely<Database>) => {
    return db.selectFrom('user').where('id', '=', id).selectAll().executeTakeFirstOrThrow();
  };
}

function getUserPosts(userId: number) {
  return (db: Kysely<Database>) => {
    return db.selectFrom('post').where('userId', '=', userId).selectAll().execute();
  };
}

function createPost(data: { userId: number; title: string; content: string }) {
  return (db: Kysely<Database>) => {
    return db.insertInto('post').values(data).returningAll().executeTakeFirstOrThrow();
  };
}

// 非事务模式
const posts = await new Chains()
  .use(db, adapter)
  .chain(getUser(1))
  .chain((results) => getUserPosts(results.r1.id))
  .invoke();

// 事务模式
const newPost = await new Chains()
  .transaction(db, adapter)
  .chain(getUser(1))
  .chain((results) =>
    createPost({
      userId: results.r1.id,
      title: 'My First Post',
      content: 'Hello World!',
    }),
  )
  .invoke();

TypeORM

import { Chains } from '@tool-chain/db';
import { TypeORMAdapter } from '@tool-chain/db/typeorm';
import { DataSource } from 'typeorm';

import { Post } from './entities/Post';
import { User } from './entities/User';

// 初始化 TypeORM
const dataSource = new DataSource({
  type: 'postgres',
  host: 'localhost',
  port: 5432,
  username: 'user',
  password: 'password',
  database: 'mydb',
  entities: [User, Post],
  synchronize: true,
});

await dataSource.initialize();

const adapter = new TypeORMAdapter();

// 定义 service 函数
function getUser(id: number) {
  return (manager: typeof dataSource.manager) => {
    return manager.findOneOrFail(User, { where: { id } });
  };
}

function getUserPosts(userId: number) {
  return (manager: typeof dataSource.manager) => {
    return manager.find(Post, { where: { userId } });
  };
}

function createPost(data: { userId: number; title: string; content: string }) {
  return (manager: typeof dataSource.manager) => {
    const post = manager.create(Post, data);
    return manager.save(post);
  };
}

// 非事务模式
const posts = await new Chains()
  .use(dataSource, adapter)
  .chain(getUser(1))
  .chain((results) => getUserPosts(results.r1.id))
  .invoke();

// 事务模式
const newPost = await new Chains()
  .transaction(dataSource, adapter)
  .chain(getUser(1))
  .chain((results) =>
    createPost({
      userId: results.r1.id,
      title: 'My First Post',
      content: 'Hello World!',
    }),
  )
  .invoke();

Prisma

import { PrismaClient } from '@prisma/client';
import { Chains } from '@tool-chain/db';
import { PrismaAdapter } from '@tool-chain/db/prisma';

// 初始化 Prisma
const prisma = new PrismaClient();

const adapter = new PrismaAdapter();

// 定义 service 函数
function getUser(id: number) {
  return (prisma: PrismaClient) => {
    return prisma.user.findUniqueOrThrow({ where: { id } });
  };
}

function getUserPosts(userId: number) {
  return (prisma: PrismaClient) => {
    return prisma.post.findMany({ where: { userId } });
  };
}

function createPost(data: { userId: number; title: string; content: string }) {
  return (prisma: PrismaClient) => {
    return prisma.post.create({ data });
  };
}

// 非事务模式
const posts = await new Chains()
  .use(prisma, adapter)
  .chain(getUser(1))
  .chain((results) => getUserPosts(results.r1.id))
  .invoke();

// 事务模式
const newPost = await new Chains()
  .transaction(prisma, adapter)
  .chain(getUser(1))
  .chain((results) =>
    createPost({
      userId: results.r1.id,
      title: 'My First Post',
      content: 'Hello World!',
    }),
  )
  .invoke();

Drizzle ORM

import { Chains } from '@tool-chain/db';
import { DrizzleAdapter } from '@tool-chain/db/drizzle';
import Database from 'better-sqlite3';
import { eq } from 'drizzle-orm';
import { drizzle } from 'drizzle-orm/better-sqlite3';

import { posts, users } from './schema';

// 初始化 Drizzle
const sqlite = new Database('mydb.db');
const db = drizzle(sqlite);

const adapter = new DrizzleAdapter();

// 定义 service 函数
function getUser(id: number) {
  return (db: typeof db) => {
    return db.select().from(users).where(eq(users.id, id)).get();
  };
}

function getUserPosts(userId: number) {
  return (db: typeof db) => {
    return db.select().from(posts).where(eq(posts.userId, userId)).all();
  };
}

function createPost(data: { userId: number; title: string; content: string }) {
  return (db: typeof db) => {
    return db.insert(posts).values(data).returning().get();
  };
}

// 非事务模式
const postList = await new Chains()
  .use(db, adapter)
  .chain(getUser(1))
  .chain((results) => getUserPosts(results.r1!.id))
  .invoke();

// 事务模式
const newPost = await new Chains()
  .transaction(db, adapter)
  .chain(getUser(1))
  .chain((results) =>
    createPost({
      userId: results.r1!.id,
      title: 'My First Post',
      content: 'Hello World!',
    }),
  )
  .invoke();

API 参考

Chains 类

use(db, adapter?)

注入数据库实例(非事务模式)。

  • 参数:
    • db: 数据库实例
    • adapter: 数据库适配器(可选)
  • 返回: 带有数据库类型的新 Chains 实例

transaction(db, adapter)

启用事务模式。

  • 参数:
    • db: 数据库实例
    • adapter: 数据库适配器(必需)
  • 返回: 带有数据库类型的新 Chains 实例

chain(fn, options?)

向链中添加数据库操作。

函数模式:

  1. Service 函数模式(推荐)

    function getUser(id: number) {
      return (db: Database) => {
        // 你的数据库操作
      };
    }
    chains.chain(getUser(123));
  2. 结果访问器模式

    chains.chain((results) => getUser(results.r1.id));
  • 参数:
    • fn: 数据库操作函数
    • options: 链选项(retry、timeout、withoutThrow 等)
  • 返回: 添加了操作的新 Chains 实例

选项:

  • retry?: number - 重试次数
  • timeout?: number - 超时时间(毫秒)
  • withoutThrow?: boolean - 返回 { data?, error? } 而不是抛出异常

invoke()

执行整个链。

  • 返回: Promise,解析为最后一个操作的结果

便利类

这些类通过预配置适当的适配器为各个 ORM 提供了更简单的 API。

ChainsWithKysely<DB>

Kysely 的便利类,已预配置适配器。

import { ChainsWithKysely } from '@tool-chain/db/kysely';

const result = await new ChainsWithKysely<Database>().use(db).chain(getUser(123)).invoke();

ChainsWithTypeORM

TypeORM 的便利类,已预配置适配器。

import { ChainsWithTypeORM } from '@tool-chain/db/typeorm';

const result = await new ChainsWithTypeORM().use(dataSource).chain(getUser(123)).invoke();

ChainsWithPrisma

Prisma 的便利类,已预配置适配器。

import { ChainsWithPrisma } from '@tool-chain/db/prisma';

const result = await new ChainsWithPrisma().use(prisma).chain(getUser(123)).invoke();

ChainsWithDrizzle<TDb>

Drizzle ORM 的便利类,已预配置适配器。

import { ChainsWithDrizzle } from '@tool-chain/db/drizzle';

const result = await new ChainsWithDrizzle().use(db).chain(getUser(123)).invoke();

适配器

如果你更喜欢显式管理适配器,这些适配器可以与通用 Chains 类一起使用。

KyselyAdapter<DB>

Kysely ORM 的适配器。

import { KyselyAdapter } from '@tool-chain/db/kysely';

const adapter = new KyselyAdapter<Database>();

TypeORMAdapter

TypeORM 的适配器。

import { TypeORMAdapter } from '@tool-chain/db/typeorm';

const adapter = new TypeORMAdapter();

PrismaAdapter

Prisma ORM 的适配器。

import { PrismaAdapter } from '@tool-chain/db/prisma';

const adapter = new PrismaAdapter();

DrizzleAdapter

Drizzle ORM 的适配器。

import { DrizzleAdapter } from '@tool-chain/db/drizzle';

const adapter = new DrizzleAdapter();

错误处理

使用 withoutThrow 选项优雅地处理错误:

const result = await new Chains().use(db, adapter).chain(getUser(999), { withoutThrow: true }).invoke();

if (result.error) {
  console.error('用户未找到:', result.error);
} else {
  console.log('用户:', result.data);
}

高级特性

失败重试

const user = await new Chains().use(db, adapter).chain(getUser(123), { retry: 3 }).invoke();

超时控制

const user = await new Chains().use(db, adapter).chain(getUser(123), { timeout: 5000 }).invoke();

访问前一步的结果

const result = await new Chains()
  .use(db, adapter)
  .chain(getUser(1))
  .chain(getUserPosts(2))
  .chain((results) => {
    // results.r1 - 第一个操作的结果(user)
    // results.r2 - 第二个操作的结果(posts)
    return someOperation(results.r1, results.r2);
  })
  .invoke();

TypeScript 支持

本库使用 TypeScript 编写,提供优秀的类型推断:

const result = await new Chains()
  .use(db, adapter)
  .chain(getUser(1)) // 返回 User
  .chain((results) => {
    // results.r1 被推断为 User
    return getUserPosts(results.r1.id);
  })
  .invoke(); // 推断为 Post[]

许可证

MIT © HU SHUKANG

贡献

欢迎贡献!请随时提交 Pull Request。

支持

如果你有任何问题或遇到问题,请在 GitHub 上开启 issue。