Cursor
Cursor 是一款由 AI 驱动的代码编辑器,旨在通过自动化重复性编码任务来提高生产力。当与 Prisma(一个用于数据库工作流的强大且类型安全的工具包)结合使用时,它成为管理和优化数据库 Schema、查询和数据填充的强大解决方案。
本指南提供了将 Prisma 与 Cursor 有效结合使用的详细说明,以便
- 使用 `.cursorrules` 定义项目特有的最佳实践。
- 使用 Cursor 的上下文感知能力。
- 生成根据您的数据库定制的 Schema、查询和填充数据。
虽然本指南侧重于 Cursor,但这些模式应适用于任何 AI 编辑器。如果您希望我们为您喜欢的工具创建指南,请在 X 上告知我们!
Prisma MCP 服务器
Prisma 提供其自己的 Model Context Protocol (MCP) 服务器,让您可以管理 Prisma Postgres 数据库,建模数据库 Schema 并通过迁移进行聊天。在此处了解如何将其添加到 Cursor。
使用 `.cursorrules` 定义项目特有规则
Cursor 中的 `.cursorrules` 文件允许您实施针对您的 Prisma 项目量身定制的最佳实践和开发标准。通过定义清晰一致的规则,您可以确保 Cursor 生成干净、可维护且项目特有的代码,并且只需最少的手动调整。
要实施这些规则,请在项目根目录中创建一个 `.cursorrules` 文件。以下是一个示例配置
示例 `.cursorrules` 文件
You are a senior TypeScript/JavaScript programmer with expertise in Prisma, clean code principles, and modern backend development.
Generate code, corrections, and refactorings that comply with the following guidelines:
TypeScript General Guidelines
Basic Principles
- Use English for all code and documentation.
- Always declare explicit types for variables and functions.
- Avoid using "any".
- Create precise, descriptive types.
- Use JSDoc to document public classes and methods.
- Maintain a single export per file.
- Write self-documenting, intention-revealing code.
Nomenclature
- Use PascalCase for classes and interfaces.
- Use camelCase for variables, functions, methods.
- Use kebab-case for file and directory names.
- Use UPPERCASE for environment variables and constants.
- Start function names with a verb.
- Use verb-based names for boolean variables:
- isLoading, hasError, canDelete
- Use complete words, avoiding unnecessary abbreviations.
- Exceptions: standard abbreviations like API, URL
- Accepted short forms:
- i, j for loop indices
- err for errors
- ctx for contexts
Functions
- Write concise, single-purpose functions.
- Aim for less than 20 lines of code.
- Name functions descriptively with a verb.
- Minimize function complexity:
- Use early returns.
- Extract complex logic to utility functions.
- Leverage functional programming techniques:
- Prefer map, filter, reduce.
- Use arrow functions for simple operations.
- Use named functions for complex logic.
- Use object parameters for multiple arguments.
- Maintain a single level of abstraction.
Data Handling
- Encapsulate data in composite types.
- Prefer immutability.
- Use readonly for unchanging data.
- Use as const for literal values.
- Validate data at the boundaries.
Error Handling
- Use specific, descriptive error types.
- Provide context in error messages.
- Use global error handling where appropriate.
- Log errors with sufficient context.
Prisma-Specific Guidelines
Schema Design
- Use meaningful, domain-driven model names.
- Leverage Prisma schema features:
- Use @id for primary keys.
- Use @unique for natural unique identifiers.
- Utilize @relation for explicit relationship definitions.
- Keep schemas normalized and DRY.
- Use meaningful field names and types.
- Implement soft delete with deletedAt timestamp.
- Use Prisma's native type decorators.
Prisma Client Usage
- Always use type-safe Prisma client operations.
- Prefer transactions for complex, multi-step operations.
- Use Prisma middleware for cross-cutting concerns:
- Logging
- Soft delete
- Auditing
- Handle optional relations explicitly.
- Use Prisma's filtering and pagination capabilities.
Database Migrations
- Create migrations for schema changes.
- Use descriptive migration names.
- Review migrations before applying.
- Never modify existing migrations.
- Keep migrations idempotent.
Error Handling with Prisma
- Catch and handle Prisma-specific errors:
- PrismaClientKnownRequestError
- PrismaClientUnknownRequestError
- PrismaClientValidationError
- Provide user-friendly error messages.
- Log detailed error information for debugging.
Testing Prisma Code
- Use in-memory database for unit tests.
- Mock Prisma client for isolated testing.
- Test different scenarios:
- Successful operations
- Error cases
- Edge conditions
- Use factory methods for test data generation.
- Implement integration tests with actual database.
Performance Considerations
- Use select and include judiciously.
- Avoid N+1 query problems.
- Use findMany with take and skip for pagination.
- Leverage Prisma's distinct for unique results.
- Profile and optimize database queries.
Security Best Practices
- Never expose raw Prisma client in APIs.
- Use input validation before database operations.
- Implement row-level security.
- Sanitize and validate all user inputs.
- Use Prisma's built-in protections against SQL injection.
Coding Style
- Keep Prisma-related code in dedicated repositories/modules.
- Separate data access logic from business logic.
- Create repository patterns for complex queries.
- Use dependency injection for Prisma services.
Code Quality
- Follow SOLID principles.
- Prefer composition over inheritance.
- Write clean, readable, and maintainable code.
- Continuously refactor and improve code structure.
Development Workflow
- Use version control (Git).
- Implement comprehensive test coverage.
- Use continuous integration.
- Perform regular code reviews.
- Keep dependencies up to date.
此文件确保一致且可维护的代码生成,减少手动干预,同时提高项目质量。
使用 Cursor 的上下文感知能力
Cursor 的上下文感知能力允许您添加特定的网站、文件、文件夹或文档,以增强其对您项目的理解。通过将您的 `schema.prisma` 文件添加为上下文,您可以使 Cursor 根据您的数据库 Schema 生成更准确的查询、测试和填充数据。
将 Prisma 文档 `llm.txt` 文件添加为 `@Docs` 上下文
为了提高 Cursor 对您项目中 Prisma 相关建议的理解,请将 `/llms.txt` markdown 文件包含为上下文。此文件提供了简洁的概述、有用的指导以及指向详细 Prisma 文档的链接——所有这些都针对 LLM 处理进行了优化。只需导航到 url 并将其作为 `@Docs` 资源添加到您的 Cursor 配置中即可。
添加额外的 Prisma 文档
Cursor 已包含 Prisma 文档中的内置上下文,因此您无需添加任何内容即可使用我们的文档!您可以在此处查看 Cursor 使用的现有资源。
要及时了解最新更改或纳入额外的上下文,请将这些资源添加为 `@Docs` 上下文
- Prisma 更新日志,用于了解更新和新功能。
- Prisma 博客,用于获取实用指南和最佳实践。
要了解如何添加和管理文档上下文,请访问 Cursor 文档。
将 Schema 用作上下文
在使用 `@Files` 语法请求查询、测试或填充脚本之前,将您的 `schema.prisma` 文件(或整个代码库)添加为上下文。这使得 Cursor 能够生成精确的、由 Schema 驱动的输出,例如查询、测试和填充数据。例如,在 Cursor Chat 中,您可以键入 `@Files`,然后添加您的 `schema.prisma` 文件来包含您的 Schema。
生成 Prisma Schema
Cursor 可以从高级描述生成 Prisma Schema,使您能够快速为数据库 Schema 建立坚实的基础。通过提供清晰详细的提示,Cursor 会创建根据您的要求量身定制的 Prisma Schema。无论您需要通用的基础 Schema 还是针对详细用例的高度特定的 Schema,Cursor 都能精确生成。以下是一个示例提示及其相应结果
如果您运行以下提示,可能会收到不同的输出,因为 LLM 生成的结果具有非确定性。
- 生成 Prisma Schema 的提示
- 结果
"Create a Prisma schema for a SaaS app using PostgreSQL as a provider with `User`, `Organization`, and `Subscription` models, ensuring all models include `createdAt` and `updatedAt` DateTime fields with defaults, a soft-delete `deletedAt` field, and proper relationships between entities."
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String
password String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime?
organization Organization @relation(fields: [organizationId], references: [id])
organizationId Int
role UserRole @default(MEMBER)
}
model Organization {
id Int @id @default(autoincrement())
name String
slug String @unique
subscription Subscription?
users User[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime?
}
model Subscription {
id Int @id @default(autoincrement())
organization Organization @relation(fields: [organizationId], references: [id])
organizationId Int @unique
plan SubscriptionPlan
status SubscriptionStatus @default(ACTIVE)
startDate DateTime
endDate DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime?
}
enum UserRole {
ADMIN
MEMBER
}
enum SubscriptionPlan {
FREE
BASIC
PREMIUM
ENTERPRISE
}
enum SubscriptionStatus {
ACTIVE
CANCELED
EXPIRED
PAST_DUE
}
生成 Prisma 查询
Cursor 可以帮助您创建根据您的 Prisma Schema 定制的查询,无论是用于基本数据检索还是复杂、优化的操作。为了获得最佳结果,请着重编写清晰、具体的提示,定义您的要求,例如要包含的字段、要应用的条件以及要遍历的关系。这确保了 Cursor 生成准确、高性能且类型安全的查询。以下是一个示例提示及其结果查询
- 生成数据库查询的提示
- 结果
"Generate a query to retrieve all User records associated with an Organization that has an `active` Subscription, while excluding any records where the deletedAt field is set."
const activeUsers = await prisma.user.findMany({
where: {
deletedAt: null,
organization: {
deletedAt: null,
subscription: {
deletedAt: null,
status: 'ACTIVE'
}
}
},
include: {
organization: {
include: {
subscription: true
}
}
},
orderBy: {
createdAt: 'desc'
},
skip: 0,
take: 10
});
使用 Cursor 创建填充文件
编写填充脚本可能是一个繁琐的过程,但 Cursor 通过快速生成结构化且有组织的填充代码来简化它。通过提供清晰的指令,您可以引导 Cursor 创建脚本,用真实数据填充您的数据库,包括处理 Schema 中定义的关系和复杂结构。以下是一个示例提示及其结果填充脚本
- 填充数据库的提示
- 结果
"Generate code to populate the Prisma schema with realistic data for the User, Organization, and Subscription models, ensuring all necessary fields are included."
import {
PrismaClient,
UserRole,
SubscriptionPlan,
SubscriptionStatus,
} from "@prisma/client";
const prisma = new PrismaClient();
async function main() {
// Clear existing data
await prisma.user.deleteMany();
await prisma.subscription.deleteMany();
await prisma.organization.deleteMany();
const organizations = [
{
name: "Tech Innovators",
slug: "tech-innovators",
subscription: {
plan: SubscriptionPlan.ENTERPRISE,
status: SubscriptionStatus.ACTIVE,
startDate: new Date("2024-01-01"),
},
users: [
{
name: "Emma Thompson",
email: "emma@techinnovators.com",
role: UserRole.ADMIN,
password: "password123",
},
{
name: "Michael Chen",
email: "michael@techinnovators.com",
role: UserRole.MEMBER,
password: "password123",
},
],
},
{
name: "Digital Solutions",
slug: "digital-solutions",
subscription: {
plan: SubscriptionPlan.PREMIUM,
status: SubscriptionStatus.ACTIVE,
startDate: new Date("2024-01-15"),
},
users: [
{
name: "Sarah Wilson",
email: "sarah@digitalsolutions.com",
role: UserRole.ADMIN,
password: "password123",
},
{
name: "James Miller",
email: "james@digitalsolutions.com",
role: UserRole.MEMBER,
password: "password123",
},
],
},
{
name: "Cloud Systems",
slug: "cloud-systems",
subscription: {
plan: SubscriptionPlan.BASIC,
status: SubscriptionStatus.ACTIVE,
startDate: new Date("2024-02-01"),
},
users: [
{
name: "David Garcia",
email: "david@cloudsystems.com",
role: UserRole.ADMIN,
password: "password123",
},
{
name: "Lisa Wang",
email: "lisa@cloudsystems.com",
role: UserRole.MEMBER,
password: "password123",
},
],
},
{
name: "Data Analytics Co",
slug: "data-analytics",
subscription: {
plan: SubscriptionPlan.PREMIUM,
status: SubscriptionStatus.ACTIVE,
startDate: new Date("2024-01-10"),
},
users: [
{
name: "Alex Johnson",
email: "alex@dataanalytics.com",
role: UserRole.ADMIN,
password: "password123",
},
{
name: "Rachel Kim",
email: "rachel@dataanalytics.com",
role: UserRole.MEMBER,
password: "password123",
},
],
},
{
name: "Smart Solutions",
slug: "smart-solutions",
subscription: {
plan: SubscriptionPlan.FREE,
status: SubscriptionStatus.ACTIVE,
startDate: new Date("2024-02-15"),
},
users: [
{
name: "Daniel Brown",
email: "daniel@smartsolutions.com",
role: UserRole.ADMIN,
password: "password123",
},
{
name: "Maria Rodriguez",
email: "maria@smartsolutions.com",
role: UserRole.MEMBER,
password: "password123",
},
],
},
];
for (const org of organizations) {
const createdOrg = await prisma.organization.create({
data: {
name: org.name,
slug: org.slug,
subscription: {
create: {
plan: org.subscription.plan,
status: org.subscription.status,
startDate: org.subscription.startDate,
},
},
},
});
for (const user of org.users) {
await prisma.user.create({
data: {
name: user.name,
email: user.email,
password: user.password,
role: user.role,
organizationId: createdOrg.id,
},
});
}
}
console.log("Seed data created successfully");
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});
其他资源
总而言之,将 Cursor 与 Prisma 结合使用可以简化您的工作流程,从生成 Schema 和查询到编写填充脚本。通过遵循本指南,您可以节省时间,减少错误,并专注于构建您的应用程序。
在其官方文档中了解更多关于 Cursor 的信息。
与 Prisma 保持联系
通过与 我们活跃的社区联系,继续您的 Prisma 之旅。保持知情,参与其中,并与其他开发者协作
- 在 X 上关注我们 获取公告、直播活动和实用技巧。
- 加入我们的 Discord 提出问题,与社区交流,并通过对话获得积极支持。
- 在 YouTube 上订阅 获取教程、演示和直播。
- 在 GitHub 上互动 通过点赞仓库、报告问题或为问题做贡献。