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

@gulibs/tegg-prisma

v0.1.6

Published

Prisma plugin for Egg.js 4.x

Readme

@gulibs/tegg-prisma

适用于 Egg.js 4.x 的 Prisma 插件,提供完整的 TypeScript 支持。

系统要求

  • Node.js >= 22.18.0
  • Egg.js >= 4.1.0-beta.35
  • Prisma >= 6.0.0(完全支持 Prisma 7.x)

特性

  • 自动类型推导 - 零配置 TypeScript 支持!(v0.1.3+)
  • ✅ 完整的 Prisma schema IntelliSense
  • Driver Adapter 支持 - Prisma 7.x(v0.1.3+)
  • ✅ 单数据库和多数据库连接
  • ✅ 自动连接和优雅断开
  • ✅ 支持自定义 Prisma Client
  • ✅ Agent 进程支持(可选)
  • ✅ 通过 app.teggPrismactx.prisma 便捷访问
  • ✅ 查询性能监控
  • ✅ 健康检查 API
  • ✅ 带自动重试的事务
  • ✅ 增强的错误处理

安装

npm i @gulibs/tegg-prisma @prisma/client
npm i -D prisma

快速开始

1. 启用插件

// config/plugin.ts
import prismaPlugin from '@gulibs/tegg-prisma';

export default {
  ...prismaPlugin(),
};

2. 设置 Prisma

# 初始化 Prisma
npx prisma init

# 在 prisma/schema.prisma 中定义模型
# 然后生成 Prisma Client
npx prisma generate

3. 启动应用

npm run dev

就这样! TypeScript 会自动推导 PrismaClient 类型 - 无需任何配置。

4. 配置

// config/config.default.ts
export default {
  teggPrisma: {
    client: {
      // 可选:覆盖数据库 URL
      // DATABASE_URL 从 .env 或 schema.prisma 中配置

      // 可选:配置日志
      log: ['query', 'error', 'warn'],

      // 可选:错误格式
      errorFormat: 'colorless',
    }
  }
};

5. 使用

// app/controller/user.ts
import { Controller, HTTPController, HTTPMethod, HTTPContext } from 'egg';

@HTTPController()
export class UserController {
  @HTTPMethod({
    path: '/users',
    method: 'GET',
  })
  async list(@HTTPContext() ctx: Context) {
    // 通过 ctx.prisma 访问 Prisma Client
    const users = await ctx.prisma.user.findMany();
    ctx.body = users;
  }

  @HTTPMethod({
    path: '/users/:id',
    method: 'GET',
  })
  async show(@HTTPContext() ctx: Context) {
    const { id } = ctx.params;
    const user = await ctx.prisma.user.findUnique({
      where: { id },
    });
    ctx.body = user;
  }

  @HTTPMethod({
    path: '/users',
    method: 'POST',
  })
  async create(@HTTPContext() ctx: Context) {
    const user = await ctx.prisma.user.create({
      data: ctx.request.body,
    });
    ctx.body = user;
  }
}

类型安全 - 自动类型推导 🎯

v0.1.3 新特性:零配置类型推导!

插件现在自动推导 PrismaClient 类型 - 无需手动类型断言或配置!

// ✅ 直接使用 - IntelliSense 自动生效!
const users = await ctx.prisma.user.findMany({
  include: { posts: true }  // ✅ 自动补全生效!
});

const user = await ctx.prisma.user.create({
  data: {
    name: 'John',
    email: '[email protected]',
    posts: {
      create: { title: '我的第一篇文章' }
    }
  }
});

工作原理

  • 插件使用 TypeScript 条件类型自动从 @prisma/client 导入和推导 PrismaClient 类型
  • 当你运行 npx prisma generate 时,schema 模型会被完全类型化
  • 插件的 EggPrisma 类型自动解析为你生成的 PrismaClient 实例类型
  • 零配置 - 只需安装和使用!

结果:在项目的任何地方都有完美的 IntelliSense!


数据库连接方式

Prisma 7.x 支持两种数据库连接配置方式:

方式 1:环境变量(推荐用于大多数情况)

适用于:单数据库,简单配置

.env 文件中配置 DATABASE_URL

