Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/four-buttons-run.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---

Ignore OTEL_EXPORTER_OTLP_ENDPOINT environment variable from `.env` files, to prevent the internal OTEL_EXPORTER_OTLP_ENDPOINT being overwritten with a user-supplied value.
6 changes: 6 additions & 0 deletions .changeset/friendly-brooms-cry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"trigger.dev": patch
"@trigger.dev/build": patch
---

prismaExtension fixes for #1325 and #1327
5 changes: 5 additions & 0 deletions .changeset/little-donkeys-protect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@trigger.dev/build": patch
---

Feat: puppeteer build extension
8 changes: 8 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@
"cwd": "${workspaceFolder}/references/v3-catalog",
"sourceMaps": true
},
{
"type": "node-terminal",
"request": "launch",
"name": "Debug prisma-catalog deploy CLI",
"command": "pnpm exec trigger deploy --self-hosted --load-image",
"cwd": "${workspaceFolder}/references/prisma-catalog",
"sourceMaps": true
},
{
"type": "node-terminal",
"request": "launch",
Expand Down
7 changes: 2 additions & 5 deletions docs/config/config-file.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -444,12 +444,9 @@ export default defineConfig({
```

<Note>
The `prismaExtension` will inject the `DATABASE_URL` environment variable into the build process
when running the `deploy` command. This means the CLI needs to have `process.env.DATABASE_URL` set
at the time of calling the `deploy` command. You can do this via a `.env` file and passing the
`--env-file .env` option to the deploy command or via shell environment variables. This goes for direct database URLs as well.
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.

These environment variables are only used during the build process and are not embedded in the final image.
These environment variables are only used during the build process and are not embedded in the final container image.

</Note>

Expand Down
1 change: 1 addition & 0 deletions docs/examples/intro.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ description: "Learn how to use Trigger.dev with these practical task examples."
| [DALL·E 3 image generation](/examples/dall-e3-generate-image) | Use OpenAI's GPT-4o and DALL·E 3 to generate an image and text. |
| [FFmpeg video processing](/examples/ffmpeg-video-processing) | Use FFmpeg to process a video in various ways and save it to Cloudflare R2. |
| [OpenAI with retrying](/examples/open-ai-with-retrying) | Create a reusable OpenAI task with custom retry options. |
| [PDF to image](/examples/pdf-to-image) | Use `MuPDF` to turn a PDF into images and save them to Cloudflare R2. |
| [React to PDF](/examples/react-pdf) | Use `react-pdf` to generate a PDF and save it to Cloudflare R2. |
| [Resend email sequence](/examples/resend-email-sequence) | Send a sequence of emails over several days using Resend with Trigger.dev. |
| [Sharp image processing](/examples/sharp-image-processing) | Use Sharp to process an image and save it to Cloudflare R2. |
Expand Down
84 changes: 84 additions & 0 deletions docs/examples/pdf-to-image.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
title: "Turn a PDF into an image using MuPDF"
sidebarTitle: "PDF to image"
description: "This example will show you how to turn a PDF into an image using MuPDF and Trigger.dev."
---

## Overview

This example demonstrates how to use Trigger.dev to turn a PDF into a series of images using MuPDF and upload them to Cloudflare R2.

## Task code

```ts trigger/pdfToImage.ts
import { logger, task } from "@trigger.dev/sdk/v3";
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
import { execSync } from "child_process";
import fs from "fs";
import path from "path";

// Initialize S3 client
const s3Client = new S3Client({
region: "auto",
endpoint: process.env.S3_ENDPOINT,
credentials: {
accessKeyId: process.env.R2_ACCESS_KEY_ID ?? "",
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY ?? "",
},
});

export const pdfToImage = task({
id: "pdf-to-image",
run: async (payload: { pdfUrl: string; documentId: string }) => {
logger.log("Converting PDF to images", payload);

const pdfPath = `/tmp/${payload.documentId}.pdf`;
const outputDir = `/tmp/${payload.documentId}`;

// Download PDF and convert to images using MuPDF
execSync(`curl -s -o ${pdfPath} ${payload.pdfUrl}`);
fs.mkdirSync(outputDir, { recursive: true });
execSync(`mutool convert -o ${outputDir}/page-%d.png ${pdfPath}`);

// Upload images to R2
const uploadedUrls = [];
for (const file of fs.readdirSync(outputDir)) {
const s3Key = `images/${payload.documentId}/${file}`;
const uploadParams = {
Bucket: process.env.S3_BUCKET,
Key: s3Key,
Body: fs.readFileSync(path.join(outputDir, file)),
ContentType: "image/png",
};

logger.log("Uploading to R2", uploadParams);

await s3Client.send(new PutObjectCommand(uploadParams));
const s3Url = `https://${process.env.S3_BUCKET}.r2.cloudflarestorage.com/${s3Key}`;
uploadedUrls.push(s3Url);
logger.log("Image uploaded to R2", { url: s3Url });
}

// Clean up
fs.rmSync(outputDir, { recursive: true, force: true });
fs.unlinkSync(pdfPath);

logger.log("All images uploaded to R2", { urls: uploadedUrls });

return {
imageUrls: uploadedUrls,
};
},
});
```

## Testing your task

To test this task in the dashboard, you can use the following payload:

```json
{
"pdfUrl": "https://pdfobject.com/pdf/sample.pdf",
"documentId": "unique-document-id"
}
```
1 change: 1 addition & 0 deletions docs/mint.json
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@
"examples/dall-e3-generate-image",
"examples/ffmpeg-video-processing",
"examples/open-ai-with-retrying",
"examples/pdf-to-image",
"examples/sharp-image-processing",
"examples/react-pdf",
"examples/resend-email-sequence",
Expand Down
17 changes: 16 additions & 1 deletion packages/build/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"./extensions/core": "./src/extensions/core.ts",
"./extensions/prisma": "./src/extensions/prisma.ts",
"./extensions/audioWaveform": "./src/extensions/audioWaveform.ts",
"./extensions/typescript": "./src/extensions/typescript.ts"
"./extensions/typescript": "./src/extensions/typescript.ts",
"./extensions/puppeteer": "./src/extensions/puppeteer.ts"
},
"sourceDialects": [
"@triggerdotdev/source"
Expand All @@ -49,6 +50,9 @@
],
"extensions/typescript": [
"dist/commonjs/extensions/typescript.d.ts"
],
"extensions/puppeteer": [
"dist/commonjs/extensions/puppeteer.d.ts"
]
}
},
Expand Down Expand Up @@ -145,6 +149,17 @@
"types": "./dist/commonjs/extensions/typescript.d.ts",
"default": "./dist/commonjs/extensions/typescript.js"
}
},
"./extensions/puppeteer": {
"import": {
"@triggerdotdev/source": "./src/extensions/puppeteer.ts",
"types": "./dist/esm/extensions/puppeteer.d.ts",
"default": "./dist/esm/extensions/puppeteer.js"
},
"require": {
"types": "./dist/commonjs/extensions/puppeteer.d.ts",
"default": "./dist/commonjs/extensions/puppeteer.js"
}
}
},
"main": "./dist/commonjs/index.js",
Expand Down
31 changes: 23 additions & 8 deletions packages/build/src/extensions/prisma.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,9 @@ export class PrismaExtension implements BuildExtension {
if (this.options.typedSql) {
generatorFlags.push(`--sql`);

const schemaDir = dirname(this._resolvedSchemaPath);
const prismaDir = dirname(schemaDir);
const prismaDir = usingSchemaFolder
? dirname(dirname(this._resolvedSchemaPath))
: dirname(this._resolvedSchemaPath);

context.logger.debug(`Using typedSql`);

Expand Down Expand Up @@ -226,15 +227,29 @@ export class PrismaExtension implements BuildExtension {
commands.push(
`${binaryForRuntime(manifest.runtime)} node_modules/prisma/build/index.js migrate deploy`
);
}

env.DATABASE_URL = manifest.deploy.env?.DATABASE_URL;
env.DATABASE_URL = manifest.deploy.env?.DATABASE_URL;

if (this.options.directUrlEnvVarName) {
env[this.options.directUrlEnvVarName] =
manifest.deploy.env?.[this.options.directUrlEnvVarName];
} else {
env.DIRECT_URL = manifest.deploy.env?.DIRECT_URL;
if (this.options.directUrlEnvVarName) {
env[this.options.directUrlEnvVarName] =
manifest.deploy.env?.[this.options.directUrlEnvVarName] ??
process.env[this.options.directUrlEnvVarName];

if (!env[this.options.directUrlEnvVarName]) {
context.logger.warn(
`prismaExtension could not resolve the ${this.options.directUrlEnvVarName} environment variable. Make sure you add it to your environment variables or provide it as an environment variable to the deploy CLI command. See our docs for more info: https://trigger.dev/docs/deploy-environment-variables`
);
}
} else {
env.DIRECT_URL = manifest.deploy.env?.DIRECT_URL;
env.DIRECT_DATABASE_URL = manifest.deploy.env?.DIRECT_DATABASE_URL;
}

