Skip to content

fix(js): resolve build output dir from globbed outputs in node executor#35288

Merged
FrozenPandaz merged 3 commits intomasterfrom
gh-35198
Apr 21, 2026
Merged

fix(js): resolve build output dir from globbed outputs in node executor#35288
FrozenPandaz merged 3 commits intomasterfrom
gh-35198

Conversation

@leosvelperez
Copy link
Copy Markdown
Member

@leosvelperez leosvelperez commented Apr 14, 2026

Current Behavior

The @nx/js:node executor fails when combined with the inferred @nx/js/typescript build target — in two distinct ways:

  1. Script-to-run resolution: fails with Could not find <project>/dist/**/*.{js,cjs,mjs,jsx,d.ts,d.cts,d.mts}{,.map}/main.js. Make sure your build succeeded. — the executor's getFileToRun was appending main.js onto the glob output pattern.
  2. Buildable-dep import resolution: when the node app imports a buildable lib that also uses the inferred build target, require('@scope/my-lib') throws MODULE_NOT_FOUND because calculateResolveMappings passes the literal glob into NX_MAPPINGS, which the CJS require override / ESM loader then tries to resolve.

Both regressed after #35041 narrowed the inferred build target's outputs[0] from {projectRoot}/dist to {projectRoot}/dist/**/*.{js,...}{,.map} (to prevent cross-OS cache pollution).

Expected Behavior

outputs entries are cache patterns and may legitimately contain globs. The node executor now strips the glob portion back to the last path separator before using the value as a directory, in both getFileToRun and calculateResolveMappings. Handles **, *, ?, character classes, brace expansion, extglob, and Windows/POSIX separators.

Related Issue(s)

Fixes #35198
Fixes #35301

@leosvelperez leosvelperez requested a review from a team as a code owner April 14, 2026 13:04
@leosvelperez leosvelperez self-assigned this Apr 14, 2026
@leosvelperez leosvelperez requested a review from lourw April 14, 2026 13:04
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 14, 2026

Deploy Preview for nx-dev ready!

Name Link
🔨 Latest commit eb8cf9d
🔍 Latest deploy log https://app.netlify.com/projects/nx-dev/deploys/69e09a2f60d3fb0008182930
😎 Deploy Preview https://deploy-preview-35288--nx-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 14, 2026

Deploy Preview for nx-docs ready!

Name Link
🔨 Latest commit eb8cf9d
🔍 Latest deploy log https://app.netlify.com/projects/nx-docs/deploys/69e09a2f66e3410009a0fd9c
😎 Deploy Preview https://deploy-preview-35288--nx-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@nx-cloud
Copy link
Copy Markdown
Contributor

nx-cloud Bot commented Apr 14, 2026

View your CI Pipeline Execution ↗ for commit eb8cf9d

Command Status Duration Result
nx affected --targets=lint,test,build,e2e,e2e-c... ✅ Succeeded 24m 31s View ↗
nx run-many -t check-imports check-lock-files c... ✅ Succeeded 3s View ↗
nx-cloud record -- pnpm nx-cloud conformance:check ✅ Succeeded 17s View ↗
nx build workspace-plugin ✅ Succeeded <1s View ↗
nx-cloud record -- nx sync:check ✅ Succeeded 23s View ↗
nx-cloud record -- nx format:check ✅ Succeeded 14s View ↗

☁️ Nx Cloud last updated this comment at 2026-04-16 08:43:10 UTC

@gg-martins091
Copy link
Copy Markdown

Hey @leosvelperez, thanks for this fix.

I just wanted to confirm something, as you closed the issue I opened as duplicate of 35198, however, taking a closer look they seem to be different issues.

My issue is only when the app imports a buildable lib. Running the nestjs api with serve works fine if there is no imports of the buildable lib.

The issue you mentioned is affected directly when running the app and not specifically when it imports a buildable lib.

The stack traces also differ, mine is related to how imports are resolved and the one this PR fixes is related to how scripts to run are resolved.

