Windsurf
Windsurf Editor 是一个 AI 驱动的代码编辑器,旨在通过自动化重复性编码任务来提高生产力。当与 Prisma(一个用于数据库工作流的强大且类型安全的工具包)结合使用时,它成为管理和优化数据库模式、查询和数据填充的强大解决方案。
本指南提供了将 Prisma 与 Windsurf 有效结合使用的详细说明,以实现以下目的:
- 使用
.windsurfrules
定义项目特定的最佳实践。 - 使用 Windsurf 的上下文感知能力。
- 生成针对你的数据库定制的模式、查询和种子数据。
虽然本指南侧重于 Windsurf,但这些模式应适用于任何 AI 编辑器。在 X 上告诉我们 如果你希望我们为你的首选工具创建指南!
Prisma MCP 服务器
Prisma 提供了自己的 模型上下文协议(MCP) 服务器,让你能够管理 Prisma Postgres 数据库、建模数据库模式,甚至通过迁移进行聊天。
通过 Windsurf 插件添加 Prisma MCP 服务器
你可以通过 Windsurf MCP 插件商店 添加 Prisma MCP 服务器。
新的 MCP 插件可以从 Plugin Store 中添加,你可以通过点击 Cascade 面板右上角菜单中的 Plugins 图标,或者从 Windsurf Settings > Cascade > Plugins 部分访问。只需在 Plugin Store 中搜索 Prisma 并安装 Prisma
插件。
你也可以手动添加 Prisma MCP 服务器。在此处了解如何手动将 MCP 服务器添加到 Windsurf:这里。
使用 .windsurfrules
定义项目特定规则
Windsurf 中的 .windsurfrules
文件 允许你强制执行针对你的 Prisma 项目量身定制的最佳实践和开发标准。通过定义清晰一致的规则,你可以确保 Windsurf 生成的代码整洁、可维护且符合项目特定要求,并最大程度地减少手动调整。
要实施这些规则,请在项目根目录中创建一个 .windsurfrules
文件。下面是一个示例配置:
示例 .windsurfrules
文件
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.
此文件确保代码生成一致且可维护,减少人工干预,同时提高项目质量。
使用 Windsurf 的上下文感知能力
Windsurf 的 上下文感知 功能让你能够利用项目文件和外部资源来增强 AI 对项目的理解。通过在上下文中包含你的 Prisma 模式和相关文档,你可以让 Windsurf 基于你的数据库模式生成更准确的查询、测试和种子数据。
包含其他 Prisma 资源
Windsurf 内置了对常见库的了解,但你可以通过明确引用外部 Prisma 资源来进一步增强其感知能力。这对于保持最新或为代码生成和最佳实践提供权威上下文特别有用。
例如,你可以引用:
在你的请求中引用资源:
在请求代码、解释或评论时,包含相关 Prisma 资源的链接,并指定应将其用作参考。
Generate a migration script using best practices from prisma.io/docs.
请求持续感知:
要求 Windsurf 始终考虑你的项目中所有与 Prisma 相关的工作的特定资源。
Always use the Prisma Changelog at prisma.io/changelog for Prisma updates in this project.
请求定期更新:
如果你希望 Windsurf 检查更新或新功能,请明确请求。
Before suggesting Prisma code, check the latest changes from prisma.io/changelog.
通过在请求或项目指南中直接引用外部资源,你可以确保 Windsurf 利用最新和最相关的 Prisma 信息。
将模式用作上下文
开箱即用,Windsurf 自动将当前文件、其他打开的文件以及代码库中已索引的部分视为上下文。为确保 Cascade 充分利用你的 Prisma 模式,请将 schema.prisma
文件保持打开或固定在编辑器中。
生成 Prisma 模式
Windsurf 可以从高级描述生成 Prisma 模式,使你能够快速为数据库模式奠定坚实的基础。通过提供清晰详细的提示,Windsurf 可以根据你的要求创建 Prisma 模式。无论你需要一个通用的基础模式,还是一个针对详细用例高度特定的模式,Windsurf 都能精确交付。以下是一个示例提示及其相应的结果:
大型语言模型每次可能会产生不同的结果,即使使用相同的提示。
- 生成 Prisma 模式的提示
- 结果
"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 查询
Windsurf 可以帮助你创建针对 Prisma 模式量身定制的查询,无论是用于基本数据检索还是复杂的优化操作。为了获得最佳结果,请专注于编写清晰、具体的提示,定义你的要求,例如要包含的字段、要应用的条件和要遍历的关系。这可确保 Windsurf 生成准确、高效且类型安全的查询。以下是一个示例提示及其生成的查询:
- 生成数据库查询的提示
- 结果
"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
});
使用 Windsurf 创建种子文件
编写种子脚本可能是一个繁琐的过程,但 Windsurf 通过快速生成结构化和有组织的种子代码来简化它。通过提供清晰的说明,你可以指导 Windsurf 创建脚本,用真实数据填充数据库,包括处理模式中定义的关系和复杂结构。以下是一个示例提示及其生成的种子脚本:
- 填充数据库的提示
- 结果
"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();
});
其他资源
将 Windsurf 与 Prisma 结合使用可以加快开发速度,同时确保代码库整洁且易于维护。要继续学习:
与 Prisma 保持联系
通过与我们活跃的社区联系,继续你的 Prisma 之旅。保持信息更新,参与其中,并与其他开发人员协作。 我们的活跃社区。随时了解最新信息,积极参与,并与其他开发者协作
- 在 X 上关注我们 获取公告、直播活动和实用技巧。
- 加入我们的 Discord 提问、与社区交流,并通过对话获得积极支持。
- 在 YouTube 上订阅 获取教程、演示和直播。
- 在 GitHub 上参与 为仓库加星、报告问题或为问题贡献代码。