);
};
export default User;
```
Generating plain SQL queries for use with TypedSQL [#generating-plain-sql-queries-for-use-with-typedsql]
How Tabnine helps [#how-tabnine-helps-3]
While Prisma provides a high-level API for querying, sometimes a developer may need to drop down to raw SQL for more low-level control of a query. In these cases, they can use [TypedSQL](/orm/prisma-client/using-raw-sql/typedsql) which provides full type safety for raq SQL queries in Prisma ORM.
One common use case are aggregation queries, such as calculating percentages of different subscription statuses in the schema example above.
Tabnine can assist by:
* Generating SQL queries based on your Prisma schema.
* Structuring complex aggregations without manual trial and error.
* Integrating the queries in your application code.
Example: Calculating the percentages of active, expired, and paused subscriptions [#example-calculating-the-percentages-of-active-expired-and-paused-subscriptions]
Prompt [#prompt-3]
*Generate a SQL query that returns the percentage of subscriptions that are Active, Paused, and Expired.*
Generated SQL query [#generated-sql-query]
```sql title="prisma/sql/subscriptionsReport.sql"
SELECT
status,
COUNT(*) * 100.0 / (SELECT COUNT(*) FROM "Subscription") AS percentage
FROM "Subscription"
GROUP BY status;
```
Application code [#application-code]
```ts
import { PrismaClient } from "../prisma/generated/client";
import { subscriptionsReport } from "../prisma/generated/client/sql";
const prisma = new PrismaClient();
const usersWithPostCounts = await prisma.$queryRawTyped(subscriptionsReport());
console.log(usersWithPostCounts);
```
Generating code for unit and integration tests [#generating-code-for-unit-and-integration-tests]
How Tabnine helps [#how-tabnine-helps-4]
Writing tests ensures that Prisma-based applications function correctly and behave according to requirements and expectations. However, writing tests is a time-consuming activity that often follows predictable and repetitive patterns.
Tabnine can drastically speed up writing tests by:
* Generating test boilerplate for both unit and integration tests.
* Suggesting mocks and fixtures for Prisma database interactions.
* Helping structure test cases to follow best practices.
* Providing integration test scaffolding for testing Prisma with a real or in-memory database.
Example: Writing a unit test for a Prisma service [#example-writing-a-unit-test-for-a-prisma-service]
Prompt [#prompt-4]
*Generate a Jest unit test for a Prisma service function that fetches all active users.*
Generated code [#generated-code-3]
```ts filename=__tests__/userService.test.ts
import { prismaMock } from "../prisma/singleton";
import { getActiveUsers } from "../services/userService";
test("should return only active users", async () => {
prismaMock.user.findMany.mockResolvedValue([
{ id: 1, name: "Alice", email: "alice@example.com" },
{ id: 2, name: "Bob", email: "bob@example.com" },
]);
const users = await getActiveUsers();
expect(users).toHaveLength(2);
expect(users[0].email).toBe("alice@example.com");
});
```
Guiding through major refactorings [#guiding-through-major-refactorings]
How Tabnine helps [#how-tabnine-helps-5]
Thanks to Prisma ORM's type safe queries, refactoring are more safe and predictable than with other ORMs: After making schema changes, the generated Prisma Client code will be updated and the TypeScript compiler will highlight all places that need a change.
However, there may still be more difficult situations during a refactoring, e.g. when business logic or complex queries need to be adjusted.
Tabnine can assist during refactorings by:
* Identifying patterns in your code and suggesting refactorings while maintaining consistency.
* Helping update database queries after schema changes and reducing manual effort.
* Providing function rewrites to simplify and optimize logic.
* Suggesting breaking changes that need to be handled across your codebase.
Example: Refactoring a Prisma query after a schema change [#example-refactoring-a-prisma-query-after-a-schema-change]
Prompt [#prompt-5]
*Refactor this Prisma query to support soft deletion using a `deletedAt` timestamp field in the User model.*
Initial code [#initial-code]
```ts
const users = await prisma.user.findMany();
```
Refactored code [#refactored-code]
```ts
const users = await prisma.user.findMany({
where: { deletedAt: null },
});
```
Generating seeding scripts [#generating-seeding-scripts]
How Tabnine helps [#how-tabnine-helps-6]
Seeding a database with realistic test data can be cumbersome. Realistic seed data is helpful during development because it gives the developer a better impression of the application when it's used in the real-world. Tabnine can help with database seeding by:
* Generating scripts with structured seed data based on the schema and with specific requirements.
* Creating real-looking placeholder data that can be used to test the app.
* Generate specific data to cover edge cases.
Example: Creating a seed script [#example-creating-a-seed-script]
Prompt [#prompt-6]
*Generate a Prisma seed script for populating User, Organization, and Subscription models.*
Generated code [#generated-code-4]
```ts
import { PrismaClient } from "../prisma/generated/client";
const prisma = new PrismaClient();
async function main() {
await prisma.organization.create({
data: {
name: "Prisma Corp",
slug: "prisma-corp",
subscription: {
create: {
plan: "PRO",
status: "ACTIVE",
},
},
users: {
create: [
{ name: "Alice Doe", email: "alice@prisma.io" },
{ name: "Bob Smith", email: "bob@prisma.io" },
],
},
},
});
console.log("Seed data created successfully");
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});
```
Using the Prisma VS Code extension to manage your database [#using-the-prisma-vs-code-extension-to-manage-your-database]
The [Prisma VS Code extension](https://marketplace.visualstudio.com/items?itemName=Prisma.prisma) is a powerful tool for building applications with [Prisma Postgres](/postgres). If you are using Tabnine in an editor that allows you to install the Prisma VS Code extension and you are using Prisma Postgres, you should use it. The extension provides a dedicated UI for managing Prisma Postgres instances, both local and remote, making it easy to view, create, and delete instances, push local databases to the cloud, and visualize your schema.
Database management UI [#database-management-ui]
With its built-in database management interface, the [Prisma VS Code extension](/guides/postgres/vscode) lets you easily work with local and remote Prisma Postgres instances from inside your editor.
Workflows [#workflows]
The UI enables the following workflows:
* Authenticate with the [Prisma Console](https://console.prisma.io/?utm_source=docs\&utm_medium=content\&utm_content=ai)
* View, create and delete Prisma Postgres instances (local & remote)
* "Push to cloud": Easily deploy a local Prisma Postgres instance
* View and edit data via an embedded Prisma Studio
* Visualize your database schema
Usage [#usage]
To manage Prisma Postgres instances via the UI in the Prisma VS Code extension:
1. Ensure you have the latest version of the [Prisma VS Code extension](https://marketplace.visualstudio.com/items?itemName=Prisma.prisma) installed
2. Find the Prisma logo in the **Activity Bar**
3. Click the **Sign in to get started** button
4. Authenticate with the [Prisma Console](https://console.prisma.io/?utm_source=docs\&utm_medium=content\&utm_content=ai) using the sign-in prompt, then select a target [workspace](/console/concepts#workspace)
Prisma Studio built-in [#prisma-studio-built-in]
Beyond managing your database instances, the Prisma VS Code extension embeds Prisma Studio directly in your editor, making it easy to perform create, update, and delete operations on your database right inside Windsurf. Follow these [easy steps](/studio/integrations/vscode-integration) to get started.
## Related pages
- [`Agent Skills`](https://www.prisma.io/docs/ai/tools/skills): Give your AI coding agent up-to-date Prisma knowledge with installable skills
- [`ChatGPT`](https://www.prisma.io/docs/ai/tools/chatgpt): Learn how to add the Prisma MCP server to ChatGPT to manage your Prisma Postgres databases
- [`Codex`](https://www.prisma.io/docs/ai/tools/codex): Learn how to install the Prisma Codex plugin and use Prisma MCP from Codex
- [`Cursor`](https://www.prisma.io/docs/ai/tools/cursor): Learn tips and best practices for using Prisma ORM with the Cursor AI code editor
- [`GitHub Copilot`](https://www.prisma.io/docs/ai/tools/github-copilot): Learn about the features available with GitHub Copilot and Prisma ORM, plus best practices and tips
# Windsurf (/docs/ai/tools/windsurf)
Location: AI > AI Tools > Windsurf
[Windsurf Editor](https://windsurf.com/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.
This guide provides detailed instructions for effectively using Prisma with Windsurf to:
* Define project-specific best practices with `.windsurfrules`.
* Use Windsurf's context-aware capabilities.
* Generate schemas, queries, and seed data tailored to your database.
> [!NOTE]
> While this guide is focused on Windsurf, these patterns should work with any AI editor. [Let us know on X](https://pris.ly/x?utm_source=docs\&utm_medium=inline_text) if you'd like us to create guides for your preferred tool!
Prisma MCP server [#prisma-mcp-server]
Prisma provides its own [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) server that lets you manage Prisma Postgres databases, inspect schemas, and execute SQL queries.
Add Prisma MCP server via Windsurf Plugins [#add-prisma-mcp-server-via-windsurf-plugins]
You can add the Prisma MCP server via [Windsurf MCP Plugin Store](https://docs.windsurf.com/windsurf/cascade/mcp#adding-a-new-mcp-plugin).
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.
> [!NOTE]
> You can also add the Prisma MCP server manually. Learn more about how you can add the MCP server manually to Windsurf [here](/ai/tools/mcp-server#windsurf).
Defining project-specific rules with .windsurfrules [#defining-project-specific-rules-with-windsurfrules]
The [`.windsurfrules` file](https://docs.windsurf.com/windsurf/cascade/memories) 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.
To implement these rules, create a `.windsurfrules` file in the root of your project. Below is an example configuration:
...
`
For public profile pages (/[username]):
Wrap the entire profile (avatar, name, username, and links list) in a single .card container
This creates a Linktree-style floating card effect
Footer/attribution links stay outside the card
Hero section:
Add a soft radial glow behind the content (large blurred white circle, blur-3xl, 50% opacity)
No visible container edges — just organic, fading brightness
Content floats freely over the glow
**Result:**
- Content "lifts" off the background
- Subtle blur creates depth
- Consistent UI across all pages
````
12. Display Clerk Profile Images [#12-display-clerk-profile-images]
If users sign in with Google or another OAuth provider, Clerk stores their profile photo. Let's display it on public profiles!
Copy and paste this prompt:
````markdown
On the public profile page (`/[username]`), display the user's Clerk profile image (Google photo, etc.) instead of the initial letter avatar.
**Pattern:**
```typescript
// Fetch Clerk user to get profile image
const client = await clerkClient();
const clerkUser = await client.users.getUser(user.clerkId);
```
**Display:**
- Use a plain `