Files
Nathan Rajlich 88f5d214d4 fix(builders): shim __dirname/__filename in fully-bundled ESM output (#3876)
* fix(builders): shim __dirname/__filename in fully-bundled ESM output

esbuild leaves the CJS globals __dirname/__filename as free identifiers
when inlining CJS modules into ESM output, so dependencies that reference
them at module scope (google-gax via @google-cloud/pubsub, Prisma's
runtime) crash the deployed Vercel function at init with
'ReferenceError: __dirname is not defined in ES module scope' before any
workflow code runs. v4 was immune because the Build Output API function
was CJS; #1562 switched it to ESM with a banner that shimmed only
require().

Extend the ESM banner to define __filename/__dirname from
import.meta.url, matching the shim verified live in #2770.

* chore(builders): clarify interop banner scope and tighten its regression test

Review follow-ups to the __dirname/__filename shim; no behavior change.

The ESM banner now declares require, __filename and __dirname, but the
flag that suppresses it is still named skipEsmRequireBanner and its
JSDoc described it purely in terms of __createRequire. Document the full
surface instead of renaming, since BaseBuilder is exported and
createStepsBundle is protected, so a rename would break external
subclasses in a patch release. The note calls out #3778 specifically:
reaching for this flag to silence a duplicate require declaration also
drops the dirname shim.

Assert the banner's import binding is emitted exactly once. A duplicated
banner fails at parse time on the redeclared import, before the var ever
runs, so that is the assertion that matches the real failure mode. Also
note that createWorkflowsBundle's final wrapper and createWebhookBundle
emit the same banner and are not covered here.

Finally, record in the changeset that CJS dependencies which
feature-detect via `typeof __dirname !== 'undefined'` now take their CJS
branch, where __dirname is the function root rather than the
dependency's own directory.

Signed-off-by: Pranay Prakash <pranay.gp@gmail.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* test(builders): assert the webhook function bundle carries the ESM interop shim

The webhook route is a separately deployed function built through its own
esbuild pass (createWebhookBundle); a CJS dependency referencing __dirname
reachable from it would have crashed identically, so cover that emit site
rather than only noting it as untested.

---------

Signed-off-by: Pranay Prakash <pranay.gp@gmail.com>
Co-authored-by: Pranay Prakash <pranay.gp@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-28 08:45:33 +00:00
..