Windsurf
Windsurf 编辑器 是一个 AI 驱动的代码编辑器,旨在通过自动执行重复的编码任务来提高工作效率。当与 Prisma(一种用于数据库工作流的强大且类型安全的工具包)搭配使用时,它将成为管理和优化数据库模式、查询和数据播种的强大解决方案。
¥Windsurf Editor is an AI-powered code editor designed to boost productivity by automating repetitive coding tasks. When paired with Prisma, a robust and type-safe toolkit for database workflows, it becomes a powerful solution for managing and optimizing database schemas, queries, and data seeding.
本指南提供了有关如何有效地将 Prisma 与 Windsurf 结合使用的详细说明:
¥This guide provides detailed instructions for effectively using Prisma with Windsurf to:
-
使用
.windsurfrules
定义特定于项目的最佳实践。¥Define project-specific best practices with
.windsurfrules
. -
使用 Windsurf 的上下文感知功能。
¥Use Windsurf's context-aware capabilities.
-
生成适合你数据库的模式、查询和种子数据。
¥Generate schemas, queries, and seed data tailored to your database.
虽然本指南重点介绍 Windsurf,但这些模式应该适用于任何 AI 编辑器。在 X 上让我们知道 如果你希望我们为你首选的工具创建指南!
¥While this guide is focused on Windsurf, these patterns should work with any AI editor. Let us know on X if you'd like us to create guides for your preferred tool!
Prisma MCP 服务器
¥Prisma MCP server
Prisma 提供自己的 模型上下文协议 (MCP) 服务器,可让你管理 Prisma Postgres 数据库、建模数据库模式,甚至通过迁移进行聊天。
¥Prisma provides its own Model Context Protocol (MCP) server that lets you manage Prisma Postgres databases, model database schemas, and even chat through migrations.
通过 Windsurf 插件添加 Prisma MCP 服务器
¥Add Prisma MCP server via Windsurf Plugins
你可以通过 Windsurf MCP 插件商店 添加 Prisma MCP 服务器。
¥You can add the Prisma MCP server via Windsurf MCP Plugin Store.
新的 MCP 插件可以从插件商店添加,你可以通过点击 Cascade 面板右上角菜单中的“插件”图标,或从 Windsurf 设置 > Cascade > 插件部分访问。只需在插件商店中搜索 Prisma 并安装 Prisma
插件即可。
¥New MCP plugins can be added from the Plugin Store, which you can access by clicking on the Plugins icon in the top right menu in the Cascade panel, or from the Windsurf Settings > Cascade > Plugins section. Just search for Prisma in the Plugin Store and install the Prisma
plugin.
使用 .windsurfrules
定义项目特定规则
¥Defining project-specific rules with .windsurfrules
Windsurf 中的 .windsurfrules
文件 允许你根据 Prisma 项目量身定制最佳实践和开发标准。通过定义清晰一致的规则,你可以确保 Windsurf 生成干净、可维护且特定于项目的代码,并且只需进行最少的手动调整。
¥The .windsurfrules
file in Windsurf allows you to enforce best practices and development standards tailored to your Prisma project. By defining clear and consistent rules, you can ensure that Windsurf generates clean, maintainable, and project-specific code with minimal manual adjustments.
要实现这些规则,请在项目的根目录中创建一个 .windsurfrules
文件。以下是示例配置:
¥To implement these rules, create a .windsurfrules
file in the root of your project. Below is an example configuration:
Example .windsurfrules
file
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.
此文件确保一致且可维护的代码生成,减少人工干预,同时提高项目质量。
¥This file ensures consistent and maintainable code generation, reducing manual intervention while improving project quality.
使用 Windsurf 的上下文感知功能
¥Using Windsurf's context-aware capabilities
Windsurf 的 context-awareness 功能让你可以利用项目文件和外部资源来增强 AI 对项目的理解。通过在上下文中包含你的 Prisma 模式和相关文档,你可以使 Windsurf 能够基于你的数据库模式生成更准确的查询、测试和种子数据。
¥Windsurf's context-awareness features let you leverage both your project files and external resources to enhance the AI's understanding of your project. By including your Prisma schema and relevant documentation in the context, you enable Windsurf to generate more accurate queries, tests, and seed data based on your database schema.
包含其他 Prisma 资源
¥Including Additional Prisma Resources
Windsurf 内置了对常用库的认知,但你可以通过明确引用外部 Prisma 资源来进一步增强其感知能力。这对于保持最新状态或为代码生成和最佳实践提供权威上下文尤其有用。
¥Windsurf comes with built-in knowledge of common libraries, but you can further enhance its awareness by explicitly referencing external Prisma resources. This is especially useful for staying up-to-date or providing authoritative context for code generation and best practices.
例如,你可以参考:
¥For example, you might reference:
在请求中引用资源:
¥Reference the resource in your requests:
索取代码、说明或评论时,请包含相关 Prisma 资源的链接,并指定将其用作参考。
¥When asking for code, explanations, or reviews, include the link to the relevant Prisma resource and specify that it should be used as a reference.
Generate a migration script using best practices from prisma.io/docs.
请求持续感知:
¥Request persistent awareness:
要求 Windsurf 始终为项目中所有与 Prisma 相关的工作考虑特定资源。
¥Ask Windsurf to always consider a specific resource for all Prisma-related work in your project.
Always use the Prisma Changelog at prisma.io/changelog for Prisma updates in this project.
请求定期更新:
¥Ask for regular updates:
如果你希望 Windsurf 检查更新或新功能,请明确请求。
¥If you want Windsurf to check for updates or new features, explicitly request it.
Before suggesting Prisma code, check the latest changes from prisma.io/changelog.
通过在请求或项目指南中直接引用外部资源,你可以确保 Windsurf 利用最新、最相关的 Prisma 信息。
¥By referencing external resources directly in your requests or project guidelines, you ensure Windsurf leverages the most current and relevant Prisma information.
使用模式作为上下文
¥Using schema as context
Windsurf 开箱即用,会自动将当前文件、其他打开的文件以及代码库的索引部分视为上下文。为确保 Cascade 充分利用 Prisma 模式,请保持 schema.prisma
文件在编辑器中处于打开或固定状态。
¥Out of the box, Windsurf automatically considers the current file, other open files, and indexed portions of your codebase as context. To ensure Cascade fully leverages your Prisma schema, keep your schema.prisma
file open or pinned in the editor.
生成 Prisma 模式
¥Generating Prisma schema
Windsurf 可以根据高级描述生成 Prisma 模式,使你能够快速为数据库模式建立坚实的基础。通过提供清晰详细的提示,Windsurf 可以根据你的需求创建 Prisma 模式。无论你需要通用的基础架构,还是针对具体用例的特定架构,Windsurf 都能精准满足你的需求。这是一个示例提示及其相应的结果:
¥Windsurf can generate Prisma schemas from high-level descriptions, enabling you to quickly establish a solid foundation for your database schema. By providing a clear and detailed prompt, Windsurf creates Prisma schemas tailored to your requirements. Whether you need a general foundational schema or a highly specific one for detailed use cases, Windsurf can deliver with precision. Here's an example prompt and its corresponding result:
即使使用相同的提示符,LLM 每次也可能产生不同的结果。
¥LLMs may produce different results each time, even with the same prompt.
- Prompt to generate Prisma schema
- Result
"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 查询
¥Generating Prisma queries
Windsurf 可以帮助你创建根据 Prisma 模式定制的查询,无论是用于基本数据检索还是复杂的优化操作。为了获得最佳结果,请专注于编写清晰、具体的提示来定义你的要求,例如要包含的字段、要应用的条件和要遍历的关系。这可确保 Windsurf 生成准确、高性能且类型安全的查询。这是一个示例提示及其结果查询:
¥Windsurf can help you create queries tailored to your Prisma schema, whether for basic data retrieval or complex, optimized operations. To get the best results, focus on writing clear, specific prompts that define your requirements, such as the fields to include, conditions to apply, and relationships to traverse. This ensures Windsurf generates accurate, performant, and type-safe queries. Here's an example prompt and its resulting query:
- Prompt to generate a database query
- Result
"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 创建种子文件
¥Creating seed files with Windsurf
编写种子脚本可能是一个繁琐的过程,但 Windsurf 通过快速生成结构化且有组织的种子代码简化了这一过程。通过提供清晰的说明,你可以指导 Windsurf 创建脚本,使用实际数据填充数据库,包括处理模式中定义的关系和复杂结构。这是一个示例提示及其结果种子脚本:
¥Writing seed scripts can be a tedious process, but Windsurf simplifies it by quickly generating structured and organized seed code. By providing clear instructions, you can guide Windsurf to create scripts that populate your database with realistic data, including handling relationships and complex structures defined in your schema. Here's an example prompt and its resulting seed script:
- Prompt to seed the database
- Result
"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();
});
其他资源
¥Additional resources
将 Windsurf 与 Prisma 结合使用可以加快开发速度,同时确保数据库代码简洁易维护。继续学习:
¥Using Windsurf with Prisma can speed up development while ensuring clean and maintainable database code. To keep learning:
Stay connected with Prisma
Continue your Prisma journey by connecting with our active community. Stay informed, get involved, and collaborate with other developers:
- Follow us on X for announcements, live events and useful tips.
- Join our Discord to ask questions, talk to the community, and get active support through conversations.
- Subscribe on YouTube for tutorials, demos, and streams.
- Engage on GitHub by starring the repository, reporting issues, or contributing to an issue.