Windsurf
Windsurf Editor 是一个 AI 驱动的代码编辑器,旨在通过自动化重复的编码任务来提高生产力。 当与 Prisma(一个用于数据库工作流程的强大且类型安全的工具包)结合使用时,它将成为管理和优化数据库模式、查询和数据填充的强大解决方案。
本指南提供了有关如何有效使用 Prisma 和 Windsurf 的详细说明,以
- 使用
.windsurfrules
定义项目特定的最佳实践。 - 使用 Windsurf 的上下文感知功能。
- 生成针对您的数据库量身定制的模式、查询和种子数据。
虽然本指南侧重于 Windsurf,但这些模式应适用于任何 AI 编辑器。 请在 X 上告知我们 如果您希望我们为您的首选工具创建指南!
Prisma MCP 服务器
Prisma 提供了自己的 模型上下文协议 (MCP) 服务器,可让您管理 Prisma Postgres 数据库、建模数据库模式,甚至可以通过迁移进行聊天。 在此处了解有关如何将其添加到 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 信息。
使用 schema 作为上下文
Windsurf 开箱即用,会自动将当前文件、其他打开的文件以及代码库的索引部分视为上下文。 为了确保 Cascade 充分利用您的 Prisma 模式,请保持您的 schema.prisma
文件在编辑器中打开或固定。
生成 Prisma 模式
Windsurf 可以从高级描述生成 Prisma 模式,使您能够快速为您的数据库模式建立坚实的基础。 通过提供清晰详细的提示,Windsurf 可以创建针对您的要求量身定制的 Prisma 模式。 无论您需要通用的基础模式还是用于详细用例的高度特定的模式,Windsurf 都可以精确地交付。 这是一个示例提示及其对应的结果
即使使用相同的提示,LLM 每次也可能会产生不同的结果。
- 生成 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 通过给仓库加星、报告问题或为问题做出贡献。