chore(core)!: build @nx/workspace to local dist and use nodenext#35643
Conversation
✅ Deploy Preview for nx-dev ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for nx-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
View your CI Pipeline Execution ↗ for commit 08a968b
☁️ Nx Cloud last updated this comment at |
|
No dependency changes detected. Learn more about Socket for GitHub. 👍 No dependency changes detected in pull request |
3b8fab3 to
9461a6b
Compare
9461a6b to
18c6509
Compare
18c6509 to
b524484
Compare
1b7b9fe to
1b88eec
Compare
1b88eec to
d2b59ae
Compare
99b5fdd to
5f016c0
Compare
b938100 to
7e22450
Compare
8b45912 to
07964d5
Compare
5daf687 to
1ead81f
Compare
1ead81f to
baa4392
Compare
| if (!outputIsDirectory) { | ||
| mkdir(options.outputPath); |
There was a problem hiding this comment.
The mkdir call will fail if parent directories don't exist. The function is imported from fs-extra which does not create parent directories by default.
Fix by passing the recursive option:
if (!outputIsDirectory) {
mkdir(options.outputPath, { recursive: true });
}Alternatively, use fs-extra's ensureDirSync which was likely the intent:
if (!outputIsDirectory) {
ensureDirSync(options.outputPath);
}| if (!outputIsDirectory) { | |
| mkdir(options.outputPath); | |
| if (!outputIsDirectory) { | |
| mkdir(options.outputPath, { recursive: true }); | |
| } | |
Spotted by Graphite
Is this helpful? React 👍 or 👎 to let us know.
b41b108 to
387f794
Compare
Migrates @nx/workspace to the local-dist build pattern, matching nx and @nx/devkit. Also cleans up the internal-leak surface that previously exposed @nx/workspace/src/* subpaths to other packages. - Build to packages/workspace/dist/ with nodenext + composite tsconfig. - Lock down exports map (no ./src/* wildcard) to match @nx/devkit. - Move TypeScriptCompilationOptions and compileTypeScript into @nx/js, where the tsc executor already lived. - Inline directoryExists in @nx/remix (it was a thin re-export from nx). - Source angularCliVersion default from @nx/angular in e2e helpers. - Drop the Nx 15.7 @nx/workspace/src/utils/create-ts-config fallback from @nx/rspack. - Guard the @nx/workspace ts-solution-setup mock in unit-test-setup.js so workspace-plugin's default-resolver tests don't fail. - Replace @nx/workspace/tasks-runners/default with a throwing stub pointing users at the canonical `nx/tasks-runners/default`. - Update dist-build-migration skill: add workspace:* preflight, remove naive .d.ts gitignore and *.d.ts eslint-ignore instructions. BREAKING CHANGE: @nx/workspace no longer exposes the \`@nx/workspace/src/*\` subpath wildcard in its exports map. Consumers that imported internal modules from \`@nx/workspace/src/utilities/...\` or \`@nx/workspace/src/utils/...\` must migrate to public alternatives (@nx/devkit, @nx/js, or reimplement the helper). Most generic file utilities (directoryExists, fileExists, etc.) are thin wrappers around node:fs and can be inlined. BREAKING CHANGE: \`@nx/workspace/tasks-runners/default\` now throws when invoked. The Nx 17 and Nx 21 migrations have rewritten/removed legacy \`tasksRunnerOptions\` entries to use \`nx/tasks-runners/default\`. If you still reference \`@nx/workspace/tasks-runners/default\` in \`nx.json\`, replace it with \`nx/tasks-runners/default\`.
387f794 to
a1b639d
Compare
There was a problem hiding this comment.
Why is this needed? I'm ok with it but I thought part of the whole goal in a package based repo was to not need @nx/workspace
| // Dynamic join() form bypasses the eslint self-circular-import check while | ||
| // still resolving to the package's own package.json in both source and built | ||
| // (local-dist) contexts. | ||
| export const nxVersion = require(join('@nx/workspace', 'package.json')).version; |
There was a problem hiding this comment.
Thanks, I hate it. We've gotta come up with a better sln here, ideally we'd be building src/* -> dist/*, so the depth from the package.json wouldn't change
There was a problem hiding this comment.
We moved d.ts generation into packages/nx/dist which means those lines are unnecessary because they're covered by dist
Package-based repos shouldn't depend on @nx/workspace by design. The add-extra-dependencies build hack is sufficient on its own to fix preset resolution; the template addition was a redundant workaround.
The add-extra-dependencies build hack alone is not sufficient to make @nx/workspace resolvable from the forked preset generator at workspace creation time. The template dep is required as a guaranteed-resolution fallback until the build layout is reworked (packages/<pkg>/src -> packages/<pkg>/dist) so the depth from built code to package.json matches source layout.
The local-dist migration removed @nx/js's dependency on @nx/workspace since the code-level imports it covered were inlined or moved. But that dep was also load-bearing as the install-graph path that makes @nx/workspace resolvable in created workspaces — without it, the forked `nx g @nx/workspace:preset` from create-nx-workspace can't locate the plugin and the ts-solution e2e tests fail. Restore it as a dependency with an eslint ignoredDependencies entry documenting that it's install-graph-only, no code-level import. Also revert the package-based-repo template addition and its snapshot updates from the prior workaround commit.
There was a problem hiding this comment.
✅ The fix from Nx Cloud was applied automatically
We add the missing packages/workspace/tsconfig.lib.json project reference to packages/js/tsconfig.lib.json to fix the sync:check failure. The PR moved TypeScriptCompilationOptions and compileTypeScript from @nx/workspace into @nx/js, creating a new compile-time dependency that the TypeScript sync generator requires to be declared.
Tip
✅ We verified this fix by re-running nx-cloud record -- nx sync:check.
Suggested Fix changes
diff --git a/packages/js/tsconfig.lib.json b/packages/js/tsconfig.lib.json
index 3ea109e0..c0890687 100644
--- a/packages/js/tsconfig.lib.json
+++ b/packages/js/tsconfig.lib.json
@@ -20,6 +20,9 @@
},
{
"path": "../nx/tsconfig.lib.json"
+ },
+ {
+ "path": "../workspace/tsconfig.lib.json"
}
]
}
🎓 Learn more about Self-Healing CI on nx.dev
Co-authored-by: FrozenPandaz <FrozenPandaz@users.noreply.github.com>
) ## Current Behavior `@nx/workspace` builds to the shared workspace-root `dist/packages/workspace/` directory, uses CommonJS `module`/`moduleResolution`, and has no `exports` map. Other Nx packages and external plugins reach into `@nx/workspace/src/*` subpaths for internal utilities. ## Expected Behavior `@nx/workspace` follows the same local-dist build pattern as `nx` and `@nx/devkit`: - Builds to `packages/workspace/dist/` instead of `dist/packages/workspace/`. - `tsconfig.lib.json` uses `module`/`moduleResolution: "nodenext"` with `composite`, `rootDir: "."`, `declarationDir: "dist"`. - `package.json` declares an `exports` map matching `@nx/devkit`'s locked-down surface — only named entry points, no `./src/*` wildcard. - `generators.json` / `executors.json` factory/schema paths rewritten `./src/...` → `./dist/src/...`. Workspace dev still works via the `tryResolveFromSource` fallback in `packages/nx/src/config/schema-utils.ts`. - `README.md` → `readme-template.md`; build command writes the rendered README to `packages/workspace/README.md`. - `project.json` adds `release.version` config (`preserveLocalDependencyProtocols: true`, matching nx/devkit). - `scripts/nx-release.ts`: adds `packages/workspace` to `packagesToReset`. Internal-leak cleanup so the locked-down exports map doesn't break first-party callers: - `TypeScriptCompilationOptions` + `compileTypeScript` moved from `@nx/workspace` to `@nx/js` (the package that owns TypeScript compilation). - `@nx/remix` inlines `directoryExists` (was a one-line re-export wrapper). - `@nx/rspack` drops the Nx 15.7-era `@nx/workspace/src/utils/create-ts-config` fallback. - e2e helpers source `angularDevkitVersion` from `@nx/angular/src/utils` instead. - `@nx/workspace` and `@nx/remix` no longer declare `@nx/workspace` deps they don't use. - Adds a preflight step to the `dist-build-migration` skill that warns about `workspace:*` deps on not-yet-migrated packages. ## Breaking Changes **`@nx/workspace/src/*` subpath imports are no longer supported.** The `exports` map no longer declares a `./src/*` wildcard. ~150 public consumers across GitHub use these subpaths today (the largest cluster is `src/utilities/fileutils` with ~60 hits). Migration: - `@nx/workspace/src/utilities/fileutils` (`directoryExists`, `fileExists`, `isRelativePath`, `createDirectory`) — these are thin re-exports from `nx/src/utils/fileutils`. Inline with `node:fs` (`statSync(p).isDirectory()` for `directoryExists`) or import from `@nx/devkit` where equivalent. - `@nx/workspace/src/utilities/typescript/compilation` — moved to `@nx/js`. Internal callers should import from there; if you were depending on the type externally, copy it or use the equivalent from `@nx/js`. - `@nx/workspace/src/utils/versions` — values are duplicated across packages; reimplement against the version of Nx you're targeting. - Other subpaths — check the `@nx/workspace`'s public `index.ts` re-exports first; otherwise reimplement. **`@nx/workspace/tasks-runners/default` now throws when invoked.** This module was an alias for `nx/src/tasks-runner/default-tasks-runner`. The Nx 17 (`use-minimal-config-for-tasks-runner-options`) and Nx 21 (`remove-custom-tasks-runner`) migrations rewrite/remove legacy `tasksRunnerOptions` entries. If your `nx.json` still references `@nx/workspace/tasks-runners/default`, replace it with `nx/tasks-runners/default`. ## Related Issue(s) Part of the ongoing migration of Nx packages to the local-dist build layout (following `nx` and `@nx/devkit`). --------- Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> Co-authored-by: FrozenPandaz <FrozenPandaz@users.noreply.github.com>
Current Behavior
@nx/workspacebuilds to the shared workspace-rootdist/packages/workspace/directory, uses CommonJSmodule/moduleResolution, and has noexportsmap. Other Nx packages and external plugins reach into@nx/workspace/src/*subpaths for internal utilities.Expected Behavior
@nx/workspacefollows the same local-dist build pattern asnxand@nx/devkit:packages/workspace/dist/instead ofdist/packages/workspace/.tsconfig.lib.jsonusesmodule/moduleResolution: "nodenext"withcomposite,rootDir: ".",declarationDir: "dist".package.jsondeclares anexportsmap matching@nx/devkit's locked-down surface — only named entry points, no./src/*wildcard.generators.json/executors.jsonfactory/schema paths rewritten./src/...→./dist/src/.... Workspace dev still works via thetryResolveFromSourcefallback inpackages/nx/src/config/schema-utils.ts.README.md→readme-template.md; build command writes the rendered README topackages/workspace/README.md.project.jsonaddsrelease.versionconfig (preserveLocalDependencyProtocols: true, matching nx/devkit).scripts/nx-release.ts: addspackages/workspacetopackagesToReset.Internal-leak cleanup so the locked-down exports map doesn't break first-party callers:
TypeScriptCompilationOptions+compileTypeScriptmoved from@nx/workspaceto@nx/js(the package that owns TypeScript compilation).@nx/remixinlinesdirectoryExists(was a one-line re-export wrapper).@nx/rspackdrops the Nx 15.7-era@nx/workspace/src/utils/create-ts-configfallback.angularDevkitVersionfrom@nx/angular/src/utilsinstead.@nx/workspaceand@nx/remixno longer declare@nx/workspacedeps they don't use.dist-build-migrationskill that warns aboutworkspace:*deps on not-yet-migrated packages.Breaking Changes
@nx/workspace/src/*subpath imports are no longer supported. Theexportsmap no longer declares a./src/*wildcard. ~150 public consumers across GitHub use these subpaths today (the largest cluster issrc/utilities/fileutilswith ~60 hits). Migration:@nx/workspace/src/utilities/fileutils(directoryExists,fileExists,isRelativePath,createDirectory) — these are thin re-exports fromnx/src/utils/fileutils. Inline withnode:fs(statSync(p).isDirectory()fordirectoryExists) or import from@nx/devkitwhere equivalent.@nx/workspace/src/utilities/typescript/compilation— moved to@nx/js. Internal callers should import from there; if you were depending on the type externally, copy it or use the equivalent from@nx/js.@nx/workspace/src/utils/versions— values are duplicated across packages; reimplement against the version of Nx you're targeting.@nx/workspace's publicindex.tsre-exports first; otherwise reimplement.@nx/workspace/tasks-runners/defaultnow throws when invoked. This module was an alias fornx/src/tasks-runner/default-tasks-runner. The Nx 17 (use-minimal-config-for-tasks-runner-options) and Nx 21 (remove-custom-tasks-runner) migrations rewrite/remove legacytasksRunnerOptionsentries. If yournx.jsonstill references@nx/workspace/tasks-runners/default, replace it withnx/tasks-runners/default.Related Issue(s)
Part of the ongoing migration of Nx packages to the local-dist build layout (following
nxand@nx/devkit).