diff --git a/docs/config/extensions/prismaExtension.mdx b/docs/config/extensions/prismaExtension.mdx index 73bc94b16a..04b049c4ad 100644 --- a/docs/config/extensions/prismaExtension.mdx +++ b/docs/config/extensions/prismaExtension.mdx @@ -9,8 +9,6 @@ If you are using Prisma, you should use the prisma build extension. - Automatically handles copying Prisma files to the build directory - Generates the Prisma client during the deploy process - Optionally will migrate the database during the deploy process -- Support for TypedSQL and multiple schema files -- You can use `prismaSchemaFolder` to specify just the directory containing your schema file, instead of the full path - You can add the extension twice if you have multiple separate schemas in the same project (example below) You can use it for a simple Prisma setup like this: @@ -109,14 +107,27 @@ export default defineConfig({ }); ``` - +### Prisma 6.6.0+ + +In Prisma 6.6.0+, the `output` path for the Prisma client is no longer in `node_modules` by default. This means that the `prismaExtension` will no longer work out of the box with this version. To fix this, you will need to add the following to your `package.json` file: + +```json +{ + "prisma": { + "schema": "prisma/schema.prisma" + } +} +``` -### TypedSQL +This will ensure that the Prisma client is generated in the correct location. -If you are using [TypedSQL](https://www.prisma.io/typedsql), you'll need to enable it via the `typedSql` option: +### The `copy` option + +By default, the prisma schema and migrations are copied to the output directory. You can set this to false to disable this behavior. ```ts import { defineConfig } from "@trigger.dev/sdk/v3"; +import { prismaExtension } from "@trigger.dev/build/extensions/prisma"; export default defineConfig({ project: "", @@ -125,13 +136,15 @@ export default defineConfig({ extensions: [ prismaExtension({ schema: "prisma/schema.prisma", - typedSql: true, + copy: false, }), ], }, }); ``` + + The `prismaExtension` will inject the `DATABASE_URL` environment variable into the build process. Learn more about setting environment variables for deploying in our [Environment Variables](/deploy-environment-variables) guide. diff --git a/packages/build/src/extensions/prisma.ts b/packages/build/src/extensions/prisma.ts index b67adc7efc..b6b4b0b03f 100644 --- a/packages/build/src/extensions/prisma.ts +++ b/packages/build/src/extensions/prisma.ts @@ -2,17 +2,13 @@ import { BuildManifest, BuildTarget } from "@trigger.dev/core/v3"; import { binaryForRuntime, BuildContext, BuildExtension } from "@trigger.dev/core/v3/build"; import assert from "node:assert"; import { existsSync } from "node:fs"; -import { cp, readdir } from "node:fs/promises"; +import { cp } from "node:fs/promises"; import { dirname, join, resolve } from "node:path"; export type PrismaExtensionOptions = { schema: string; migrate?: boolean; version?: string; - /** - * Adds the `--sql` flag to the `prisma generate` command. This will generate the SQL files for the Prisma schema. Requires the `typedSql preview feature and prisma 5.19.0 or later. - */ - typedSql?: boolean; /** * The client generator to use. Set this param to prevent all generators in the prisma schema from being generated. * @@ -42,6 +38,11 @@ export type PrismaExtensionOptions = { */ clientGenerator?: string; directUrlEnvVarName?: string; + /** + * By default, the prisma schema and migrations are copied to the output directory. Set this to false to disable this behavior. + * @default true + */ + copy?: boolean; }; const BINARY_TARGET = "linux-arm64-openssl-3.0.x"; @@ -98,6 +99,12 @@ export class PrismaExtension implements BuildExtension { externals: manifest.externals, }); + context.logger.debug("[PrismaExtension] Debugging paths and options", { + resolvedSchemaPath: this._resolvedSchemaPath, + options: this.options, + workingDir: context.workingDir, + }); + const prismaExternal = manifest.externals?.find( (external) => external.name === "@prisma/client" ); @@ -112,117 +119,55 @@ export class PrismaExtension implements BuildExtension { context.logger.debug(`PrismaExtension is generating the Prisma client for version ${version}`); - const usingSchemaFolder = dirname(this._resolvedSchemaPath).endsWith("schema"); - const commands: string[] = []; - let prismaDir: string | undefined; - const generatorFlags: string[] = []; if (this.options.clientGenerator) { generatorFlags.push(`--generator=${this.options.clientGenerator}`); } - if (this.options.typedSql) { - generatorFlags.push(`--sql`); - - const prismaDir = usingSchemaFolder - ? dirname(dirname(this._resolvedSchemaPath)) - : dirname(this._resolvedSchemaPath); - - context.logger.debug(`Using typedSql`); - - // Find all the files prisma/sql/*.sql - const sqlFiles = await readdir(join(prismaDir, "sql")).then((files) => - files.filter((file) => file.endsWith(".sql")) - ); - - context.logger.debug(`Found sql files`, { - sqlFiles, - }); - - const sqlDestinationPath = join(manifest.outputPath, "prisma", "sql"); - - for (const file of sqlFiles) { - const destination = join(sqlDestinationPath, file); - const source = join(prismaDir, "sql", file); - - context.logger.debug(`Copying the sql from ${source} to ${destination}`); - - await cp(source, destination); - } - } - - if (usingSchemaFolder) { - const schemaDir = dirname(this._resolvedSchemaPath); - - prismaDir = dirname(schemaDir); - - context.logger.debug(`Using the schema folder: ${schemaDir}`); + const prismaDir = dirname(this._resolvedSchemaPath); + const doCopy = this.options.copy ?? true; - // Find all the files in schemaDir that end with .prisma (excluding the schema.prisma file) - const prismaFiles = await readdir(schemaDir).then((files) => - files.filter((file) => file.endsWith(".prisma")) - ); - - context.logger.debug(`Found prisma files in the schema folder`, { - prismaFiles, - }); - - const schemaDestinationPath = join(manifest.outputPath, "prisma", "schema"); - - const allPrismaFiles = [...prismaFiles]; - - for (const file of allPrismaFiles) { - const destination = join(schemaDestinationPath, file); - const source = join(schemaDir, file); - - context.logger.debug(`Copying the prisma schema from ${source} to ${destination}`); - - await cp(source, destination); - } - - commands.push( - `${binaryForRuntime( - manifest.runtime - )} node_modules/prisma/build/index.js generate ${generatorFlags.join(" ")}` // Don't add the --schema flag or this will fail - ); - } else { - prismaDir = dirname(this._resolvedSchemaPath); + if (doCopy) { // Now we need to add a layer that: // Copies the prisma schema to the build outputPath // Adds the `prisma` CLI dependency to the dependencies // Adds the `prisma generate` command, which generates the Prisma client - const schemaDestinationPath = join(manifest.outputPath, "prisma", "schema.prisma"); + const schemaDestinationPath = join(manifest.outputPath, "schema.prisma"); // Copy the prisma schema to the build output path context.logger.debug( `Copying the prisma schema from ${this._resolvedSchemaPath} to ${schemaDestinationPath}` ); await cp(this._resolvedSchemaPath, schemaDestinationPath); - - commands.push( - `${binaryForRuntime( - manifest.runtime - )} node_modules/prisma/build/index.js generate --schema=./prisma/schema.prisma ${generatorFlags.join( - " " - )}` - ); } + commands.push( + `${binaryForRuntime( + manifest.runtime + )} node_modules/prisma/build/index.js generate --schema=./schema.prisma ${generatorFlags.join( + " " + )}` + ); + const env: Record = {}; if (this.options.migrate) { - // Copy the migrations directory to the build output path - const migrationsDir = join(prismaDir, "migrations"); - const migrationsDestinationPath = join(manifest.outputPath, "prisma", "migrations"); + if (doCopy) { + // Copy the migrations directory to the build output path + const migrationsDir = join(prismaDir, "migrations"); + const migrationsDestinationPath = join(manifest.outputPath, "migrations"); - context.logger.debug( - `Copying the prisma migrations from ${migrationsDir} to ${migrationsDestinationPath}` - ); + context.logger.debug( + `Copying the prisma migrations from ${migrationsDir} to ${migrationsDestinationPath}` + ); - await cp(migrationsDir, migrationsDestinationPath, { recursive: true }); + if (existsSync(migrationsDir)) { + await cp(migrationsDir, migrationsDestinationPath, { recursive: true }); + } + } commands.push( `${binaryForRuntime(manifest.runtime)} node_modules/prisma/build/index.js migrate deploy`