# .env
DATABASE_URL="postgresql://user:pass@localhost:5432/mydb?connection_limit=10&pool_timeout=30"
// config/config.default.ts
export default {
  teggPrisma: {
    client: {
      // DATABASE_URL 自动从环境变量读取
      log: ['query', 'error', 'warn'],
    }
  }
};

优点:简单,符合 12-factor app 原则,兼容 Prisma CLI

方式 2:Driver Adapter(Prisma 7.x 新增)

适用于:动态数据库配置,多数据库,运行时连接变更

安装 adapter:

# PostgreSQL
npm i @prisma/adapter-pg pg

# MySQL
npm i @prisma/adapter-mysql2 mysql2

# 其他 adapter:@prisma/adapter-planetscale, @prisma/adapter-neon 等

在配置中使用 adapter:

// config/config.default.ts
import { PrismaPg } from '@prisma/adapter-pg';

// 创建带有 connectionString 的 adapter
const adapter = new PrismaPg({
  connectionString: process.env.DATABASE_URL
});

export default {
  teggPrisma: {
    client: {
      adapter,  // 将 adapter 传递给插件
      log: ['query', 'error', 'warn'],
    }
  }
};

优点

  • ✅ 运行时配置(可以动态更改连接)
  • ✅ 支持边缘运行时(Cloudflare Workers、Vercel Edge 等)
  • ✅ 高级连接池控制
  • ✅ 多数据库支持不同驱动

参考Prisma Driver Adapters 文档


配置

单数据库

export default {
  teggPrisma: {
    client: {
      // DATABASE_URL 从 .env 或 schema.prisma 中配置
      log: ['query', 'error', 'warn'],

      // 可选:事务选项
      transactionOptions: {
        maxWait: 5000,
        timeout: 10000,
        isolationLevel: 'ReadCommitted',
      },

      // 可选:查询监控
      queryMonitor: {
        enabled: true,
        slowQueryThreshold: 1000,  // 1秒
        logAllQueries: process.env.NODE_ENV === 'development',
      },
    }
  }
};

多数据库

export default {
  teggPrisma: {
    clients: {
      db1: {
        // 使用自定义 PrismaClient(从 schema-db1.prisma 生成)
        log: ['error'],
      },
      db2: {
        // 使用自定义 PrismaClient(从 schema-db2.prisma 生成)
        log: ['error'],
      },
    }
  }
};

访问多个数据库:

// 获取特定客户端
const db1 = app.teggPrisma.get('db1');
const users = await db1.user.findMany();

// 或通过 ctx
const db2 = ctx.prisma.get('db2');
const posts = await db2.post.findMany();

自定义 Prisma Client

如果有自定义生成的 Prisma Client(例如在 monorepo 中):

import { PrismaClient as CustomPrismaClient } from './prisma/client';

export default {
  teggPrisma: {
    client: {
      PrismaClient: CustomPrismaClient,
      // DATABASE_URL 从 .env 或 schema.prisma 中配置
    }
  }
};

Agent 支持

在 agent 进程中启用 Prisma(用于定时任务等):

export default {
  teggPrisma: {
    agent: true, // 在 agent 中启用
    client: {
      // DATABASE_URL 从 .env 或 schema.prisma 中配置
    }
  }
};

API

app.teggPrisma

在应用中访问 Prisma Client:

// 单客户端
const users = await app.teggPrisma.user.findMany();

// 多客户端
const db1 = app.teggPrisma.get('db1');
const users = await db1.user.findMany();

// 或使用别名
const db2 = app.teggPrismas.get('db2');

ctx.prisma

在上下文中访问 Prisma Client:

async show(ctx: Context) {
  const user = await ctx.prisma.user.findUnique({
    where: { id: ctx.params.id },
  });
  ctx.body = user;
}

CLIENT_NAME_SYMBOL

获取客户端名称:

import { CLIENT_NAME_SYMBOL } from '@gulibs/tegg-prisma';

const clientName = Reflect.get(ctx.prisma, CLIENT_NAME_SYMBOL);
console.log(clientName); // 'default' 或客户端名称

健康检查 API

检查数据库连接健康状态:

// 单客户端
const healthy = await app.checkPrismaHealth();
if (!healthy) {
  console.error('数据库连接不健康');
}

