From 61df28dbc91b7c9f358ebea329d7c23f5428777b Mon Sep 17 00:00:00 2001 From: Peter Wielander Date: Thu, 23 Apr 2026 14:17:02 -0700 Subject: [PATCH 1/3] Add `sourcemap` option to builders to allow disabling step sourcemap Signed-off-by: Peter Wielander --- .changeset/sourcemap-config-option.md | 10 +++++++ .../workflow-next/with-workflow.mdx | 2 ++ docs/content/docs/getting-started/astro.mdx | 6 +++++ docs/content/docs/getting-started/nestjs.mdx | 6 +++++ docs/content/docs/getting-started/nitro.mdx | 22 +++++++++++++++ .../docs/getting-started/sveltekit.mdx | 6 +++++ packages/astro/src/builder.ts | 4 ++- packages/astro/src/plugin.ts | 19 ++++++++++--- packages/builders/src/base-builder.ts | 27 ++++++++++++++++--- packages/builders/src/config-helpers.ts | 2 ++ packages/builders/src/types.ts | 12 +++++++++ packages/nest/src/builder.ts | 7 +++++ packages/next/src/index.ts | 7 +++++ packages/nitro/src/builders.ts | 2 ++ packages/nitro/src/types.ts | 8 ++++++ packages/sveltekit/src/builder.ts | 1 + packages/sveltekit/src/plugin.ts | 13 +++++++-- 17 files changed, 144 insertions(+), 10 deletions(-) create mode 100644 .changeset/sourcemap-config-option.md diff --git a/.changeset/sourcemap-config-option.md b/.changeset/sourcemap-config-option.md new file mode 100644 index 0000000000..d8073cd6da --- /dev/null +++ b/.changeset/sourcemap-config-option.md @@ -0,0 +1,10 @@ +--- +"@workflow/builders": minor +"@workflow/nitro": minor +"@workflow/nest": minor +"@workflow/next": minor +"@workflow/sveltekit": minor +"@workflow/astro": minor +--- + +Add `sourcemap` option (`boolean | 'inline' | 'disabled'`) to disable inline source maps in workflow bundles. Defaults unchanged. Exposed per framework: `nitro.options.workflow.sourcemap`, `NestBuilderOptions.sourcemap`, `withWorkflow({ workflows: { sourcemap } })`, and the `sourcemap` option on `workflowPlugin()` for SvelteKit/Astro. diff --git a/docs/content/docs/api-reference/workflow-next/with-workflow.mdx b/docs/content/docs/api-reference/workflow-next/with-workflow.mdx index 85090227d0..8e4dab753a 100644 --- a/docs/content/docs/api-reference/workflow-next/with-workflow.mdx +++ b/docs/content/docs/api-reference/workflow-next/with-workflow.mdx @@ -63,6 +63,7 @@ export default withWorkflow(nextConfig, { local: { port: 4000, }, + sourcemap: "inline", }, }); ``` @@ -71,6 +72,7 @@ export default withWorkflow(nextConfig, { | --- | --- | --- | --- | | `workflows.lazyDiscovery` | `boolean` | `false` | When `true`, defers workflow discovery until files are requested instead of scanning eagerly at startup. Useful for large projects where startup time matters. | | `workflows.local.port` | `number` | — | Overrides the `PORT` environment variable for local development. Has no effect when deployed to Vercel. | +| `workflows.sourcemap` | `boolean \| 'inline' \| 'disabled'` | `'inline'` | Controls inline source maps on the step and workflow bundles. Set to `'disabled'` (or `false`) to omit them for smaller bundles, at the cost of workflow VM stack traces pointing at generated code instead of your source files. | The `workflows.local` options only affect local development. When deployed to Vercel, the runtime ignores `local` settings and uses the Vercel world automatically. diff --git a/docs/content/docs/getting-started/astro.mdx b/docs/content/docs/getting-started/astro.mdx index 37012bc810..bf0681efad 100644 --- a/docs/content/docs/getting-started/astro.mdx +++ b/docs/content/docs/getting-started/astro.mdx @@ -51,6 +51,12 @@ export default defineConfig({ }); ``` +`workflow()` accepts an options object: + +| Option | Type | Default | Description | +| --- | --- | --- | --- | +| `sourcemap` | `boolean \| 'inline' \| 'disabled'` | `'inline'` | Controls inline source maps on the step and workflow bundles. Set to `'disabled'` (or `false`) to omit them for smaller bundles, at the cost of workflow VM stack traces pointing at generated code instead of your source files. | + diff --git a/docs/content/docs/getting-started/nestjs.mdx b/docs/content/docs/getting-started/nestjs.mdx index afe193c0e9..cbc1783840 100644 --- a/docs/content/docs/getting-started/nestjs.mdx +++ b/docs/content/docs/getting-started/nestjs.mdx @@ -386,6 +386,12 @@ WorkflowModule.forRoot({ // Only used when moduleType is 'commonjs' // Should match the outDir in your tsconfig.json distDir: 'dist', + + // Inline source maps on step and workflow bundles (default: 'inline'). + // Set to 'disabled' (or false) to omit source maps for smaller bundles, + // at the cost of workflow VM stack traces pointing at generated code + // instead of your source files. + sourcemap: 'inline', }); ``` diff --git a/docs/content/docs/getting-started/nitro.mdx b/docs/content/docs/getting-started/nitro.mdx index 688b965ebe..44bc2fd246 100644 --- a/docs/content/docs/getting-started/nitro.mdx +++ b/docs/content/docs/getting-started/nitro.mdx @@ -46,6 +46,28 @@ export default defineConfig({ ``` +### Module options + +The `workflow/nitro` module reads its options from `workflow` on your Nitro config. + +```typescript title="nitro.config.ts" lineNumbers +import { defineConfig } from "nitro"; + +export default defineConfig({ + modules: ["workflow/nitro"], + workflow: { + runtime: "nodejs22.x", + sourcemap: "inline", + }, +}); +``` + +| Option | Type | Default | Description | +| --- | --- | --- | --- | +| `dirs` | `string[]` | — | Directories to scan for workflows and steps. By default, `workflows/` is scanned from the project root and all layer source directories. | +| `runtime` | `string` | `'nodejs22.x'` | Node.js runtime version for Vercel Functions (e.g. `'nodejs22.x'`, `'nodejs24.x'`). | +| `sourcemap` | `boolean \| 'inline' \| 'disabled'` | `'inline'` | Controls inline source maps on the step and workflow bundles. Set to `'disabled'` (or `false`) to omit them for smaller bundles, at the cost of workflow VM stack traces pointing at generated code instead of your source files. | + diff --git a/docs/content/docs/getting-started/sveltekit.mdx b/docs/content/docs/getting-started/sveltekit.mdx index 9dd77e158b..ec527d78ad 100644 --- a/docs/content/docs/getting-started/sveltekit.mdx +++ b/docs/content/docs/getting-started/sveltekit.mdx @@ -46,6 +46,12 @@ export default defineConfig({ }); ``` +`workflowPlugin()` accepts an options object: + +| Option | Type | Default | Description | +| --- | --- | --- | --- | +| `sourcemap` | `boolean \| 'inline' \| 'disabled'` | `'inline'` | Controls inline source maps on the step and workflow bundles. Set to `'disabled'` (or `false`) to omit them for smaller bundles, at the cost of workflow VM stack traces pointing at generated code instead of your source files. | + diff --git a/packages/astro/src/builder.ts b/packages/astro/src/builder.ts index d13cae3f03..236c9be952 100644 --- a/packages/astro/src/builder.ts +++ b/packages/astro/src/builder.ts @@ -24,7 +24,7 @@ const WORKFLOW_ROUTES = [ ]; export class LocalBuilder extends BaseBuilder { - constructor() { + constructor(options?: { sourcemap?: boolean | 'inline' | 'disabled' }) { super({ dirs: ['src/pages', 'src/workflows'], buildTarget: 'astro' as const, @@ -33,6 +33,7 @@ export class LocalBuilder extends BaseBuilder { webhookBundlePath: '', // unused in base workingDir: process.cwd(), debugFilePrefix: '_', // Prefix with underscore so Astro ignores debug files + sourcemap: options?.sourcemap, }); } @@ -232,6 +233,7 @@ export class VercelBuilder extends VercelBuildOutputAPIBuilder { workingDir, dirs: ['src/pages', 'src/workflows'], runtime: config?.runtime, + sourcemap: config?.sourcemap, }), buildTarget: 'vercel-build-output-api', debugFilePrefix: '_', diff --git a/packages/astro/src/plugin.ts b/packages/astro/src/plugin.ts index 25a0847a4a..54e38cc9c5 100644 --- a/packages/astro/src/plugin.ts +++ b/packages/astro/src/plugin.ts @@ -4,8 +4,19 @@ import { workflowHotUpdatePlugin } from '@workflow/vite'; import type { AstroIntegration, HookParameters } from 'astro'; import { LocalBuilder, VercelBuilder } from './builder.js'; -export function workflowPlugin(): AstroIntegration { - const builder = new LocalBuilder(); +export interface WorkflowPluginOptions { + /** + * Controls whether inline source maps are emitted for workflow bundles. + * Defaults to `'inline'`. Set to `'disabled'` (or `false`) to omit source + * maps for smaller bundles at the cost of stack trace readability. + */ + sourcemap?: boolean | 'inline' | 'disabled'; +} + +export function workflowPlugin( + options: WorkflowPluginOptions = {} +): AstroIntegration { + const builder = new LocalBuilder({ sourcemap: options.sourcemap }); const enqueue = createBuildQueue(); return { @@ -40,7 +51,9 @@ export function workflowPlugin(): AstroIntegration { }, 'astro:build:done': async () => { if (process.env.VERCEL_DEPLOYMENT_ID) { - const vercelBuilder = new VercelBuilder(); + const vercelBuilder = new VercelBuilder({ + sourcemap: options.sourcemap, + }); await vercelBuilder.build(); } }, diff --git a/packages/builders/src/base-builder.ts b/packages/builders/src/base-builder.ts index b3678f1adf..4bec45b680 100644 --- a/packages/builders/src/base-builder.ts +++ b/packages/builders/src/base-builder.ts @@ -26,6 +26,19 @@ const enhancedResolve = promisify(enhancedResolveOriginal); const EMIT_SOURCEMAPS_FOR_DEBUGGING = process.env.WORKFLOW_EMIT_SOURCEMAPS_FOR_DEBUGGING === '1'; +/** + * Normalize the user-facing `sourcemap` config into a boolean indicating + * whether inline sourcemaps should be emitted. Undefined means "use the + * caller's default" and is returned as undefined so callers can decide. + */ +function resolveSourcemap( + sourcemap: boolean | 'inline' | 'disabled' | undefined +): boolean | undefined { + if (sourcemap === undefined) return undefined; + if (sourcemap === true || sourcemap === 'inline') return true; + return false; +} + /** * Normalize an array of file paths by appending the `realpath()` of each entry * (to handle symlinks, e.g. pnpm/workspace layouts) and deduplicating. @@ -568,7 +581,8 @@ export abstract class BaseBuilder { // Steps execute in Node.js context and inline sourcemaps ensure we get // meaningful stack traces with proper file names and line numbers when errors // occur in deeply nested function calls across multiple files. - sourcemap: 'inline', + sourcemap: + (resolveSourcemap(this.config.sourcemap) ?? true) ? 'inline' : false, plugins: [ // Handle pseudo-packages like 'server-only' and 'client-only' by providing // empty modules. Must run first to intercept these before other resolution. @@ -772,7 +786,8 @@ export abstract class BaseBuilder { // Inline source maps for better stack traces in workflow VM execution. // This intermediate bundle is executed via runInContext() in a VM, so we need // inline source maps to get meaningful stack traces instead of "evalmachine.". - sourcemap: 'inline', + sourcemap: + (resolveSourcemap(this.config.sourcemap) ?? true) ? 'inline' : false, // Use tsconfig for path alias resolution. // For symlinked configs this uses tsconfigRaw to preserve cwd-relative aliases. ...esbuildTsconfigOptions, @@ -944,7 +959,9 @@ export const POST = workflowEntrypoint(workflowCode);`; outfile, // Source maps for the final workflow bundle wrapper (not important since this code // doesn't run in the VM - only the intermediate bundle sourcemap is relevant) - sourcemap: EMIT_SOURCEMAPS_FOR_DEBUGGING, + sourcemap: + resolveSourcemap(this.config.sourcemap) ?? + EMIT_SOURCEMAPS_FOR_DEBUGGING, absWorkingDir: this.config.workingDir, bundle: true, format, @@ -1213,7 +1230,9 @@ export const OPTIONS = handler;`; '.mjs', '.cjs', ], - sourcemap: EMIT_SOURCEMAPS_FOR_DEBUGGING, + sourcemap: + resolveSourcemap(this.config.sourcemap) ?? + EMIT_SOURCEMAPS_FOR_DEBUGGING, mainFields: ['module', 'main'], // Don't externalize anything - bundle everything including workflow packages external: [], diff --git a/packages/builders/src/config-helpers.ts b/packages/builders/src/config-helpers.ts index 94b50aa5a0..8fd1e091cd 100644 --- a/packages/builders/src/config-helpers.ts +++ b/packages/builders/src/config-helpers.ts @@ -96,6 +96,7 @@ export function createBaseBuilderConfig(options: { watch?: boolean; externalPackages?: string[]; runtime?: string; + sourcemap?: boolean | 'inline' | 'disabled'; }): Omit { return { dirs: options.dirs ?? ['workflows'], @@ -107,5 +108,6 @@ export function createBaseBuilderConfig(options: { webhookBundlePath: '', // Not used by base builder methods externalPackages: options.externalPackages, runtime: options.runtime, + sourcemap: options.sourcemap, }; } diff --git a/packages/builders/src/types.ts b/packages/builders/src/types.ts index 688b14826e..2cfd10f825 100644 --- a/packages/builders/src/types.ts +++ b/packages/builders/src/types.ts @@ -48,6 +48,18 @@ interface BaseWorkflowConfig { // Node.js runtime version for Vercel Functions (e.g., "nodejs22.x", "nodejs24.x") runtime?: string; + + /** + * Controls whether inline source maps are emitted for the step bundle and + * the intermediate workflow bundle. + * + * - `true` / `'inline'` (default): emit inline source maps. Produces readable + * stack traces for step errors and workflow VM errors. + * - `false` / `'disabled'`: omit source maps. Produces smaller bundles at the + * cost of stack traces that reference generated code (e.g. the workflow VM + * bundle will show `evalmachine.` instead of user file paths). + */ + sourcemap?: boolean | 'inline' | 'disabled'; } /** diff --git a/packages/nest/src/builder.ts b/packages/nest/src/builder.ts index c1e7a5b488..d6670e55d1 100644 --- a/packages/nest/src/builder.ts +++ b/packages/nest/src/builder.ts @@ -40,6 +40,12 @@ export interface NestBuilderOptions { * @default 'dist' */ distDir?: string; + /** + * Controls whether inline source maps are emitted for workflow bundles. + * Defaults to `'inline'`. Set to `'disabled'` (or `false`) to omit source + * maps for smaller bundles at the cost of stack trace readability. + */ + sourcemap?: boolean | 'inline' | 'disabled'; } export class NestLocalBuilder extends BaseBuilder { @@ -58,6 +64,7 @@ export class NestLocalBuilder extends BaseBuilder { workingDir, watch: options.watch ?? false, dirs, + sourcemap: options.sourcemap, }), // Use 'standalone' as base target - we handle the specific bundling ourselves buildTarget: 'standalone', diff --git a/packages/next/src/index.ts b/packages/next/src/index.ts index f16c45967e..2b217449b0 100644 --- a/packages/next/src/index.ts +++ b/packages/next/src/index.ts @@ -58,6 +58,12 @@ export function withWorkflow( local?: { port?: number; }; + /** + * Controls whether inline source maps are emitted for workflow bundles. + * Defaults to `'inline'`. Set to `'disabled'` (or `false`) to omit source + * maps for smaller bundles at the cost of stack trace readability. + */ + sourcemap?: boolean | 'inline' | 'disabled'; }; } = {} ) { @@ -131,6 +137,7 @@ export function withWorkflow( workflowsBundlePath: '', // not used in base stepsBundlePath: '', // not used in base webhookBundlePath: '', // node used in base + sourcemap: workflows?.sourcemap, suppressCreateWorkflowsBundleLogs: useDeferredBuilder, suppressCreateWorkflowsBundleWarnings: useDeferredBuilder, suppressCreateWebhookBundleLogs: useDeferredBuilder, diff --git a/packages/nitro/src/builders.ts b/packages/nitro/src/builders.ts index cd87a308b6..061e9af958 100644 --- a/packages/nitro/src/builders.ts +++ b/packages/nitro/src/builders.ts @@ -15,6 +15,7 @@ export class VercelBuilder extends VercelBuildOutputAPIBuilder { workingDir: nitro.options.rootDir, dirs: ['.'], // Different apps that use nitro have different directories runtime: nitro.options.workflow?.runtime, + sourcemap: nitro.options.workflow?.sourcemap, }), buildTarget: 'vercel-build-output-api', }); @@ -41,6 +42,7 @@ export class LocalBuilder extends BaseBuilder { workingDir: nitro.options.rootDir, watch: nitro.options.dev, dirs: ['.'], // Different apps that use nitro have different directories + sourcemap: nitro.options.workflow?.sourcemap, }), buildTarget: 'next', // Placeholder, not actually used }); diff --git a/packages/nitro/src/types.ts b/packages/nitro/src/types.ts index d8fd832f52..a8a2db057b 100644 --- a/packages/nitro/src/types.ts +++ b/packages/nitro/src/types.ts @@ -21,6 +21,14 @@ export interface ModuleOptions { * @example "nodejs24.x" */ runtime?: string; + + /** + * Controls whether inline source maps are emitted for workflow bundles. + * Defaults to `'inline'`. Set to `'disabled'` (or `false`) to omit source + * maps in exchange for smaller bundles, at the cost of workflow VM stack + * traces pointing at generated code instead of user files. + */ + sourcemap?: boolean | 'inline' | 'disabled'; } declare module 'nitro/types' { diff --git a/packages/sveltekit/src/builder.ts b/packages/sveltekit/src/builder.ts index 3a0a988af6..c7e4521319 100644 --- a/packages/sveltekit/src/builder.ts +++ b/packages/sveltekit/src/builder.ts @@ -34,6 +34,7 @@ export class SvelteKitBuilder extends BaseBuilder { webhookBundlePath: '', // unused in base workingDir, externalPackages: [...SVELTEKIT_VIRTUAL_MODULES], + sourcemap: config?.sourcemap, }); } diff --git a/packages/sveltekit/src/plugin.ts b/packages/sveltekit/src/plugin.ts index f12cd5faa7..652dc785e3 100644 --- a/packages/sveltekit/src/plugin.ts +++ b/packages/sveltekit/src/plugin.ts @@ -4,8 +4,17 @@ import { workflowHotUpdatePlugin } from '@workflow/vite'; import type { Plugin } from 'vite'; import { SvelteKitBuilder } from './builder.js'; -export function workflowPlugin(): Plugin[] { - const builder = new SvelteKitBuilder(); +export interface WorkflowPluginOptions { + /** + * Controls whether inline source maps are emitted for workflow bundles. + * Defaults to `'inline'`. Set to `'disabled'` (or `false`) to omit source + * maps for smaller bundles at the cost of stack trace readability. + */ + sourcemap?: boolean | 'inline' | 'disabled'; +} + +export function workflowPlugin(options: WorkflowPluginOptions = {}): Plugin[] { + const builder = new SvelteKitBuilder({ sourcemap: options.sourcemap }); const enqueue = createBuildQueue(); return [ From 0dc9a182fbe261d466a3051cecfaa29e1ab7a707 Mon Sep 17 00:00:00 2001 From: Peter Wielander Date: Thu, 23 Apr 2026 14:47:06 -0700 Subject: [PATCH 2/3] Adopt esbuild sourcemap vocabulary and add WORKFLOW_SOURCEMAP env var Replace the bespoke `boolean | 'inline' | 'disabled'` type with esbuild's full `SourcemapMode` vocabulary (adds `'linked'`, `'external'`, `'both'`) so users can ship sourcemaps to observability tooling without bloating the function bundle. Add a `WORKFLOW_SOURCEMAP` env var as a cross-framework override; config wins over env, env wins over the per-bundle default. Flip `shouldAddSourcemapSupport` to track `sourcemapsEnabled` on the Vercel step function so disabling sourcemaps also drops the runtime shim. Co-Authored-By: Claude Opus 4.7 (1M context) --- .changeset/sourcemap-config-option.md | 8 +- .../workflow-next/with-workflow.mdx | 24 ++- docs/content/docs/getting-started/astro.mdx | 2 +- docs/content/docs/getting-started/nestjs.mdx | 10 +- docs/content/docs/getting-started/nitro.mdx | 2 +- .../docs/getting-started/sveltekit.mdx | 2 +- packages/astro/src/builder.ts | 4 +- packages/astro/src/plugin.ts | 9 +- packages/builders/src/base-builder.ts | 84 +++++++--- packages/builders/src/config-helpers.ts | 4 +- .../builders/src/resolve-sourcemap.test.ts | 151 ++++++++++++++++++ packages/builders/src/types.ts | 35 +++- .../builders/src/vercel-build-output-api.ts | 5 +- packages/nest/src/builder.ts | 9 +- packages/next/src/index.ts | 10 +- packages/nitro/src/types.ts | 16 +- packages/sveltekit/src/plugin.ts | 9 +- 17 files changed, 321 insertions(+), 63 deletions(-) create mode 100644 packages/builders/src/resolve-sourcemap.test.ts diff --git a/.changeset/sourcemap-config-option.md b/.changeset/sourcemap-config-option.md index d8073cd6da..b9ec767a64 100644 --- a/.changeset/sourcemap-config-option.md +++ b/.changeset/sourcemap-config-option.md @@ -7,4 +7,10 @@ "@workflow/astro": minor --- -Add `sourcemap` option (`boolean | 'inline' | 'disabled'`) to disable inline source maps in workflow bundles. Defaults unchanged. Exposed per framework: `nitro.options.workflow.sourcemap`, `NestBuilderOptions.sourcemap`, `withWorkflow({ workflows: { sourcemap } })`, and the `sourcemap` option on `workflowPlugin()` for SvelteKit/Astro. +Add `sourcemap` option to builders for disabling or customising source map emission on generated workflow bundles. Accepts the same values as esbuild's `sourcemap` option: `true`, `false`, `'inline'`, `'linked'`, `'external'`, `'both'`. Can also be set via the `WORKFLOW_SOURCEMAP` environment variable. + +Setting `sourcemap: false` drops inline source maps from the step, workflow and webhook bundles, and skips the source-map-support runtime shim on the Vercel step function — helpful for staying under the Vercel 250MB function size limit. + +Exposed per framework: `nitro.options.workflow.sourcemap`, `NestBuilderOptions.sourcemap`, `withWorkflow({ workflows: { sourcemap } })`, and the `sourcemap` option on `workflowPlugin()` for SvelteKit and Astro. + +Minor semantics change: when the `sourcemap` option (or `WORKFLOW_SOURCEMAP`) is set explicitly, it now applies to **all** generated bundles. Previously, the final workflow wrapper and webhook bundles could only be toggled via the legacy `WORKFLOW_EMIT_SOURCEMAPS_FOR_DEBUGGING=1` env var, which continues to work but is narrower in scope. diff --git a/docs/content/docs/api-reference/workflow-next/with-workflow.mdx b/docs/content/docs/api-reference/workflow-next/with-workflow.mdx index 8e4dab753a..7f07e7d080 100644 --- a/docs/content/docs/api-reference/workflow-next/with-workflow.mdx +++ b/docs/content/docs/api-reference/workflow-next/with-workflow.mdx @@ -63,7 +63,7 @@ export default withWorkflow(nextConfig, { local: { port: 4000, }, - sourcemap: "inline", + sourcemap: false, }, }); ``` @@ -72,7 +72,27 @@ export default withWorkflow(nextConfig, { | --- | --- | --- | --- | | `workflows.lazyDiscovery` | `boolean` | `false` | When `true`, defers workflow discovery until files are requested instead of scanning eagerly at startup. Useful for large projects where startup time matters. | | `workflows.local.port` | `number` | — | Overrides the `PORT` environment variable for local development. Has no effect when deployed to Vercel. | -| `workflows.sourcemap` | `boolean \| 'inline' \| 'disabled'` | `'inline'` | Controls inline source maps on the step and workflow bundles. Set to `'disabled'` (or `false`) to omit them for smaller bundles, at the cost of workflow VM stack traces pointing at generated code instead of your source files. | +| `workflows.sourcemap` | `boolean \| 'inline' \| 'linked' \| 'external' \| 'both'` | `'inline'` | Controls source maps on generated workflow bundles. See [Source maps](#source-maps) below. | + +### Source maps + +The step bundle and intermediate workflow bundle default to `'inline'` source maps so that stack traces from step errors and workflow VM errors point at your source files. The `sourcemap` option lets you change that: + +| Value | Behavior | +| --- | --- | +| `true` / `'inline'` | Base64-encode the source map and append it to the bundle (default). | +| `'linked'` | Write a separate `.map` file and add a `sourceMappingURL` comment. | +| `'external'` | Write a separate `.map` file without the comment. | +| `'both'` | Emit both inline and external source maps. | +| `false` | Omit source maps entirely. | + +Setting `sourcemap: false` is the main escape hatch for users hitting the Vercel 250MB function size limit — it drops the inline source map from every bundle and also skips the source-map-support runtime shim on the Vercel step function. The tradeoff is that workflow VM stack traces will reference generated code (e.g. `evalmachine.`) rather than your source files. + + +Setting `sourcemap` explicitly affects **all** generated bundles (steps, workflows, webhook). The legacy `WORKFLOW_EMIT_SOURCEMAPS_FOR_DEBUGGING=1` environment variable is narrower — it only toggles source maps on the final workflow wrapper and webhook bundle (which default to off). It continues to work, but new code should use the `sourcemap` option or the `WORKFLOW_SOURCEMAP` environment variable instead. + + +The option can also be set via the `WORKFLOW_SOURCEMAP` environment variable, which accepts the same values plus `'0'` / `'1'` as aliases for `false` / `true`. Precedence is: explicit config > `WORKFLOW_SOURCEMAP` > per-bundle default. The `workflows.local` options only affect local development. When deployed to Vercel, the runtime ignores `local` settings and uses the Vercel world automatically. diff --git a/docs/content/docs/getting-started/astro.mdx b/docs/content/docs/getting-started/astro.mdx index bf0681efad..03d3f9421e 100644 --- a/docs/content/docs/getting-started/astro.mdx +++ b/docs/content/docs/getting-started/astro.mdx @@ -55,7 +55,7 @@ export default defineConfig({ | Option | Type | Default | Description | | --- | --- | --- | --- | -| `sourcemap` | `boolean \| 'inline' \| 'disabled'` | `'inline'` | Controls inline source maps on the step and workflow bundles. Set to `'disabled'` (or `false`) to omit them for smaller bundles, at the cost of workflow VM stack traces pointing at generated code instead of your source files. | +| `sourcemap` | `boolean \| 'inline' \| 'linked' \| 'external' \| 'both'` | `'inline'` | Controls source maps on generated workflow bundles. Accepts the same values as esbuild's `sourcemap` option. Set to `false` for smaller function bundles (useful for staying under the Vercel 250MB function size limit) at the cost of stack traces pointing at generated code. Can also be set via the `WORKFLOW_SOURCEMAP` environment variable. | diff --git a/docs/content/docs/getting-started/nestjs.mdx b/docs/content/docs/getting-started/nestjs.mdx index cbc1783840..630ba4c579 100644 --- a/docs/content/docs/getting-started/nestjs.mdx +++ b/docs/content/docs/getting-started/nestjs.mdx @@ -387,10 +387,12 @@ WorkflowModule.forRoot({ // Should match the outDir in your tsconfig.json distDir: 'dist', - // Inline source maps on step and workflow bundles (default: 'inline'). - // Set to 'disabled' (or false) to omit source maps for smaller bundles, - // at the cost of workflow VM stack traces pointing at generated code - // instead of your source files. + // Source maps on generated workflow bundles (default: 'inline'). + // Accepts the same values as esbuild's sourcemap option: true, false, + // 'inline', 'linked', 'external', 'both'. Set to false for smaller + // function bundles (useful for staying under the Vercel 250MB function + // size limit) at the cost of stack traces pointing at generated code. + // Can also be set via the WORKFLOW_SOURCEMAP environment variable. sourcemap: 'inline', }); ``` diff --git a/docs/content/docs/getting-started/nitro.mdx b/docs/content/docs/getting-started/nitro.mdx index 44bc2fd246..3c460708b7 100644 --- a/docs/content/docs/getting-started/nitro.mdx +++ b/docs/content/docs/getting-started/nitro.mdx @@ -66,7 +66,7 @@ export default defineConfig({ | --- | --- | --- | --- | | `dirs` | `string[]` | — | Directories to scan for workflows and steps. By default, `workflows/` is scanned from the project root and all layer source directories. | | `runtime` | `string` | `'nodejs22.x'` | Node.js runtime version for Vercel Functions (e.g. `'nodejs22.x'`, `'nodejs24.x'`). | -| `sourcemap` | `boolean \| 'inline' \| 'disabled'` | `'inline'` | Controls inline source maps on the step and workflow bundles. Set to `'disabled'` (or `false`) to omit them for smaller bundles, at the cost of workflow VM stack traces pointing at generated code instead of your source files. | +| `sourcemap` | `boolean \| 'inline' \| 'linked' \| 'external' \| 'both'` | `'inline'` | Controls source maps on generated workflow bundles. Accepts the same values as esbuild's `sourcemap` option. Set to `false` for smaller function bundles (useful for staying under the Vercel 250MB function size limit) at the cost of stack traces pointing at generated code. Can also be set via the `WORKFLOW_SOURCEMAP` environment variable. | diff --git a/docs/content/docs/getting-started/sveltekit.mdx b/docs/content/docs/getting-started/sveltekit.mdx index ec527d78ad..943e8f9410 100644 --- a/docs/content/docs/getting-started/sveltekit.mdx +++ b/docs/content/docs/getting-started/sveltekit.mdx @@ -50,7 +50,7 @@ export default defineConfig({ | Option | Type | Default | Description | | --- | --- | --- | --- | -| `sourcemap` | `boolean \| 'inline' \| 'disabled'` | `'inline'` | Controls inline source maps on the step and workflow bundles. Set to `'disabled'` (or `false`) to omit them for smaller bundles, at the cost of workflow VM stack traces pointing at generated code instead of your source files. | +| `sourcemap` | `boolean \| 'inline' \| 'linked' \| 'external' \| 'both'` | `'inline'` | Controls source maps on generated workflow bundles. Accepts the same values as esbuild's `sourcemap` option. Set to `false` for smaller function bundles (useful for staying under the Vercel 250MB function size limit) at the cost of stack traces pointing at generated code. Can also be set via the `WORKFLOW_SOURCEMAP` environment variable. | diff --git a/packages/astro/src/builder.ts b/packages/astro/src/builder.ts index 236c9be952..4e2e2884a6 100644 --- a/packages/astro/src/builder.ts +++ b/packages/astro/src/builder.ts @@ -24,7 +24,9 @@ const WORKFLOW_ROUTES = [ ]; export class LocalBuilder extends BaseBuilder { - constructor(options?: { sourcemap?: boolean | 'inline' | 'disabled' }) { + constructor(options?: { + sourcemap?: boolean | 'inline' | 'linked' | 'external' | 'both'; + }) { super({ dirs: ['src/pages', 'src/workflows'], buildTarget: 'astro' as const, diff --git a/packages/astro/src/plugin.ts b/packages/astro/src/plugin.ts index 54e38cc9c5..968f5b26c4 100644 --- a/packages/astro/src/plugin.ts +++ b/packages/astro/src/plugin.ts @@ -6,11 +6,12 @@ import { LocalBuilder, VercelBuilder } from './builder.js'; export interface WorkflowPluginOptions { /** - * Controls whether inline source maps are emitted for workflow bundles. - * Defaults to `'inline'`. Set to `'disabled'` (or `false`) to omit source - * maps for smaller bundles at the cost of stack trace readability. + * Controls how source maps are emitted for workflow bundles. Accepts the + * same values as esbuild's `sourcemap` option: `true`/`'inline'` (default), + * `'linked'`, `'external'`, `'both'`, or `false` to omit source maps. Can + * also be set via the `WORKFLOW_SOURCEMAP` environment variable. */ - sourcemap?: boolean | 'inline' | 'disabled'; + sourcemap?: boolean | 'inline' | 'linked' | 'external' | 'both'; } export function workflowPlugin( diff --git a/packages/builders/src/base-builder.ts b/packages/builders/src/base-builder.ts index 4bec45b680..edf673a12b 100644 --- a/packages/builders/src/base-builder.ts +++ b/packages/builders/src/base-builder.ts @@ -18,25 +18,53 @@ import { getImportPath } from './module-specifier.js'; import { createNodeModuleErrorPlugin } from './node-module-esbuild-plugin.js'; import { createPseudoPackagePlugin } from './pseudo-package-esbuild-plugin.js'; import { createSwcPlugin } from './swc-esbuild-plugin.js'; -import type { WorkflowConfig } from './types.js'; +import type { SourcemapMode, WorkflowConfig } from './types.js'; import { extractWorkflowGraphs } from './workflows-extractor.js'; const enhancedResolve = promisify(enhancedResolveOriginal); +/** + * Legacy opt-in for source maps on the final workflow wrapper + webhook + * bundles (which default to off, unlike the step/interim workflow bundles + * that default to inline). Superseded by the `sourcemap` config option and + * the `WORKFLOW_SOURCEMAP` environment variable; kept for back-compat. + */ const EMIT_SOURCEMAPS_FOR_DEBUGGING = process.env.WORKFLOW_EMIT_SOURCEMAPS_FOR_DEBUGGING === '1'; +const VALID_SOURCEMAP_STRINGS = new Set([ + 'inline', + 'linked', + 'external', + 'both', +]); + /** - * Normalize the user-facing `sourcemap` config into a boolean indicating - * whether inline sourcemaps should be emitted. Undefined means "use the - * caller's default" and is returned as undefined so callers can decide. + * Parse the value of the `WORKFLOW_SOURCEMAP` environment variable into a + * `SourcemapMode`. Returns `undefined` if the env var is unset, empty, or + * unrecognized (a warning is emitted for unrecognized values). */ -function resolveSourcemap( - sourcemap: boolean | 'inline' | 'disabled' | undefined -): boolean | undefined { - if (sourcemap === undefined) return undefined; - if (sourcemap === true || sourcemap === 'inline') return true; - return false; +function parseSourcemapEnv( + value: string | undefined +): SourcemapMode | undefined { + if (value === undefined || value === '') return undefined; + switch (value) { + case '0': + case 'false': + return false; + case '1': + case 'true': + return true; + default: + if (VALID_SOURCEMAP_STRINGS.has(value)) { + return value as SourcemapMode; + } + console.warn( + `Ignoring unrecognized WORKFLOW_SOURCEMAP=${value}. ` + + `Expected one of: true, false, 0, 1, inline, linked, external, both.` + ); + return undefined; + } } /** @@ -581,8 +609,7 @@ export abstract class BaseBuilder { // Steps execute in Node.js context and inline sourcemaps ensure we get // meaningful stack traces with proper file names and line numbers when errors // occur in deeply nested function calls across multiple files. - sourcemap: - (resolveSourcemap(this.config.sourcemap) ?? true) ? 'inline' : false, + sourcemap: this.resolveSourcemap('inline'), plugins: [ // Handle pseudo-packages like 'server-only' and 'client-only' by providing // empty modules. Must run first to intercept these before other resolution. @@ -786,8 +813,7 @@ export abstract class BaseBuilder { // Inline source maps for better stack traces in workflow VM execution. // This intermediate bundle is executed via runInContext() in a VM, so we need // inline source maps to get meaningful stack traces instead of "evalmachine.". - sourcemap: - (resolveSourcemap(this.config.sourcemap) ?? true) ? 'inline' : false, + sourcemap: this.resolveSourcemap('inline'), // Use tsconfig for path alias resolution. // For symlinked configs this uses tsconfigRaw to preserve cwd-relative aliases. ...esbuildTsconfigOptions, @@ -959,9 +985,7 @@ export const POST = workflowEntrypoint(workflowCode);`; outfile, // Source maps for the final workflow bundle wrapper (not important since this code // doesn't run in the VM - only the intermediate bundle sourcemap is relevant) - sourcemap: - resolveSourcemap(this.config.sourcemap) ?? - EMIT_SOURCEMAPS_FOR_DEBUGGING, + sourcemap: this.resolveSourcemap(EMIT_SOURCEMAPS_FOR_DEBUGGING), absWorkingDir: this.config.workingDir, bundle: true, format, @@ -1230,9 +1254,7 @@ export const OPTIONS = handler;`; '.mjs', '.cjs', ], - sourcemap: - resolveSourcemap(this.config.sourcemap) ?? - EMIT_SOURCEMAPS_FOR_DEBUGGING, + sourcemap: this.resolveSourcemap(EMIT_SOURCEMAPS_FOR_DEBUGGING), mainFields: ['module', 'main'], // Don't externalize anything - bundle everything including workflow packages external: [], @@ -1348,6 +1370,28 @@ export const OPTIONS = handler;`; ); } + /** + * Resolve the effective source map mode for a given call site. Precedence: + * explicit `sourcemap` config > `WORKFLOW_SOURCEMAP` env var > the call + * site's default. Returned value is passed directly to esbuild's + * `sourcemap` option. + */ + protected resolveSourcemap(defaultMode: SourcemapMode): SourcemapMode { + if (this.config.sourcemap !== undefined) return this.config.sourcemap; + const envMode = parseSourcemapEnv(process.env.WORKFLOW_SOURCEMAP); + if (envMode !== undefined) return envMode; + return defaultMode; + } + + /** + * Whether the resolved source map mode emits any source maps at all. + * Used by consumers like the Vercel builder to decide whether to include + * the source-map-support runtime shim in generated functions. + */ + protected get sourcemapsEnabled(): boolean { + return this.resolveSourcemap(true) !== false; + } + /** * Creates a manifest JSON file containing step/workflow/class metadata * and graph data for visualization. diff --git a/packages/builders/src/config-helpers.ts b/packages/builders/src/config-helpers.ts index 8fd1e091cd..e07975e26c 100644 --- a/packages/builders/src/config-helpers.ts +++ b/packages/builders/src/config-helpers.ts @@ -1,7 +1,7 @@ import { readFile } from 'node:fs/promises'; import { findUp } from 'find-up'; import JSON5 from 'json5'; -import type { WorkflowConfig } from './types.js'; +import type { SourcemapMode, WorkflowConfig } from './types.js'; export interface DecoratorOptions { decorators: boolean; @@ -96,7 +96,7 @@ export function createBaseBuilderConfig(options: { watch?: boolean; externalPackages?: string[]; runtime?: string; - sourcemap?: boolean | 'inline' | 'disabled'; + sourcemap?: SourcemapMode; }): Omit { return { dirs: options.dirs ?? ['workflows'], diff --git a/packages/builders/src/resolve-sourcemap.test.ts b/packages/builders/src/resolve-sourcemap.test.ts new file mode 100644 index 0000000000..63f288d37c --- /dev/null +++ b/packages/builders/src/resolve-sourcemap.test.ts @@ -0,0 +1,151 @@ +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; +import { BaseBuilder } from './base-builder.js'; +import type { SourcemapMode, StandaloneConfig } from './types.js'; + +/** + * Minimal subclass that exposes the protected `resolveSourcemap()` and + * `sourcemapsEnabled` members for testing. + */ +class TestBuilder extends BaseBuilder { + async build(): Promise { + // no-op + } + + public callResolveSourcemap(defaultMode: SourcemapMode): SourcemapMode { + return this.resolveSourcemap(defaultMode); + } + + public get publicSourcemapsEnabled(): boolean { + return this.sourcemapsEnabled; + } +} + +function createBuilder(sourcemap?: SourcemapMode): TestBuilder { + const config: StandaloneConfig = { + buildTarget: 'standalone', + workingDir: '/tmp/workflow-test', + dirs: ['.'], + stepsBundlePath: '', + workflowsBundlePath: '', + webhookBundlePath: '', + sourcemap, + }; + return new TestBuilder(config); +} + +describe('resolveSourcemap', () => { + const originalEnv = process.env.WORKFLOW_SOURCEMAP; + + beforeEach(() => { + delete process.env.WORKFLOW_SOURCEMAP; + }); + + afterEach(() => { + if (originalEnv === undefined) { + delete process.env.WORKFLOW_SOURCEMAP; + } else { + process.env.WORKFLOW_SOURCEMAP = originalEnv; + } + }); + + it('returns the default when no config or env var is set', () => { + const builder = createBuilder(); + expect(builder.callResolveSourcemap('inline')).toBe('inline'); + expect(builder.callResolveSourcemap(false)).toBe(false); + expect(builder.callResolveSourcemap(true)).toBe(true); + }); + + it('prefers explicit config over the default', () => { + expect(createBuilder(false).callResolveSourcemap('inline')).toBe(false); + expect(createBuilder('external').callResolveSourcemap('inline')).toBe( + 'external' + ); + expect(createBuilder('linked').callResolveSourcemap(false)).toBe('linked'); + expect(createBuilder(true).callResolveSourcemap('inline')).toBe(true); + }); + + it('prefers explicit config over environment variable', () => { + process.env.WORKFLOW_SOURCEMAP = 'inline'; + expect(createBuilder(false).callResolveSourcemap('inline')).toBe(false); + expect(createBuilder('external').callResolveSourcemap('inline')).toBe( + 'external' + ); + }); + + it('uses environment variable when config is not set', () => { + process.env.WORKFLOW_SOURCEMAP = 'false'; + expect(createBuilder().callResolveSourcemap('inline')).toBe(false); + + process.env.WORKFLOW_SOURCEMAP = 'true'; + expect(createBuilder().callResolveSourcemap(false)).toBe(true); + + for (const mode of ['inline', 'linked', 'external', 'both'] as const) { + process.env.WORKFLOW_SOURCEMAP = mode; + expect(createBuilder().callResolveSourcemap('inline')).toBe(mode); + } + }); + + it('accepts "0" / "1" as environment variable aliases for false / true', () => { + process.env.WORKFLOW_SOURCEMAP = '0'; + expect(createBuilder().callResolveSourcemap('inline')).toBe(false); + + process.env.WORKFLOW_SOURCEMAP = '1'; + expect(createBuilder().callResolveSourcemap(false)).toBe(true); + }); + + it('falls back to default when env var is empty or unrecognized', () => { + process.env.WORKFLOW_SOURCEMAP = ''; + expect(createBuilder().callResolveSourcemap('inline')).toBe('inline'); + + // Suppress the expected warning + const originalWarn = console.warn; + console.warn = () => {}; + try { + process.env.WORKFLOW_SOURCEMAP = 'nonsense'; + expect(createBuilder().callResolveSourcemap('inline')).toBe('inline'); + } finally { + console.warn = originalWarn; + } + }); +}); + +describe('sourcemapsEnabled', () => { + const originalEnv = process.env.WORKFLOW_SOURCEMAP; + + beforeEach(() => { + delete process.env.WORKFLOW_SOURCEMAP; + }); + + afterEach(() => { + if (originalEnv === undefined) { + delete process.env.WORKFLOW_SOURCEMAP; + } else { + process.env.WORKFLOW_SOURCEMAP = originalEnv; + } + }); + + it('is true by default', () => { + expect(createBuilder().publicSourcemapsEnabled).toBe(true); + }); + + it('is false when config sourcemap is false', () => { + expect(createBuilder(false).publicSourcemapsEnabled).toBe(false); + }); + + it('is true for any non-false config value', () => { + for (const mode of [ + true, + 'inline', + 'linked', + 'external', + 'both', + ] as const) { + expect(createBuilder(mode).publicSourcemapsEnabled).toBe(true); + } + }); + + it('is false when WORKFLOW_SOURCEMAP env is false', () => { + process.env.WORKFLOW_SOURCEMAP = 'false'; + expect(createBuilder().publicSourcemapsEnabled).toBe(false); + }); +}); diff --git a/packages/builders/src/types.ts b/packages/builders/src/types.ts index 2cfd10f825..4856a326a6 100644 --- a/packages/builders/src/types.ts +++ b/packages/builders/src/types.ts @@ -8,6 +8,18 @@ export const validBuildTargets = [ ] as const; export type BuildTarget = (typeof validBuildTargets)[number]; +/** + * Source map emission mode for generated workflow bundles. Matches esbuild's + * `sourcemap` option vocabulary: + * + * - `true` / `'inline'`: emit a base64-encoded source map at the end of the bundle + * - `'linked'`: write a separate `.map` file and add a `sourceMappingURL` comment + * - `'external'`: write a separate `.map` file without the comment + * - `'both'`: emit both inline and external source maps + * - `false`: omit source maps entirely + */ +export type SourcemapMode = boolean | 'inline' | 'linked' | 'external' | 'both'; + /** * Common configuration options shared across all builder types. */ @@ -50,16 +62,23 @@ interface BaseWorkflowConfig { runtime?: string; /** - * Controls whether inline source maps are emitted for the step bundle and - * the intermediate workflow bundle. + * Controls how source maps are emitted for workflow bundles. Accepts the + * same values as esbuild's `sourcemap` option. + * + * Default is `'inline'` for the step bundle and intermediate workflow + * bundle (gives readable stack traces for step errors and workflow VM + * errors). Setting `false` omits source maps entirely, which produces + * smaller bundles — useful for staying under the Vercel 250MB function + * limit — at the cost of stack traces that reference generated code. + * + * `'external'` and `'linked'` write a separate `.map` file; use these + * when you want to ship source maps to observability tooling but keep + * them out of the function bundle. * - * - `true` / `'inline'` (default): emit inline source maps. Produces readable - * stack traces for step errors and workflow VM errors. - * - `false` / `'disabled'`: omit source maps. Produces smaller bundles at the - * cost of stack traces that reference generated code (e.g. the workflow VM - * bundle will show `evalmachine.` instead of user file paths). + * Can also be set via the `WORKFLOW_SOURCEMAP` environment variable; + * config wins over env var, env var wins over the default. */ - sourcemap?: boolean | 'inline' | 'disabled'; + sourcemap?: SourcemapMode; } /** diff --git a/packages/builders/src/vercel-build-output-api.ts b/packages/builders/src/vercel-build-output-api.ts index 81ab83342f..4d34982905 100644 --- a/packages/builders/src/vercel-build-output-api.ts +++ b/packages/builders/src/vercel-build-output-api.ts @@ -83,7 +83,10 @@ export class VercelBuildOutputAPIBuilder extends BaseBuilder { await this.createPackageJson(stepsFuncDir, 'module'); await this.createVcConfig(stepsFuncDir, { handler: 'index.mjs', - shouldAddSourcemapSupport: true, + // Skip the source-map-support runtime shim when sourcemaps are + // disabled — it's a meaningful chunk of the step function bundle + // and serves no purpose without maps. + shouldAddSourcemapSupport: this.sourcemapsEnabled, maxDuration: 'max', experimentalTriggers: [STEP_QUEUE_TRIGGER], runtime: this.config.runtime, diff --git a/packages/nest/src/builder.ts b/packages/nest/src/builder.ts index d6670e55d1..ac024df2ad 100644 --- a/packages/nest/src/builder.ts +++ b/packages/nest/src/builder.ts @@ -41,11 +41,12 @@ export interface NestBuilderOptions { */ distDir?: string; /** - * Controls whether inline source maps are emitted for workflow bundles. - * Defaults to `'inline'`. Set to `'disabled'` (or `false`) to omit source - * maps for smaller bundles at the cost of stack trace readability. + * Controls how source maps are emitted for workflow bundles. Accepts the + * same values as esbuild's `sourcemap` option: `true`/`'inline'` (default), + * `'linked'`, `'external'`, `'both'`, or `false` to omit source maps. + * Can also be set via the `WORKFLOW_SOURCEMAP` environment variable. */ - sourcemap?: boolean | 'inline' | 'disabled'; + sourcemap?: boolean | 'inline' | 'linked' | 'external' | 'both'; } export class NestLocalBuilder extends BaseBuilder { diff --git a/packages/next/src/index.ts b/packages/next/src/index.ts index 2b217449b0..6522f2674c 100644 --- a/packages/next/src/index.ts +++ b/packages/next/src/index.ts @@ -59,11 +59,13 @@ export function withWorkflow( port?: number; }; /** - * Controls whether inline source maps are emitted for workflow bundles. - * Defaults to `'inline'`. Set to `'disabled'` (or `false`) to omit source - * maps for smaller bundles at the cost of stack trace readability. + * Controls how source maps are emitted for workflow bundles. Accepts + * the same values as esbuild's `sourcemap` option: `true`/`'inline'` + * (default), `'linked'`, `'external'`, `'both'`, or `false` to omit + * source maps. Can also be set via the `WORKFLOW_SOURCEMAP` + * environment variable. */ - sourcemap?: boolean | 'inline' | 'disabled'; + sourcemap?: boolean | 'inline' | 'linked' | 'external' | 'both'; }; } = {} ) { diff --git a/packages/nitro/src/types.ts b/packages/nitro/src/types.ts index a8a2db057b..274d311a95 100644 --- a/packages/nitro/src/types.ts +++ b/packages/nitro/src/types.ts @@ -23,12 +23,18 @@ export interface ModuleOptions { runtime?: string; /** - * Controls whether inline source maps are emitted for workflow bundles. - * Defaults to `'inline'`. Set to `'disabled'` (or `false`) to omit source - * maps in exchange for smaller bundles, at the cost of workflow VM stack - * traces pointing at generated code instead of user files. + * Controls how source maps are emitted for workflow bundles. Accepts the + * same values as esbuild's `sourcemap` option: `true`/`'inline'` (default + * for step/workflow bundles), `'linked'`, `'external'`, `'both'`, or + * `false` to omit source maps. + * + * Set to `false` for smaller function bundles — useful for staying under + * the Vercel 250MB function size limit — at the cost of stack traces that + * point at generated code instead of your source files. + * + * Can also be set via the `WORKFLOW_SOURCEMAP` environment variable. */ - sourcemap?: boolean | 'inline' | 'disabled'; + sourcemap?: boolean | 'inline' | 'linked' | 'external' | 'both'; } declare module 'nitro/types' { diff --git a/packages/sveltekit/src/plugin.ts b/packages/sveltekit/src/plugin.ts index 652dc785e3..28193621a0 100644 --- a/packages/sveltekit/src/plugin.ts +++ b/packages/sveltekit/src/plugin.ts @@ -6,11 +6,12 @@ import { SvelteKitBuilder } from './builder.js'; export interface WorkflowPluginOptions { /** - * Controls whether inline source maps are emitted for workflow bundles. - * Defaults to `'inline'`. Set to `'disabled'` (or `false`) to omit source - * maps for smaller bundles at the cost of stack trace readability. + * Controls how source maps are emitted for workflow bundles. Accepts the + * same values as esbuild's `sourcemap` option: `true`/`'inline'` (default), + * `'linked'`, `'external'`, `'both'`, or `false` to omit source maps. Can + * also be set via the `WORKFLOW_SOURCEMAP` environment variable. */ - sourcemap?: boolean | 'inline' | 'disabled'; + sourcemap?: boolean | 'inline' | 'linked' | 'external' | 'both'; } export function workflowPlugin(options: WorkflowPluginOptions = {}): Plugin[] { From 56bf5e0b7afba16d2c0e7471974e66ac182c11ef Mon Sep 17 00:00:00 2001 From: Peter Wielander Date: Sun, 26 Apr 2026 11:49:50 -0700 Subject: [PATCH 3/3] Update packages/builders/src/types.ts Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com> Signed-off-by: Peter Wielander --- packages/builders/src/types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/builders/src/types.ts b/packages/builders/src/types.ts index 4856a326a6..2b56ee045e 100644 --- a/packages/builders/src/types.ts +++ b/packages/builders/src/types.ts @@ -12,8 +12,8 @@ export type BuildTarget = (typeof validBuildTargets)[number]; * Source map emission mode for generated workflow bundles. Matches esbuild's * `sourcemap` option vocabulary: * - * - `true` / `'inline'`: emit a base64-encoded source map at the end of the bundle - * - `'linked'`: write a separate `.map` file and add a `sourceMappingURL` comment + * - `true` / `'linked'`: write a separate `.map` file and add a `sourceMappingURL` comment + * - `'inline'`: emit a base64-encoded source map at the end of the bundle * - `'external'`: write a separate `.map` file without the comment * - `'both'`: emit both inline and external source maps * - `false`: omit source maps entirely