Just wanted to make sure that I understand this correctly, since I tested these changes locally and still see the same error.

@gg-martins091
Copy link
Copy Markdown

The stack traces also differ, mine is related to how imports are resolved and the one this PR fixes is related to how scripts to run are resolved.

Using your stripGlobToBaseDir in calculateResolveMappings fixed my issue locally, I just dont know what else it could break... Cloning the repo right now to run the tests.

   function calculateResolveMappings(
     context: ExecutorContext,
     options: NodeExecutorOptions
   ): Record<string, string> {
     const parsed = parseTargetString(options.buildTarget, context);
     const { dependencies } = calculateProjectBuildableDependencies(/* … */);
     return dependencies.reduce((m, c) => {
       if (c.node.type !== 'npm' && c.outputs[0] != null) {
  -      m[c.name] = joinPathFragments(context.root, c.outputs[0]);
  +      // Same treatment as getFileToRun above — `outputs[0]` may be a glob
  +      // from the inferred `@nx/js/typescript` build target. Without stripping
  +      // it, the runtime `require('@scope/my-lib')` is rewritten to the literal
  +      // glob string via NX_MAPPINGS and Node throws MODULE_NOT_FOUND.
  +      const outputDir = stripGlobToBaseDir(c.outputs[0]);
  +      m[c.name] = joinPathFragments(context.root, outputDir);
       }
       return m;
     }, {} as Record<string, string>);
   }

@leosvelperez
Copy link
Copy Markdown
Member Author

@gg-martins091 good catch! You're right. The issue is caused by the same underlying root cause but it requires an additional fix. I'll update this PR with the fix for what you reported. Thanks for the investigation!

nx-cloud[bot]

This comment was marked as outdated.

Copy link
Copy Markdown
Contributor

@nx-cloud nx-cloud Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nx Cloud has identified a flaky task in your failed CI:

🔂 Since the failure was identified as flaky, we triggered a CI rerun by adding an empty commit to this branch.

Nx Cloud View detailed reasoning in Nx Cloud ↗

🔔 Heads up, your workspace has pending recommendations ↗ to auto-apply fixes for similar failures.


🎓 Learn more about Self-Healing CI on nx.dev

@FrozenPandaz FrozenPandaz merged commit 9844f0d into master Apr 21, 2026
23 checks passed
@FrozenPandaz FrozenPandaz deleted the gh-35198 branch April 21, 2026 13:32
barbados-clemens pushed a commit that referenced this pull request Apr 21, 2026
…or (#35288)

## Current Behavior

The `@nx/js:node` executor fails when combined with the inferred
`@nx/js/typescript` build target — in two distinct ways:

1. **Script-to-run resolution**: fails with `Could not find
<project>/dist/**/*.{js,cjs,mjs,jsx,d.ts,d.cts,d.mts}{,.map}/main.js.
Make sure your build succeeded.` — the executor's `getFileToRun` was
appending `main.js` onto the glob output pattern.
2. **Buildable-dep import resolution**: when the node app imports a
buildable lib that also uses the inferred build target,
`require('@scope/my-lib')` throws `MODULE_NOT_FOUND` because
`calculateResolveMappings` passes the literal glob into `NX_MAPPINGS`,
which the CJS require override / ESM loader then tries to resolve.

Both regressed after #35041 narrowed the inferred build target's
`outputs[0]` from `{projectRoot}/dist` to
`{projectRoot}/dist/**/*.{js,...}{,.map}` (to prevent cross-OS cache
pollution).

## Expected Behavior

`outputs` entries are cache patterns and may legitimately contain globs.
The node executor now strips the glob portion back to the last path
separator before using the value as a directory, in both `getFileToRun`
and `calculateResolveMappings`. Handles `**`, `*`, `?`, character
classes, brace expansion, extglob, and Windows/POSIX separators.

## Related Issue(s)

Fixes #35198
Fixes #35301

---------

Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

This pull request has already been merged/closed. If you experience issues related to these changes, please open a new issue referencing this pull request.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Apr 27, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

3 participants