// 多客户端
const db1Healthy = await app.checkPrismaHealth('db1');
const db2Healthy = await app.checkPrismaHealth('db2');

// 获取所有客户端健康状态
const status = await app.getPrismaHealthStatus();
console.log(status); // { default: true, db1: true, db2: false }

健康检查端点示例:

@HTTPMethod({ path: '/health', method: 'GET' })
async healthCheck(@HTTPContext() ctx: Context) {
  const dbStatus = await ctx.app.getPrismaHealthStatus();
  const allHealthy = Object.values(dbStatus).every(v => v);

  ctx.body = {
    status: allHealthy ? 'ok' : 'error',
    database: dbStatus,
    timestamp: new Date().toISOString(),
  };

  ctx.status = allHealthy ? 200 : 503;
}

高级功能

1. 查询性能监控

使用 Prisma Client Extensions 监控慢查询并追踪查询性能。

要求:Prisma Client 4.16.0 或更高版本

工作原理:插件使用 Prisma 的 $extends API 拦截和监控所有数据库查询,不会影响性能。

// config/config.default.ts
export default {
  teggPrisma: {
    client: {
      // DATABASE_URL 从 .env 或 schema.prisma 中配置
      queryMonitor: {
        enabled: true,
        slowQueryThreshold: 1000,  // 查询超过1秒发出警告
        logAllQueries: process.env.NODE_ENV === 'development',
        onSlowQuery: (info) => {
          // 发送到监控服务
          console.warn('检测到慢查询:', {
            model: info.model,
            action: info.action,
            duration: info.duration,
            timestamp: info.timestamp,
          });
        },
        onQuery: (info) => {
          // 在开发环境追踪所有查询
          console.log(`查询: ${info.model}.${info.action} - ${info.duration}ms`);
        },
      },
    }
  }
};

注意:查询监控使用 Prisma 4.16.0 引入的 Client Extensions ($extends),它替代了已废弃的 $use middleware API。

2. 连接池配置

重要:在 Prisma 7.x 中,连接池设置必须在 DATABASE_URL 连接字符串中配置:

# .env - 在连接字符串中配置池设置
DATABASE_URL="postgresql://user:pass@host:5432/db?connection_limit=10&pool_timeout=30"
export default {
  teggPrisma: {
    client: {
      // DATABASE_URL 从 .env 或 schema.prisma 中配置  // 池设置从 URL 读取
      transactionOptions: {
        maxWait: 5000,        // 事务开始的最大等待时间
        timeout: 10000,       // 事务执行的最大时间
        isolationLevel: 'ReadCommitted',
      },
    }
  }
};

常用连接池参数

  • connection_limit - 最大连接数(PostgreSQL/MySQL)
  • pool_timeout - 超时时间(秒)
  • connect_timeout - 连接超时

参考:https://www.prisma.io/docs/guides/database/connection-pooling

3. 带自动重试的事务

使用事务辅助函数,自动重试逻辑:

import { withTransaction } from '@gulibs/tegg-prisma';

async transfer(@HTTPContext() ctx: Context) {
  const result = await withTransaction(
    ctx.prisma,
    async (tx) => {
      const from = await tx.account.update({
        where: { id: ctx.request.body.fromId },
        data: { balance: { decrement: ctx.request.body.amount } },
      });

      if (from.balance < 0) {
        throw new Error('余额不足');
      }

      const to = await tx.account.update({
        where: { id: ctx.request.body.toId },
        data: { balance: { increment: ctx.request.body.amount } },
      });

      return { from, to };
    },
    {
      maxRetries: 3,
      timeout: 10000,
      isolationLevel: 'Serializable',
    }
  );

  ctx.body = result;
}

4. 增强的错误处理

使用内置的错误处理工具:

import { isPrismaError, getPrismaErrorMessage, PrismaErrorCodes } from '@gulibs/tegg-prisma';

async create(@HTTPContext() ctx: Context) {
  try {
    const user = await ctx.prisma.user.create({
      data: ctx.request.body,
    });
    ctx.body = user;
  } catch (error) {
    if (isPrismaError(error)) {
      if (error.code === PrismaErrorCodes.UNIQUE_CONSTRAINT) {
        ctx.status = 400;
        ctx.body = {
          error: '邮箱已存在',
          message: getPrismaErrorMessage(error),
        };
        return;
      }

      if (error.code === PrismaErrorCodes.FOREIGN_KEY_CONSTRAINT) {
        ctx.status = 400;
        ctx.body = { error: '引用的记录不存在' };
        return;
      }
    }
    throw error;
  }
}

