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 上參與 為倉庫加星、報告問題或為問題貢獻程式碼。