if (!env.DATABASE_URL) {
context.logger.warn(
`prismaExtension could not resolve the DATABASE_URL environment variable. Make sure you add it to your environment variables. See our docs for more info: https://trigger.dev/docs/deploy-environment-variables`
);
}

context.logger.debug(`Adding the prisma layer with the following commands`, {
Expand Down
34 changes: 34 additions & 0 deletions packages/build/src/extensions/puppeteer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { BuildManifest } from "@trigger.dev/core/v3";
import { BuildContext, BuildExtension } from "@trigger.dev/core/v3/build";

export function puppeteer() {
return new PuppeteerExtension();
}

class PuppeteerExtension implements BuildExtension {
public readonly name = "PuppeteerExtension";

async onBuildComplete(context: BuildContext, manifest: BuildManifest) {
if (context.target === "dev") {
return;
}

context.logger.debug(`Adding ${this.name} to the build`);

const instructions = [
`RUN apt-get update && apt-get install curl gnupg -y \
&& curl --location --silent https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
&& sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \
&& apt-get update \
&& apt-get install google-chrome-stable -y --no-install-recommends \
&& rm -rf /var/lib/apt/lists/*`,
];

context.addLayer({
id: "puppeteer",
image: {
instructions,
},
});
}
}
4 changes: 2 additions & 2 deletions packages/cli-v3/src/deploy/buildImage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ COPY --chown=bun:bun . .

${postInstallCommands}

from build as indexer
FROM build AS indexer

USER bun
WORKDIR /app
Expand Down Expand Up @@ -601,7 +601,7 @@ COPY --chown=node:node . .

${postInstallCommands}

from build as indexer
FROM build AS indexer

USER node
WORKDIR /app
Expand Down
1 change: 1 addition & 0 deletions packages/cli-v3/src/utilities/dotEnv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export function resolveDotEnvVars(cwd?: string, envFile?: string) {
// remove TRIGGER_API_URL and TRIGGER_SECRET_KEY, since those should be coming from the worker
delete result.TRIGGER_API_URL;
delete result.TRIGGER_SECRET_KEY;
delete result.OTEL_EXPORTER_OTLP_ENDPOINT;

return result;
}
Expand Down
Loading
Loading