5. 原生 SQL 查询

需要时执行原生 SQL:

// 使用 app
const users = await app.prismaRawQuery`
  SELECT * FROM "User" WHERE age > ${18}
`;

// 使用 ctx
const stats = await ctx.prisma.$queryRaw`
  SELECT COUNT(*) as total, AVG(age) as avgAge FROM "User"
`;

6. Prisma 指标

获取 Prisma Client 指标(如果启用了指标):

const metrics = await app.getPrismaMetrics();
if (metrics) {
  console.log('活跃连接数:', metrics.connections?.active);
  console.log('查询持续时间:', metrics.queries?.duration);
}

最佳实践

1. 事务支持

async transfer(ctx: Context) {
  const result = await ctx.prisma.$transaction(async (prisma) => {
    await prisma.account.update({
      where: { id: 1 },
      data: { balance: { decrement: 100 } },
    });

    await prisma.account.update({
      where: { id: 2 },
      data: { balance: { increment: 100 } },
    });

    return { success: true };
  });

  ctx.body = result;
}

2. 查询优化

// ✅ 使用 select 获取特定字段
const users = await ctx.prisma.user.findMany({
  select: { id: true, name: true, email: true },
});

// ❌ 避免获取不必要的数据
const users = await ctx.prisma.user.findMany(); // 获取所有字段

// ✅ 使用分页
const users = await ctx.prisma.user.findMany({
  take: 10,
  skip: (page - 1) * 10,
  orderBy: { createdAt: 'desc' },
});

// ✅ 监控慢查询
// 在配置中启用 queryMonitor 可自动检测 N+1 查询问题

3. 生产环境部署

// config/config.prod.ts
export default {
  teggPrisma: {
    client: {
      // DATABASE_URL 从 .env 或 schema.prisma 中配置  // 在 URL 中包含池设置
      log: ['error'],  // 生产环境只记录错误
      queryMonitor: {
        enabled: true,
        slowQueryThreshold: 2000,  // 生产环境更高的阈值
        onSlowQuery: (info) => {
          // 发送到监控服务(如 Sentry、DataDog)
          monitoring.trackSlowQuery({
            model: info.model,
            action: info.action,
            duration: info.duration,
          });
        },
      },
      transactionOptions: {
        maxWait: 10000,
        timeout: 30000,
        isolationLevel: 'ReadCommitted',
      },
    }
  }
};

配置选项参考

完整配置

export default {
  teggPrisma: {
    // 在 app 进程中启用(默认: true)
    app: true,

    // 在 agent 进程中启用(默认: false)
    agent: false,

    // 所有客户端的默认选项
    default: {
      log: ['error', 'warn'],
    },

    // 单客户端配置
    client: {
      // 数据库 URL
      // DATABASE_URL 从 .env 或 schema.prisma 中配置

      // 日志配置
      log: ['query', 'error', 'warn'],
      // 或使用 emit 模式
      log: [
        { emit: 'event', level: 'query' },
        { emit: 'stdout', level: 'error' },
      ],

      // 错误格式
      errorFormat: 'colorless', // 'pretty' | 'colorless' | 'minimal'

      // Driver Adapter(Prisma 7.x)
      // 用于动态数据库配置
      adapter: myAdapter, // driver adapter 实例
      // 示例:
      // import { PrismaPg } from '@prisma/adapter-pg';
      // const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL });

      // 连接池 - 请在 DATABASE_URL 中配置:
      // postgresql://...?connection_limit=10&pool_timeout=30

      // 事务选项
      transactionOptions: {
        maxWait: 5000,
        timeout: 10000,
        isolationLevel: 'ReadCommitted',
      },

      // 查询监控
      queryMonitor: {
        enabled: true,
        slowQueryThreshold: 1000,
        logAllQueries: false,
        onSlowQuery: (info) => {
          console.warn('慢查询:', info);
        },
        onQuery: (info) => {
          console.log('查询:', info);
        },
      },

      // 自定义 Prisma Client
      PrismaClient: CustomPrismaClient,
    },

    // 或多客户端配置
    clients: {
      db1: {
        // 使用自定义 PrismaClient(从 schema-db1.prisma 生成)
        // ... 与单客户端相同的选项
      },
      db2: {
        // 使用自定义 PrismaClient(从 schema-db2.prisma 生成)
        // ... 与单客户端相同的选项
      },
    },
  }
};

