From 6ac9a2d9ce5e1ebd63a1cf57bc53aa9e09e9704b Mon Sep 17 00:00:00 2001 From: yuly_c Date: Tue, 20 Oct 2026 23:09:08 +0300 Subject: [PATCH] fix(cli): allow selecting Bun 1.4 runtime Add `bun-1.3` and `bun-1.4` as runtime options, mapped to the published `triggerdotdev/bun:1.3-bookworm` and `1.4-bookworm` images (Bun 1.3.14 and 1.4.2). Bun 1.3.x aborts any fetch that receives no bytes for 300s, which fails long non-streaming calls; Bun 1.4 does not have that limit. Plain `bun` is unchanged and still resolves to the 1.3-node20 image. The versioned images have no node binary, so their final stage starts the app with `dumb-init bun`. The supervisor pins uid 1001 for every bun runtime. Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01XW9yYwuPcYpqPr1zX5pk2W --- .changeset/bun-version-runtimes.md | 16 +++++++ .../src/workloadManager/kubernetes.test.ts | 4 +- .../src/workloadManager/kubernetesPodSpec.ts | 2 +- docs/config/config-file.mdx | 25 +++++++++++ docs/guides/frameworks/bun.mdx | 7 ++- docs/self-hosting/overview.mdx | 6 +-- docs/snippets/node-versions.mdx | 4 +- packages/cli-v3/src/build/plugins.ts | 4 +- packages/cli-v3/src/config.ts | 5 ++- packages/cli-v3/src/deploy/buildImage.test.ts | 31 +++++++++++++ packages/cli-v3/src/deploy/buildImage.ts | 17 ++++++- packages/core/src/v3/build/runtime.test.ts | 44 ++++++++++++++++++- packages/core/src/v3/build/runtime.ts | 13 +++++- packages/core/src/v3/schemas/build.ts | 12 ++++- packages/rsc/src/build.ts | 7 +-- 15 files changed, 177 insertions(+), 20 deletions(-) create mode 100644 .changeset/bun-version-runtimes.md diff --git a/.changeset/bun-version-runtimes.md b/.changeset/bun-version-runtimes.md new file mode 100644 index 00000000000..9aaf9ccf8dd --- /dev/null +++ b/.changeset/bun-version-runtimes.md @@ -0,0 +1,16 @@ +--- +"@trigger.dev/core": patch +"@trigger.dev/rsc": patch +"trigger.dev": patch +--- + +Add `bun-1.3` (Bun 1.3.14) and `bun-1.4` (Bun 1.4.2) as `runtime` options in `trigger.config.ts`. Bun 1.3.x aborts any `fetch` that receives no bytes for 300 seconds, which fails long non-streaming calls such as LLM requests. Bun 1.4 does not have this limit, so set `runtime: "bun-1.4"` for those tasks. `runtime: "bun"` is unchanged and still deploys on Bun 1.3.3. + +```ts +import { defineConfig } from "@trigger.dev/sdk"; + +export default defineConfig({ + runtime: "bun-1.4", + project: "", +}); +``` diff --git a/apps/supervisor/src/workloadManager/kubernetes.test.ts b/apps/supervisor/src/workloadManager/kubernetes.test.ts index e99e292aca1..410ea91bfbf 100644 --- a/apps/supervisor/src/workloadManager/kubernetes.test.ts +++ b/apps/supervisor/src/workloadManager/kubernetes.test.ts @@ -177,7 +177,9 @@ describe("runnerSecurityContext", () => { }); it("pins bun's own uid, which differs from node's", () => { - expect(runnerSecurityContext("restricted", 1000, "bun")?.runAsUser).toBe(1001); + for (const runtime of ["bun", "bun-1.3", "bun-1.4"]) { + expect(runnerSecurityContext("restricted", 1000, runtime)?.runAsUser).toBe(1001); + } }); it("falls back to the configured uid when the runtime is unknown", () => { diff --git a/apps/supervisor/src/workloadManager/kubernetesPodSpec.ts b/apps/supervisor/src/workloadManager/kubernetesPodSpec.ts index ddd336d2f2e..ecdc9fd2c42 100644 --- a/apps/supervisor/src/workloadManager/kubernetesPodSpec.ts +++ b/apps/supervisor/src/workloadManager/kubernetesPodSpec.ts @@ -122,7 +122,7 @@ export function runnerSecurityContext( allowPrivilegeEscalation: false, capabilities: { drop: ["ALL"] }, ...(level === "restricted" - ? { runAsNonRoot: true, runAsUser: runtime === "bun" ? BUN_RUN_AS_USER : runAsUser } + ? { runAsNonRoot: true, runAsUser: runtime?.startsWith("bun") ? BUN_RUN_AS_USER : runAsUser } : {}), }; } diff --git a/docs/config/config-file.mdx b/docs/config/config-file.mdx index 34738566a04..53cfb96fe02 100644 --- a/docs/config/config-file.mdx +++ b/docs/config/config-file.mdx @@ -347,6 +347,31 @@ See our [Bun guide](/guides/frameworks/bun) for more information. +### Bun versions + +`runtime: "bun"` deploys on Bun `1.3.3`. To pick a Bun release line yourself, use `bun-1.3` (Bun `1.3.14`) or `bun-1.4` (Bun `1.4.2`): + +```ts trigger.config.ts +import { defineConfig } from "@trigger.dev/sdk"; + +export default defineConfig({ + project: "", + // Your other config settings... + runtime: "bun-1.4", +}); +``` + + + On Bun 1.3.x (`bun` and `bun-1.3`), `fetch` aborts any request that receives no bytes for 300 + seconds with `TimeoutError: The operation timed out.`, even if you set a longer `timeout` or + `AbortSignal`. A long, non-streaming call, such as an LLM request that returns nothing until it + finishes, fails at exactly 5 minutes. Bun 1.4 does not have this limit, so use `bun-1.4` for + tasks that make such calls. + + +The `bun-1.3` and `bun-1.4` images don't include Node.js, so a task that spawns a `node` process +needs to stay on `runtime: "bun"`, whose image does. + ## Default machine You can specify the default machine for all tasks in your project: diff --git a/docs/guides/frameworks/bun.mdx b/docs/guides/frameworks/bun.mdx index 2e25292e5ee..074d7b6fce3 100644 --- a/docs/guides/frameworks/bun.mdx +++ b/docs/guides/frameworks/bun.mdx @@ -15,14 +15,17 @@ import CliViewRunStep from "/snippets/step-view-run.mdx"; - **Supported Bun version:** Deployed tasks run on Bun 1.3.3. For local development, use Bun 1.3.x - for compatibility. + **Supported Bun version:** With `runtime: "bun"`, deployed tasks run on Bun 1.3.3. To deploy on a + newer release, set `runtime: "bun-1.4"` (Bun 1.4.2) or `runtime: "bun-1.3"` (Bun 1.3.14), see + [Bun versions](/config/config-file#bun-versions). For local development, use the same Bun release + line as your deployed runtime. ## Known issues +- On Bun 1.3.x (`runtime: "bun"` and `"bun-1.3"`), `fetch` aborts any request that receives no bytes for 300 seconds with `TimeoutError: The operation timed out.`, so a long, non-streaming call such as an LLM request fails at exactly 5 minutes. **Workaround:** set `runtime: "bun-1.4"` in `trigger.config.ts`, which does not have this limit. - Certain OpenTelemetry instrumentation will not work with Bun, because Bun does not support Node's `register` hook. This means that some libraries that rely on this hook will not work with Bun. - If Bun is installed via Homebrew (e.g. `/opt/homebrew/bin/bun`), you may see an `ENOENT: spawn /Users//.bun/bin/bun` error because the CLI expects Bun at the default install path. **Workaround:** create a symlink: ```bash diff --git a/docs/self-hosting/overview.mdx b/docs/self-hosting/overview.mdx index 2f7479f2309..29056f73116 100644 --- a/docs/self-hosting/overview.mdx +++ b/docs/self-hosting/overview.mdx @@ -108,15 +108,15 @@ Deploys build on the published `triggerdotdev/node` and `triggerdotdev/bun` Debi DEPLOY_BASE_IMAGES="node-26=registry.example.com/node-fips:26@sha256:<64-character-digest>" ``` -Entries are comma-separated `runtime=image@sha256:`. The runtimes are `node-22`, `node-24`, `node-26` and `bun`, and every image must be pinned by digest. An invalid value prevents the webapp from starting. Projects with `runtime: "node"` in their config resolve to the current default Node runtime (`node-24` today), so set that key for them. With the Helm chart, set the variables through `webapp.extraEnvVars`. +Entries are comma-separated `runtime=image@sha256:`. The runtimes are `node-22`, `node-24`, `node-26`, `bun`, `bun-1.3` and `bun-1.4`, and every image must be pinned by digest. An invalid value prevents the webapp from starting. Projects with `runtime: "node"` in their config resolve to the current default Node runtime (`node-24` today), so set that key for them. With the Helm chart, set the variables through `webapp.extraEnvVars`. Runtimes with an entry build on that image; the others keep the published images. Deploys from CLI versions that cannot apply the images are rejected with an error asking to upgrade, and so are `--native-build`, `--local-bundle` and `--from-bundle` deploys. This is a self-hosting setting and does not apply to Trigger.dev Cloud. You own a custom base image. It must provide: -- `node` on `PATH` at the runtime's major version (for `bun`, both `bun` and `node`, because the final stage starts the app with `dumb-init node`) +- `node` on `PATH` at the runtime's major version (for `bun`, both `bun` and `node`, because the final stage starts the app with `dumb-init node`; for `bun-1.3` and `bun-1.4`, only `bun`, because the final stage starts the app with `dumb-init bun`) - `busybox`, `ca-certificates`, `dumb-init`, `git` and `openssl` -- a `node` user (a `bun` user for the Bun runtime) +- a `node` user (a `bun` user for the Bun runtimes) - glibc, so native modules built in the build stage load at runtime A `DEPLOY_BUILD_BASE_IMAGES` image needs everything the base image provides, plus `python3`, `make` and `g++`. Build extensions that add image instructions are replayed on it. Without an entry, the build stage uses the published build image, except for projects whose build extensions add image instructions: those build from your base image and install the toolchain with `apt-get`, so that base must be Debian-based. To avoid the published images entirely, set both variables. diff --git a/docs/snippets/node-versions.mdx b/docs/snippets/node-versions.mdx index 2c08cd63f0b..27e708b6662 100644 --- a/docs/snippets/node-versions.mdx +++ b/docs/snippets/node-versions.mdx @@ -5,6 +5,8 @@ Trigger.dev runs your deployed tasks on one of these runtimes: - Node.js `node-24` — `24.18.0` - Node.js `node-26` — `26.4.0` - Bun `bun` — `1.3.3` +- Bun `bun-1.3` — `1.3.14` +- Bun `bun-1.4` — `1.4.2` If you don't set a `runtime`, or you set `runtime: "node"`, your tasks run on the current Node.js LTS. That version moves forward as new LTS releases land, so set an explicit version — for example `runtime: "node-24"` — if you need it to stay fixed. @@ -12,7 +14,7 @@ If you don't set a `runtime`, or you set `runtime: "node"`, your tasks run on th import { defineConfig } from "@trigger.dev/sdk"; export default defineConfig({ - // "node", "node-22", "node-24", "node-26" or "bun" + // "node", "node-22", "node-24", "node-26", "bun", "bun-1.3" or "bun-1.4" runtime: "node-24", project: "", }); diff --git a/packages/cli-v3/src/build/plugins.ts b/packages/cli-v3/src/build/plugins.ts index 1f945fa2a2b..0650a1713f8 100644 --- a/packages/cli-v3/src/build/plugins.ts +++ b/packages/cli-v3/src/build/plugins.ts @@ -1,6 +1,6 @@ import * as esbuild from "esbuild"; import { BuildTarget } from "@trigger.dev/core/v3/schemas"; -import { ResolvedConfig } from "@trigger.dev/core/v3/build"; +import { isBunRuntime, ResolvedConfig } from "@trigger.dev/core/v3/build"; import { configPlugin } from "../config.js"; import { logger } from "../utilities/logger.js"; import { bunPlugin } from "../runtimes/bun.js"; @@ -25,7 +25,7 @@ export async function buildPlugins( plugins.push(polyshedPlugin()); - if (resolvedConfig.runtime === "bun") { + if (isBunRuntime(resolvedConfig.runtime)) { plugins.push(bunPlugin()); } diff --git a/packages/cli-v3/src/config.ts b/packages/cli-v3/src/config.ts index a34138cd4c1..12a6dc6e62f 100644 --- a/packages/cli-v3/src/config.ts +++ b/packages/cli-v3/src/config.ts @@ -9,6 +9,7 @@ import type { ResolvedConfig } from "@trigger.dev/core/v3/build"; import { DEFAULT_RUNTIME, deprecatedRuntimeReplacement, + isBunRuntime, isDeprecatedConfigRuntime, resolveBuildRuntime, } from "@trigger.dev/core/v3/build"; @@ -367,10 +368,10 @@ function validateConfig(config: TriggerConfig, warn = true) { ); } - if (config.runtime && config.runtime === "bun") { + if (isBunRuntime(config.runtime)) { warn && prettyWarning( - `The "bun" runtime is currently experimental, and certain features may not work, especially opentelemetry instrumentation of 3rd party packages.` + `The "${config.runtime}" runtime is currently experimental, and certain features may not work, especially opentelemetry instrumentation of 3rd party packages.` ); } } diff --git a/packages/cli-v3/src/deploy/buildImage.test.ts b/packages/cli-v3/src/deploy/buildImage.test.ts index 7339c7d3cb6..4c30f56e539 100644 --- a/packages/cli-v3/src/deploy/buildImage.test.ts +++ b/packages/cli-v3/src/deploy/buildImage.test.ts @@ -54,6 +54,16 @@ const images: Array<[BuildRuntime, string, string]> = [ "triggerdotdev/bun:1.3-node20-bookworm@sha256:25b467196277b9d75a37773ee36d28b65ca81a6f41786f7d7d7f1fad95fb5a31", "triggerdotdev/bun:1.3-node20-bookworm-build@sha256:a2d5e6d1ec25946ca1d86abdd9ffb9c589376df64ee1b490c461607953931245", ], + [ + "bun-1.3", + "triggerdotdev/bun:1.3-bookworm@sha256:991ebbc955a793aaebfa619f9cd000d0c9d370a3b8673b705c8364d23a756717", + "triggerdotdev/bun:1.3-bookworm-build@sha256:4d90ab4b25ae3bd2f4eda468d94a475b2b73977c5be1497df17b18384cf5ea2d", + ], + [ + "bun-1.4", + "triggerdotdev/bun:1.4-bookworm@sha256:8d3fdda4309808b9e12e388a4da20dcac72e67449a277b38d7aacc7c50b8e586", + "triggerdotdev/bun:1.4-bookworm-build@sha256:ae31fe34246e8b8b9725a8c5366c842ccce59742a0e3a57b42f43f1b251e84a9", + ], ]; describe("generateContainerfile", () => { @@ -269,6 +279,27 @@ describe("generateContainerfile", () => { } }); + it.each([ + ["bun", "node"], + ["bun-1.3", "bun"], + ["bun-1.4", "bun"], + ] as [BuildRuntime, string][])( + "starts the %s app with %s, since only plain bun ships a node binary", + async (runtime, binary) => { + const containerfile = await generateContainerfile({ + runtime, + build: {}, + image: undefined, + indexScript: "index.js", + entrypoint: "entrypoint.js", + }); + + expect(containerfile).toContain(`ENTRYPOINT [ "dumb-init", "${binary}", "entrypoint.js" ]`); + expect(containerfile).toContain('RUN [ "bun", "run", "index.js" ]'); + expect(containerfile).toContain("USER bun"); + } + ); + it("pairs every runtime image with its -build variant", () => { for (const runtime of Object.keys(BASE_IMAGE) as BuildRuntime[]) { const baseRef = BASE_IMAGE[runtime].split("@")[0]; diff --git a/packages/cli-v3/src/deploy/buildImage.ts b/packages/cli-v3/src/deploy/buildImage.ts index aa265cf5cd3..40fd42a2a37 100644 --- a/packages/cli-v3/src/deploy/buildImage.ts +++ b/packages/cli-v3/src/deploy/buildImage.ts @@ -711,6 +711,10 @@ export type GenerateContainerfileOptions = { // Prebuilt in base-images/; both maps must be bumped together, from one publish run export const BASE_IMAGE: Record = { bun: "triggerdotdev/bun:1.3-node20-bookworm@sha256:25b467196277b9d75a37773ee36d28b65ca81a6f41786f7d7d7f1fad95fb5a31", + "bun-1.3": + "triggerdotdev/bun:1.3-bookworm@sha256:991ebbc955a793aaebfa619f9cd000d0c9d370a3b8673b705c8364d23a756717", + "bun-1.4": + "triggerdotdev/bun:1.4-bookworm@sha256:8d3fdda4309808b9e12e388a4da20dcac72e67449a277b38d7aacc7c50b8e586", node: "triggerdotdev/node:24-bookworm@sha256:d2d0c01822409f6d2de1cc69a9e718424048fa12fc64b223dfa84f6db44d0ffd", "node-22": "triggerdotdev/node:22-bookworm@sha256:3d1b59a1d50c3df713078a7b18386441cf7fdbaeea6da799247df5a2e180bdd5", @@ -722,6 +726,10 @@ export const BASE_IMAGE: Record = { export const BUILD_IMAGE: Record = { bun: "triggerdotdev/bun:1.3-node20-bookworm-build@sha256:a2d5e6d1ec25946ca1d86abdd9ffb9c589376df64ee1b490c461607953931245", + "bun-1.3": + "triggerdotdev/bun:1.3-bookworm-build@sha256:4d90ab4b25ae3bd2f4eda468d94a475b2b73977c5be1497df17b18384cf5ea2d", + "bun-1.4": + "triggerdotdev/bun:1.4-bookworm-build@sha256:ae31fe34246e8b8b9725a8c5366c842ccce59742a0e3a57b42f43f1b251e84a9", node: "triggerdotdev/node:24-bookworm-build@sha256:19322289508ae9b4be0b769acac179637e4b57d363844682f4b116feb951267d", "node-22": "triggerdotdev/node:22-bookworm-build@sha256:acc6f0143021f532b601bf9fa2cd7745b07612358f94acb8e1cd864468320a81", @@ -769,7 +777,9 @@ export async function generateContainerfile(options: GenerateContainerfileOption case "node-26": { return await generateNodeContainerfile(options); } - case "bun": { + case "bun": + case "bun-1.3": + case "bun-1.4": { return await generateBunContainerfile(options); } } @@ -857,6 +867,9 @@ async function generateBunContainerfile(options: GenerateContainerfileOptions) { const { baseImage, buildStage, buildArgs, buildEnvVars, postInstallCommands, customization } = parseGenerateOptions(options); + // Only plain "bun" is on the node + bun image; the versioned runtimes have no node binary + const entrypointBinary = options.runtime === "bun" ? "node" : "bun"; + return `# syntax=docker/dockerfile:1 # check=skip=SecretsUsedInArgOrEnv FROM ${baseImage} AS base @@ -951,7 +964,7 @@ COPY --from=code --chown=bun:bun /app ./ # Copy the index.json file from the indexer stage COPY --from=indexer --chown=bun:bun /app/index.json ./ -ENTRYPOINT [ "dumb-init", "node", "${options.entrypoint}" ] +ENTRYPOINT [ "dumb-init", "${entrypointBinary}", "${options.entrypoint}" ] CMD [] `; } diff --git a/packages/core/src/v3/build/runtime.test.ts b/packages/core/src/v3/build/runtime.test.ts index 6ce7321192c..ece6322d31f 100644 --- a/packages/core/src/v3/build/runtime.test.ts +++ b/packages/core/src/v3/build/runtime.test.ts @@ -1,6 +1,12 @@ import { describe, expect, it } from "vitest"; import { BuildManifest, BuildRuntime, ConfigRuntime, WorkerManifest } from "../schemas/build.js"; -import { isDeprecatedConfigRuntime, resolveBuildRuntime } from "./runtime.js"; +import { + binaryForRuntime, + execOptionsForRuntime, + isBunRuntime, + isDeprecatedConfigRuntime, + resolveBuildRuntime, +} from "./runtime.js"; describe("runtime configuration", () => { it.each([ @@ -11,6 +17,8 @@ describe("runtime configuration", () => { "experimental-node-24", "experimental-node-26", "bun", + "bun-1.3", + "bun-1.4", ] as const)("accepts %s as a public config runtime", (runtime) => { expect(ConfigRuntime.parse(runtime)).toBe(runtime); }); @@ -23,10 +31,44 @@ describe("runtime configuration", () => { ["node-24", "node-24"], ["node-26", "node-26"], ["bun", "bun"], + ["bun-1.3", "bun-1.3"], + ["bun-1.4", "bun-1.4"], ] as const)("normalizes %s to %s", (runtime, expected) => { expect(resolveBuildRuntime(runtime)).toBe(expected); }); + it.each(["bun", "bun-1.3", "bun-1.4"] as const)( + "accepts %s in the internal schemas and runs it with the bun binary", + (runtime) => { + expect(BuildRuntime.safeParse(runtime).success).toBe(true); + expect(BuildManifest.shape.runtime.safeParse(runtime).success).toBe(true); + expect(WorkerManifest.shape.runtime.safeParse(runtime).success).toBe(true); + expect(binaryForRuntime(runtime)).toBe("bun"); + expect(execOptionsForRuntime(runtime, {})).toBe(""); + expect(isBunRuntime(runtime)).toBe(true); + } + ); + + it.each(["node", "node-24", undefined, null, ""])( + "does not treat %s as a bun runtime", + (runtime) => { + expect(isBunRuntime(runtime)).toBe(false); + } + ); + + it.each(["bun-1.2", "bun-1.5", "bun-2", "bun-latest"])( + "rejects unsupported bun version %s", + (runtime) => { + expect(ConfigRuntime.safeParse(runtime).success).toBe(false); + expect(BuildRuntime.safeParse(runtime).success).toBe(false); + expect(() => resolveBuildRuntime(runtime)).toThrowError( + new RegExp( + `Unsupported runtime "${runtime}" in trigger\\.config\\. Supported runtimes:.*bun-1\\.4` + ) + ); + } + ); + it("normalizes an omitted runtime to node-24", () => { expect(resolveBuildRuntime(undefined)).toBe("node-24"); }); diff --git a/packages/core/src/v3/build/runtime.ts b/packages/core/src/v3/build/runtime.ts index f781b38ab49..5f13bd66161 100644 --- a/packages/core/src/v3/build/runtime.ts +++ b/packages/core/src/v3/build/runtime.ts @@ -58,6 +58,11 @@ export function resolveBuildRuntime(runtime: unknown): BuildRuntime { } } +/** True for every Bun runtime ("bun", "bun-1.3", "bun-1.4"). */ +export function isBunRuntime(runtime: string | null | undefined): boolean { + return runtime?.startsWith("bun") ?? false; +} + export function binaryForRuntime(runtime: BuildRuntime): string { switch (runtime) { case "node": @@ -66,6 +71,8 @@ export function binaryForRuntime(runtime: BuildRuntime): string { case "node-26": return "node"; case "bun": + case "bun-1.3": + case "bun-1.4": return "bun"; default: throw new Error(`Unsupported runtime ${runtime}`); @@ -80,6 +87,8 @@ export function execPathForRuntime(runtime: BuildRuntime): string { case "node-26": return process.execPath; case "bun": + case "bun-1.3": + case "bun-1.4": if (typeof process.env.BUN_INSTALL === "string") { return join(process.env.BUN_INSTALL, "bin", "bun"); } @@ -129,7 +138,9 @@ export function execOptionsForRuntime( return dedupFlags(flags); } - case "bun": { + case "bun": + case "bun-1.3": + case "bun-1.4": { return ""; } } diff --git a/packages/core/src/v3/schemas/build.ts b/packages/core/src/v3/schemas/build.ts index b966313ae7e..c3722e2c397 100644 --- a/packages/core/src/v3/schemas/build.ts +++ b/packages/core/src/v3/schemas/build.ts @@ -31,11 +31,21 @@ export const ConfigRuntime = z.enum([ "experimental-node-24", "experimental-node-26", "bun", + "bun-1.3", + "bun-1.4", ]); export type ConfigRuntime = z.infer; -export const BuildRuntime = z.enum(["node", "node-22", "node-24", "node-26", "bun"]); +export const BuildRuntime = z.enum([ + "node", + "node-22", + "node-24", + "node-26", + "bun", + "bun-1.3", + "bun-1.4", +]); export type BuildRuntime = z.infer; diff --git a/packages/rsc/src/build.ts b/packages/rsc/src/build.ts index 96ccb9710b9..cf4b6cb7f68 100644 --- a/packages/rsc/src/build.ts +++ b/packages/rsc/src/build.ts @@ -1,4 +1,4 @@ -import type { BuildExtension } from "@trigger.dev/core/v3/build"; +import { isBunRuntime, type BuildExtension } from "@trigger.dev/core/v3/build"; import { sourceDir } from "./sourceDir.js"; export type RSCExtensionOptions = { @@ -89,8 +89,9 @@ export function rscExtension(options?: RSCExtensionOptions): BuildExtension { }); build.onResolve({ filter: /^react-dom\/server$/ }, (args) => { - const condition = - context.config.runtime === "bun" ? "bun" : (options?.reactDomEnvironment ?? "node"); + const condition = isBunRuntime(context.config.runtime) + ? "bun" + : (options?.reactDomEnvironment ?? "node"); context.logger.debug("Resolving react-dom/server", { args, condition });