From 3fc2fa17980c298532381987fb811784ddc850b0 Mon Sep 17 00:00:00 2001 From: CuboYe Date: Sun, 17 May 2026 11:37:22 +1000 Subject: [PATCH 1/9] feat(build): add libreoffice build extension --- packages/build/src/extensions/core/libreoffice.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 packages/build/src/extensions/core/libreoffice.ts diff --git a/packages/build/src/extensions/core/libreoffice.ts b/packages/build/src/extensions/core/libreoffice.ts new file mode 100644 index 00000000000..e69de29bb2d From 3169bc14067563a08d57d7afd8faf982662a04f7 Mon Sep 17 00:00:00 2001 From: CuboYe Date: Sun, 17 May 2026 11:37:36 +1000 Subject: [PATCH 2/9] feat(build): add libreoffice build extension for docx/pptx to PDF conversion --- packages/build/src/extensions/core.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/build/src/extensions/core.ts b/packages/build/src/extensions/core.ts index 62671dfd571..971cf83ca68 100644 --- a/packages/build/src/extensions/core.ts +++ b/packages/build/src/extensions/core.ts @@ -5,3 +5,5 @@ export * from "./core/aptGet.js"; export * from "./core/ffmpeg.js"; export * from "./core/neonSyncEnvVars.js"; export * from "./core/vercelSyncEnvVars.js"; +export * from "./core/syncSupabaseEnvVars.js"; +export * from "./core/libreoffice.js"; From 778e902b02b7d42c6f5cd1b50c664d6ff4c6fa4a Mon Sep 17 00:00:00 2001 From: CuboYe Date: Sun, 17 May 2026 11:37:37 +1000 Subject: [PATCH 3/9] feat(build): add libreoffice extension - packages/build/src/extensions/core/libreoffice.ts --- .../build/src/extensions/core/libreoffice.ts | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/packages/build/src/extensions/core/libreoffice.ts b/packages/build/src/extensions/core/libreoffice.ts index e69de29bb2d..87eaa2458ae 100644 --- a/packages/build/src/extensions/core/libreoffice.ts +++ b/packages/build/src/extensions/core/libreoffice.ts @@ -0,0 +1,109 @@ +import { BuildExtension } from "@trigger.dev/core/v3/build"; +import { dirname } from "node:path"; +import { readPackageJSON } from "pkg-types"; + +export type LibreOfficeOptions = { + /** + * Use the minimal LibreOffice writer package (libreoffice-writer) instead of full LibreOffice. + * Sufficient for docx/pptx/xlsx to PDF conversion. Saves ~400MB vs. full install. + * @default false + */ + minimal?: boolean; +}; + +/** + * Build extension that installs LibreOffice for docx/pptx/xlsx → PDF conversion. + * + * Adds the `libreoffice-convert` npm package and the required system packages + * to the Docker build image. The extension is scoped to "deploy" target only + * (dev uses the host machine's LibreOffice if available). + * + * @example + * ```ts + * // In trigger.config.ts + * import { libreoffice } from "@trigger.dev/build/extensions/core"; + * + * build: { + * extensions: [ + * libreoffice(), + * ] + * } + * ``` + * + * Then in your task: + * ```ts + * import libreofficeConvert from "libreoffice-convert"; + * // Convert docx → PDF + * const pdfBuffer = await libreofficeConvert(docxBuffer, "pdf"); + * ``` + */ +export function libreoffice(options: LibreOfficeOptions = {}): BuildExtension { + const { minimal = false } = options; + + // The npm package used for conversion + const NPM_PACKAGE = "libreoffice-convert"; + + return { + name: "libreoffice", + + async onBuildStart(context) { + if (context.target !== "deploy") { + return; + } + + // ── System packages (apt) ───────────────────────────────────────────── + // `aptGet` is defined in the same core directory. + // We delegate to it by registering an apt-get layer. + const systemPackages = minimal + ? [ + "libreoffice-writer", + "libreoffice-calc", + "libreoffice-impress", + "fonts-liberation", + "--no-install-recommends", + ] + : [ + "libreoffice", + "--no-install-recommends", + ]; + + context.addLayer({ + id: "libreoffice-apt", + image: { + pkgs: systemPackages, + }, + }); + + // ── npm package ──────────────────────────────────────────────────────── + // Resolve the locally installed version of libreoffice-convert if present, + // otherwise fall back to "latest". + let version = "latest"; + try { + const modulePath = await context.resolvePath(NPM_PACKAGE); + if (modulePath) { + const packageJSON = await readPackageJSON(dirname(modulePath)); + version = packageJSON.version ?? "latest"; + context.logger.debug( + `[libreoffice] Resolved ${NPM_PACKAGE} version: ${version}` + ); + } + } catch (error) { + context.logger.debug( + `[libreoffice] Could not resolve ${NPM_PACKAGE} version, using "latest"`, + { error } + ); + } + + context.addLayer({ + id: "libreoffice-npm", + dependencies: { + [NPM_PACKAGE]: version, + }, + }); + + context.logger.debug( + `[libreoffice] Added LibreOffice layer (minimal=${minimal})` + ); + }, + }; +} \ No newline at end of file From 8af3e74ebdf4e8018a483d3d67dec673aa4a4349 Mon Sep 17 00:00:00 2001 From: CuboYe Date: Sun, 17 May 2026 11:37:39 +1000 Subject: [PATCH 4/9] feat(build): add libreoffice extension - references/libreoffice-convert/.gitignore --- references/libreoffice-convert/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 references/libreoffice-convert/.gitignore diff --git a/references/libreoffice-convert/.gitignore b/references/libreoffice-convert/.gitignore new file mode 100644 index 00000000000..c2658d7d1b3 --- /dev/null +++ b/references/libreoffice-convert/.gitignore @@ -0,0 +1 @@ +node_modules/ From 9322e51151edd444a54a08c31b28faaf5123d70d Mon Sep 17 00:00:00 2001 From: CuboYe Date: Sun, 17 May 2026 11:37:41 +1000 Subject: [PATCH 5/9] feat(build): add libreoffice extension - references/libreoffice-convert/package.json --- references/libreoffice-convert/package.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 references/libreoffice-convert/package.json diff --git a/references/libreoffice-convert/package.json b/references/libreoffice-convert/package.json new file mode 100644 index 00000000000..e6feac1bfe8 --- /dev/null +++ b/references/libreoffice-convert/package.json @@ -0,0 +1,18 @@ +{ + "name": "references-libreoffice-convert", + "private": true, + "type": "module", + "devDependencies": { + "trigger.dev": "workspace:*" + }, + "dependencies": { + "@trigger.dev/build": "workspace:*", + "@trigger.dev/sdk": "workspace:*", + "libreoffice-convert": "^1.4.3", + "zod": "3.25.76" + }, + "scripts": { + "dev": "trigger dev", + "deploy": "trigger deploy" + } +} \ No newline at end of file From c5e90d0675a525c1d2f7afc001b42d64e3845594 Mon Sep 17 00:00:00 2001 From: CuboYe Date: Sun, 17 May 2026 11:37:42 +1000 Subject: [PATCH 6/9] feat(build): add libreoffice extension - references/libreoffice-convert/trigger.config.ts --- references/libreoffice-convert/trigger.config.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 references/libreoffice-convert/trigger.config.ts diff --git a/references/libreoffice-convert/trigger.config.ts b/references/libreoffice-convert/trigger.config.ts new file mode 100644 index 00000000000..8cb1ae9bc6d --- /dev/null +++ b/references/libreoffice-convert/trigger.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from "@trigger.dev/sdk/v3"; +import { syncEnvVars } from "@trigger.dev/build/extensions/core"; +import { libreoffice } from "@trigger.dev/build/extensions/core"; + +export default defineConfig({ + compatibilityFlags: ["run_engine_v2"], + project: "proj_rrkpdguyagvsoktglnod", + logLevel: "debug", + build: { + extensions: [ + syncEnvVars(), + libreoffice(), + ], + }, +}); \ No newline at end of file From eeb2e0d9934cd9b668a1cc4525e3b242fc0a1fbe Mon Sep 17 00:00:00 2001 From: CuboYe Date: Sun, 17 May 2026 11:37:44 +1000 Subject: [PATCH 7/9] feat(build): add libreoffice extension - references/libreoffice-convert/tsconfig.json --- references/libreoffice-convert/tsconfig.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 references/libreoffice-convert/tsconfig.json diff --git a/references/libreoffice-convert/tsconfig.json b/references/libreoffice-convert/tsconfig.json new file mode 100644 index 00000000000..9a5ee0b9d68 --- /dev/null +++ b/references/libreoffice-convert/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ES2023", + "module": "Node16", + "moduleResolution": "Node16", + "esModuleInterop": true, + "strict": true, + "skipLibCheck": true, + "customConditions": ["@triggerdotdev/source"], + "jsx": "preserve", + "lib": ["DOM", "DOM.Iterable"], + "noEmit": true + }, + "include": ["./src/**/*.ts", "trigger.config.ts"] +} From 8d70ad24248f56a1ef9f16ed2ff0cf0b514d4b7c Mon Sep 17 00:00:00 2001 From: CuboYe Date: Sun, 17 May 2026 11:37:45 +1000 Subject: [PATCH 8/9] feat(build): add libreoffice extension - references/libreoffice-convert/src/index.ts --- references/libreoffice-convert/src/index.ts | 41 +++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 references/libreoffice-convert/src/index.ts diff --git a/references/libreoffice-convert/src/index.ts b/references/libreoffice-convert/src/index.ts new file mode 100644 index 00000000000..30707490e72 --- /dev/null +++ b/references/libreoffice-convert/src/index.ts @@ -0,0 +1,41 @@ +import { createTask } from "@trigger.dev/sdk/v3"; +import libreofficeConvert from "libreoffice-convert"; +import { z } from "zod"; + +/** + * Task that converts Office documents (docx, pptx, xlsx) to PDF using LibreOffice. + * Requires the `libreoffice()` build extension in trigger.config.ts. + * + * @example + * ```ts + * await client.tasks.call("libreoffice-convert", { + * params: { + * input: docxBuffer, // Buffer containing the Office document + * outputFormat: "pdf", // Output format (default: "pdf") + * } + * }); + * ``` + */ +export const libreofficeConvertTask = createTask({ + rpc: "libreoffice/convert", + queue: { + name: "libreoffice-convert", + parallelLimit: 2, + }, + schema: z.object({ + /** Buffer containing the Office document (docx, pptx, xlsx) */ + input: z.string().describe("Base64-encoded document buffer"), + /** Output format. Only "pdf" is supported by libreoffice-convert. */ + outputFormat: z.string().optional().default("pdf"), + }), + async run(params): Promise<{ output: string }> { + const inputBuffer = Buffer.from(params.input, "base64"); + const format = (params.outputFormat || "pdf") as Parameters[1]; + + const pdfBuffer = await libreofficeConvert(inputBuffer, format); + + return { + output: pdfBuffer.toString("base64"), + }; + }, +}); \ No newline at end of file From 6558d0224e57c63ff236a062b48a0dfffb2b32ce Mon Sep 17 00:00:00 2001 From: CuboYe Date: Sun, 17 May 2026 17:02:09 +1000 Subject: [PATCH 9/9] docs(changeset): add changeset for libreoffice build extension --- .changeset/feat-libreoffice-extension.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .changeset/feat-libreoffice-extension.md diff --git a/.changeset/feat-libreoffice-extension.md b/.changeset/feat-libreoffice-extension.md new file mode 100644 index 00000000000..ac1da2ddf96 --- /dev/null +++ b/.changeset/feat-libreoffice-extension.md @@ -0,0 +1,8 @@ +--- +"@trigger.dev/build": minor +"references/libreoffice-convert": patch +--- + +feat(build): add `libreoffice()` build extension for docx/pptx to PDF conversion + +Adds a `libreoffice(options?)` BuildExtension that installs LibreOffice system packages and `libreoffice-convert` npm package at deploy time, enabling direct Office-to-PDF conversion in Trigger.dev tasks.