故障排除

问题:"PrismaClient is unable to run in this browser environment"

确保你没有为浏览器打包 Prisma Client。Prisma 只能在 Node.js 中运行。

问题:"@prisma/client did not initialize yet"

安装 @prisma/client 后运行 npx prisma generate

问题:数据库连接问题

检查 .env 文件中的 DATABASE_URL

DATABASE_URL="postgresql://user:password@localhost:5432/mydb?connection_limit=10"

问题:慢查询

启用查询监控以检测慢查询:

queryMonitor: {
  enabled: true,
  slowQueryThreshold: 1000,
  logAllQueries: process.env.NODE_ENV === 'development',
}

问题:连接池耗尽

在 DATABASE_URL 中增加连接限制:

# 在连接字符串中增加连接限制
DATABASE_URL="postgresql://...?connection_limit=20&pool_timeout=60"

API 参考

导出的工具

// 错误处理
import {
  isPrismaError,
  getPrismaErrorMessage,
  PrismaErrorCodes,
  getUniqueConstraintField,
} from '@gulibs/tegg-prisma';

// 事务工具
import { withTransaction } from '@gulibs/tegg-prisma';
import type { TransactionOptions } from '@gulibs/tegg-prisma';

// 查询监控类型
import type { QueryMonitorOptions, QueryInfo } from '@gulibs/tegg-prisma';

// 配置类型
import type {
  EggPrismaConfig,
  EggPrismaClientOption
} from '@gulibs/tegg-prisma';

// 客户端名称 symbol
import { CLIENT_NAME_SYMBOL } from '@gulibs/tegg-prisma';

Application 方法

// 健康检查
await app.checkPrismaHealth(clientName?: string): Promise<boolean>
await app.getPrismaHealthStatus(): Promise<Record<string, boolean>>

// 原生查询
await app.prismaRawQuery<T>(sql: TemplateStringsArray, ...values: any[]): Promise<T[]>

// 指标
await app.getPrismaMetrics(clientName?: string): Promise<any>

错误码

PrismaErrorCodes.UNIQUE_CONSTRAINT       // P2002
PrismaErrorCodes.FOREIGN_KEY_CONSTRAINT  // P2003
PrismaErrorCodes.RECORD_NOT_FOUND        // P2025
PrismaErrorCodes.RELATION_VIOLATION      // P2014
PrismaErrorCodes.DATABASE_UNREACHABLE    // P1001
PrismaErrorCodes.DATABASE_TIMEOUT        // P1008
PrismaErrorCodes.SERVER_CLOSED           // P1017

迁移指南

从 egg-sequelize 迁移

主要区别:

  1. Schema 定义:Prisma 使用 schema.prisma,而非模型文件
  2. 代码生成:修改 schema 后运行 npx prisma generate
  3. 类型安全:Prisma 提供开箱即用的更好类型推断
  4. API:Prisma 有更现代化的 fluent API
  5. 健康检查:内置健康检查 API
  6. 监控:内置查询性能监控

示例迁移:

// Sequelize
const users = await ctx.model.User.findAll({
  where: { age: { $gt: 18 } },
  include: [{ model: ctx.model.Post }],
});

// Prisma
const users = await ctx.prisma.user.findMany({
  where: { age: { gt: 18 } },
  include: { posts: true },
});

迁移到 Prisma 的好处:

  • ✅ 更好的类型安全和自动补全
  • ✅ 现代化查询 API
  • ✅ 内置迁移工具
  • ✅ 查询性能监控
  • ✅ 健康检查 API
  • ✅ 事务自动重试
  • ✅ 更好的错误处理

许可证

MIT

文档

链接

更新日志

查看 CHANGELOG.md 了解版本历史和迁移指南。