Compare commits

...

47 Commits

Author SHA1 Message Date
Nicholas Cunningham c5f658b95d docs(nx-dev): Remove unused environment variables (#28521) 2024-10-18 14:32:53 -04:00
Colum Ferry 8fac5d79da fix(module-federation): normalize hypen names for runtime library control plugin #28497 (#28512)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
As part of the work to normalize `-` in MF project names for Federation,
setting the NX_MF_DEV_REMOTES env var was missed.
This causes issues with the RuntimeLibraryControlPlugin


## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
Remote names should be normalized correctly

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #28497
2024-10-18 14:32:48 -04:00
Colum Ferry c3ed7f9f5d fix(react): ensure rspack react app is added to exclude on rspack plugin #28464 (#28515)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
When you create a react rspack app when there is a `@nx/rspack/plugin`
definition in the nx.json, it causes the project graph to fail to create
nodes.


## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
Ensure the projects created via @nx/react:app --bundler=rspack are added
to exclude array if the plugin exists

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #28464
2024-10-18 14:32:45 -04:00
Benjamin Cabanes e337cb6de7 docs(nx-dev): update blog post (#28500) 2024-10-18 10:12:20 -04:00
Isaac Mann d082cd1610 docs(core): powerpack pricing clarification (#28473)
Clarify the powerpack pricing for small teams and OSS repos
2024-10-17 17:52:48 -04:00
Juri Strumpflohner fef174f509 feat(nx-dev): add contact link on powerpack page (#28458)
Co-authored-by: Benjamin Cabanes <3447705+bcabanes@users.noreply.github.com>
(cherry picked from commit 5cb2552daf)
2024-10-17 17:52:28 -04:00
Nicholas Cunningham a6a81cfc33 fix(core): neverConnectToCloud should disable connecting to nxCloud (#28501)
closed #28482, #28486

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
If, `neverConnectToCloud` is set to `true`, there are still attempts
made to connect to NxCloud.
## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
if, `neverConnectToCloud` is set to `true`, we should not attempt to
connect to NxCloud.

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
2024-10-17 17:51:09 -04:00
MaxKless a45cdd6f55 fix(core): repair SIGINT signals on windows (#28496)
using `windowsHide: true` is causing an issue on windows: Ctrl + C
handling isn't enabled and no `SIGINT` is sent to the child process when
users exit the process. See https://github.com/nodejs/node/issues/29837
and https://github.com/nodejs/node-v0.x-archive/issues/5054 for
reference. This will cause leftover processes throughout nx.

This PR sets `windowsHide: false` everywhere except for the plugin
workers and some short-lived utils. They `spawn` child processes but
have explicit handling to make sure they kill themselves when the parent
process dies, so the missing Ctrl + C handling doesn't cause issues.

We will follow up to make sure any other culprits that still cause
windows popups (especially when used through Nx Console) are handled.
Leaving no leftover processes running is more important for now, though.

Keep in mind the underlying tooling (like vite) might have some windows
popups themselves that Nx will inherit.
2024-10-17 17:51:05 -04:00
Igor Loskutov c0da413fb8 fix(expo): pnpm+workspace build (#28209)
## Current Behavior

build executors for expo crash when package manager pnpm and workspaces
are used

## Expected Behavior

no crashies

## Related Issue(s)

https://github.com/nrwl/nx/issues/28208

Fixes #28208

## FAQ

- why not handle the `undefined` by the calling code instead

The less the calling code knows about inner workings, the better: in
this case, doing this would add the implicit dependency on "pnpm and
workspaces" to the calling code

- but it's an empty function, my performance

We call it once per user interaction.

- but still, it's an empty function

We return an `empty array` when there are no elements; we don't return
`undefined` when the array is empty and `array` when array is non-empty.
Hopefully so.

- but,

The doc also says that this function returns a function.
2024-10-17 17:51:02 -04:00
Colum Ferry 7fc8a62880 fix(vite): use resolveConfig instead of loadConfigFromFile to ensure node env set #27627 (#28444)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
In the Vite Build Executor, we're using `loadConfigFromFile` from Vite
to get the config options.
The issue with this is that vite will not attempt to set `NODE_ENV`
which may be required by both the config file that is being loaded, and
other plugins.


## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
Use resolveConfig which does set NODE_ENV correctly


## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #27627
2024-10-17 17:50:59 -04:00
Nicholas Cunningham 88c2529dbc fix(react): update rspack to include styles in the main bundle (#28478)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
Currently, styles are not included in the main bundle by default.
## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
Similar to webpack, styles should be included by default.
## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #28465
2024-10-17 17:50:57 -04:00
Alan Pazetto c41de4b383 fix(js): change verdaccio childProcess kill order (#28364)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
`@nx/js:verdaccio` current call `npm config` to setup npm scopes in
global `.npmrc` file, which it's supposed to do.

However, when process is killed (using terminal exit command or any
other way), the process is killed and doesn't restore changed config.

In my case I'm changing scope to my private scope (using `scopes`
option), but after kill I need to restore manually.

## Expected Behavior
When process be killed, restore all configs that was set.

## Related Issue(s)
#28353

Fixes #28353
2024-10-17 17:50:54 -04:00
MaxKless 84ed1d728e fix(graph): make sure disabledTaskSyncGenerators can be set correctly from nx console (#28466)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
2024-10-17 17:50:51 -04:00
Isaac Mann f371a6e217 fix(nx-dev): fix tabs logic (#28470)
Fix tabs being hidden when selecting a tab in a different tab group
2024-10-17 17:50:27 -04:00
Colum Ferry 8d0f277520 fix(vite): add vite temp files to gitignore #28371 (#28443)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
When Vite's tries to handle a `.ts` config file it builds it to JS with
a `.timestamp-` suffix. These files are still picked up by Nx when they
shouldn't as it's a temp file
(https://github.com/vitejs/vite/issues/13267).



## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
Add these temp files to gitignore to prevent processing.


## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #28371
2024-10-17 15:19:05 -04:00
Phillip Barta 6cb2af4e6f fix(rspack): add dependency-checks lint rule (#28225)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

The rspack plugin has no dependency-checks in place. I discovered it
while working on #27676.

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

The `@nx/dependency-checks` eslint rule should be used.

There are a few dependencies that I don't know how to proceed with:

```
The "rspack" project uses the following packages, but they are missing from "dependencies":
    - @nx/workspace
    - webpack-sources
    - @module-federation/sdk  @nx/dependency-checks

The "@rspack/plugin-minify" package is not used by "rspack" project
```

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

#27676

---------

Co-authored-by: Emily Xiong <xiongemi@gmail.com>
Co-authored-by: Colum Ferry <cferry09@gmail.com>
2024-10-17 15:19:01 -04:00
Isaac Mann f808ea86b0 docs(core): center specific markdown tables (#28459)
- Removes the hard-coded centering of markdown table cells.
- Centers specific tables that make sense to be centered
2024-10-17 15:18:57 -04:00
Sam Tsai a714301ad0 fix(rspack): make rspack dev server respect port (#28251)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
Port is not respected from `rspack.config.[jt]s` and needs to be
explicitly set in `project.json` options.

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
Port should be configurable via config, options, etc.

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->
Fixes #28040 (port portion)
2024-10-17 15:18:53 -04:00
Sam Tsai d59e8cc6af fix(rspack): replace DefinePlugin with EnvironmentPlugin (#28252)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
```
[webpack-dev-server] WARNING
  ⚠ DefinePlugin:
  │ Conflicting values for 'process.env.NODE_ENV' ("'development'" !== "\"development\"")
```

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
`process.env.NODE_ENV` should resolve to `'development'` and not a
quoted value: `"'development'"`

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #28040 (NODE_ENV part)
2024-10-17 15:18:49 -04:00
James Henry 10405bcfe9 fix(release): ensure plan subcommand works with object config (#28460) 2024-10-17 15:18:44 -04:00
James Henry 07c07e4e86 chore(repo): fix npm-audit workflow, only run on origin (#28457) 2024-10-17 15:18:39 -04:00
Mike Hartington 7325b9ce28 docs(core): update release blog post (#28384)
Provide a recap of features from the previous release

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
2024-10-17 15:18:34 -04:00
Colum Ferry c83dd29c3c docs(rspack): remove incorrect information (#28383)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
The docs specify that the react library generator supports using rspack
as a bundler option.
The react library generator does not have rspack as an option.


## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
Remove misleading docs


## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
2024-10-17 15:18:31 -04:00
Isaac Mann 399ee5b3bd docs(core): schema update to disable nx cloud (#28432)
Add `neverConnectToCloud` to the `nx-schema.json`

Fixes #28188
2024-10-17 15:18:25 -04:00
Isaac Mann 6f9e1477d4 docs(core): update data cache env var (#28431)
Fix data cache env var

Fixes #28389
2024-10-17 15:18:22 -04:00
Isaac Mann 1e39ba671f docs(core): add s3-cache github actions example (#28241)
Add a GitHub Actions example in the s3-cache plugin docs
2024-10-17 15:18:14 -04:00
Isaac Mann 7ead9a022f docs(core): redirect conf to monorepo.world (#28338)
Redirect `/conf` to `monorepo.world`
2024-10-17 15:17:34 -04:00
Benjamin Cabanes 99cfc14893 feat(nx-dev): update home hero & livestream notifier (#28403) 2024-10-17 15:17:30 -04:00
Nicholas Cunningham aa7b2b011d docs(nx-dev): update monorepo world notification (#28398) 2024-10-17 15:17:27 -04:00
Isaac Mann 245bed7a07 docs(core): update livestream links again 2024-10-17 15:17:24 -04:00
Isaac Mann e47b45b958 docs(core): update live stream links 2024-10-17 15:17:22 -04:00
Benjamin Cabanes 69ec3796fe feat(nx-dev): add live stream notifier (#28260)
Co-authored-by: Juri <juri.strumpflohner@gmail.com>
2024-10-17 15:17:17 -04:00
Jonathan Cammisuli 145fe01e3d fix(core): add migration to set useLegacyCache by default (#28454) 2024-10-15 16:06:41 -04:00
Jonathan Cammisuli afe0cecb1e fix(core): handle neverConnectToCloud property (#28452)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
`neverConnectToCloud` was not respected in the `isNxCloudUsed` function

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
`neverConnectToCloud` is now respected

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #28287
2024-10-15 16:06:15 -04:00
Leosvel Pérez Espinosa 485090572c fix(js): improve @nx/js/typescript plugin and typescript-sync generator performance (#28379) 2024-10-15 12:44:57 -04:00
Jonathan Cammisuli e8ce99d234 fix(core): add busy handler for sqlite (#28390)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
When the sql database throws a busy signal, there is no handler in nx to
try the operation again.

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
There is a handler to tell sqlite to handle the operation again, and try
up to N times.

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
2024-10-15 11:22:52 -04:00
Jonathan Cammisuli 46eac466de fix(core): support NX_NO_CLOUD (#28366)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
Using `NX_NO_CLOUD` does not disable the remoteCache implementation for
Nx Cloud

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
Using `NX_NO_CLOUD` will disable nx cloud remote cache

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
2024-10-15 10:43:14 -04:00
Colum Ferry c006e90f97 fix(rspack): do not select char from string when mapping remotes (#28441)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
When global prefix is used, there is an issue with the mapping of string
remote usage.
It selects a single character from the string rather than using the full
string


## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
Use the full string as remote name when mapping remotes

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
2024-10-15 10:43:10 -04:00
Colum Ferry c3f401ceda fix(module-federation): remote names should follow JS variable naming schema (#28401)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
We previously had a schema restriction on the characters allowed for
remote names. It was to prevent names that violated the JS spec for a
variable declaration.


## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
Ensure invalid project names fail error allowing the user to fix it at
generation


## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #28354, #28408

---------

Co-authored-by: Jack Hsu <jack.hsu@gmail.com>
2024-10-14 19:49:45 -04:00
Colum Ferry 85bed15280 fix(rspack): log compilation errors #28179 (#28429)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
When running serve with Rspack, `stats: false` is being added to
`devMiddleware` preventing logs from being output to the terminal.


## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
Ensure logs are logged to the devServer

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #28179
2024-10-14 19:49:42 -04:00
Colum Ferry 74777a1754 fix(module-federation): ensure mf-manifest supported and tspaths are added with snake_case (#28244)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
2024-10-14 19:49:39 -04:00
Leosvel Pérez Espinosa 11fe2a700e fix(angular): add missing package version bump for zone.js (#28430)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #28046
2024-10-14 19:49:36 -04:00
Colum Ferry 926ade4270 fix(angular): ensure provideStore is provided before storeDevTools #28107 (#28428)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
The order of the `provide*` functions for NgRx matters and should
therefore be structured as such


## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
Ensure `provideStore` is first provider added

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #28107
2024-10-14 19:49:33 -04:00
Colum Ferry 7231561c92 fix(react): depends on migration should ignore configs that point to @nx/react #28377 (#28382)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
Some executors using `@nx/webpack:webpack` point to a webpack config
that is exported from the `@nx/react plugin.

We do not want to try modify this.


## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
Skip the migration if the webpack config points to the exported plugin
from @nx/react.


## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #28377
2024-10-14 19:49:31 -04:00
Leosvel Pérez Espinosa e458ecf2b1 fix(linter): scope js and ts shared configs to js and ts files (#28381) 2024-10-14 19:49:29 -04:00
James Henry 371d20446f chore(repo): add new issue type to bug template (#28367) 2024-10-14 19:49:26 -04:00
Nicholas Cunningham 392d72e00d chore(nx-dev): Update LTS version for Nx 20 (#28259)
Co-authored-by: Jack Hsu <jack.hsu@gmail.com>
2024-10-14 19:49:23 -04:00
176 changed files with 1442 additions and 628 deletions
+1
View File
@@ -1,6 +1,7 @@
name: 🐞 Bug Report
description: This form is to report unexpected behavior in Nx.
labels: ["type: bug"]
type: Bug
body:
- type: markdown
attributes:
+4 -8
View File
@@ -8,25 +8,21 @@ on:
permissions: {}
jobs:
audit:
if: ${{ github.repository_owner == 'nrwl' }}
permissions:
contents: read # to fetch code (actions/checkout)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install PNPM
run: |
npm install -g @pnpm/exe@8
- uses: pnpm/action-setup@v4
with:
version: 9.8.0 # Aligned with root package.json (pnpm/action-setup will helpfully error if out of sync)
- name: Run a security audit
run: pnpm dlx audit-ci --critical --report-type summary
# - name: Run Dependency confusion supply chain check
# run: npx snync -d .
report:
if: ${{ always() && github.repository_owner == 'nrwl' && github.event_name != 'workflow_dispatch' }}
needs: audit
+5
View File
@@ -79,12 +79,14 @@ rust-toolchain @nrwl/nx-native-reviewers
/docs/generated/packages/js/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/web/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/webpack/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/rspack/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/esbuild/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/rollup/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/generated/packages/vite/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/js/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/web/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/webpack/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/rspack/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/esbuild/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/docs/shared/packages/vite/** @nrwl/nx-js-reviewers @nrwl/nx-docs-reviewers
/packages/js/** @nrwl/nx-js-reviewers
@@ -94,6 +96,9 @@ rust-toolchain @nrwl/nx-native-reviewers
/packages/webpack/** @nrwl/nx-js-reviewers
/packages/webpack/src/utils/module-federation @jaysoo @Coly010
/e2e/webpack/** @nrwl/nx-js-reviewers
/packages/rspack/** @nrwl/nx-js-reviewers
/packages/rspack/src/utils/module-federation @jaysoo @Coly010
/e2e/rspack/** @nrwl/nx-js-reviewers
/packages/esbuild/** @nrwl/nx-js-reviewers
/e2e/esbuild/** @nrwl/nx-js-reviewers
/packages/rollup/** @nrwl/nx-js-reviewers
+7 -7
View File
@@ -61,13 +61,13 @@ Tasks can fail:
Lets see how varying a few parameters affects the probability of the CI execution failing.
| Number of VMS | Avg Tests per VM | Flaky Test Probability | Slow Test Probability | Broken CI Builds (Flaky) | Slow CI Builds |
| ------------- | ---------------- | ---------------------- | --------------------- | ------------------------ | -------------- |
| 5 | 10 | 0.1% | 0.3% | 5% | 15% |
| 10 | 10 | 0.1% | 0.3% | 10% | 26% |
| 50 | 10 | 0.1% | 0.3% | 39% | 78% |
| 5 | 10 | 0.5% | 1% | 23% | 41% |
| 10 | 10 | 0.5% | 1% | 40% | 65% |
| 50 | 10 | 0.5% | 1% | 92% | 99% |
| :-----------: | :--------------: | :--------------------: | :-------------------: | :----------------------: | :------------: |
| 5 | 10 | 0.1% | 0.3% | 5% | 15% |
| 10 | 10 | 0.1% | 0.3% | 10% | 26% |
| 50 | 10 | 0.1% | 0.3% | 39% | 78% |
| 5 | 10 | 0.5% | 1% | 23% | 41% |
| 10 | 10 | 0.5% | 1% | 40% | 65% |
| 50 | 10 | 0.5% | 1% | 92% | 99% |
**The result is much worse than most intuitively expect.** For instance, assuming that an **e2e test has 1 in 1000 chance (0.1%) of failing** for a flaky reason, when the number of e2e tests reaches 500, **the probability of the CI failing for a flaky reason reaches 39%**, and the vast majority of CI executions are slowed down. Note, this is an exceptionally stable test suite. The bottom part of the table is more representative of a typical e2e suite, and the CI becomes “broken” at a much smaller scale.
+7 -1
View File
@@ -6,6 +6,12 @@ tags: [nx, release]
cover_image: /blog/images/evolving-nx/thumbnail.png
---
_Update from Jeff Cross, October 17, 2024_
In my original version of this post, I said that Powerpack is completely new functionality. I mistakenly thought that all custom remote cache solutions were using private/unsupported APIs, but I've since learned that we've had docs and some APIs that helped people build their own remote caches. I'm sorry for the error, and have updated the text to indicate that Powerpack is mostly new functionality. We've also updated the [Powerpack page](/powerpack) to make it more explicit how some teams can get free Powerpack licenses.
---
Over the years, Nx has grown from a small 20% side project of our consulting business into a tool that empowers millions of developers worldwide and helps Fortune 500 companies ship high-quality software faster. In the last two years, we successfully transformed our consulting business into a product company, where our team can fully focus on evolving Nx and building Nx Cloud to extend Nxs capabilities beyond local development.
This success is in large part thanks to:
@@ -21,7 +27,7 @@ When we have new ideas to make Nx better, weve always had two options: it cou
> If you want to get into the technical details, we wrote a separate blog post diving deeper into the technical details: [Introducing Nx Powerpack](/blog/introducing-nx-powerpack).
Everything in Powerpack is new functionality, not previously free features that were now putting behind a paywall. However, this change coincides with some Nx improvements that will eventually interfere with users who were relying on our original filesystem-based implementation of local caching. Weve completely rewritten Nx's local caching to be faster and more secure, partly by using a local database instead of checking the filesystem for artifact metadata. With this rewrite, any custom remote caches that rely on metadata reflected in the filesystem will not work as of Nx 21. This is why we decided to build an API into Powerpack to be able to connect Nxs cache to different clouds and data sources. Now with Powerpack, teams can use an officially-supported implementation of remote caching, without needing to use Nx Cloud.
Powerpack is mostly new functionality. However, this change coincides with some Nx improvements that will eventually interfere with users who were relying on our original filesystem-based implementation of local caching. Weve completely rewritten Nx's local caching to be faster and more secure, partly by using a local database instead of checking the filesystem for artifact metadata. With this rewrite, any custom remote caches that rely on metadata reflected in the filesystem will not work as of Nx 21. This is why we decided to build an API into Powerpack to be able to connect Nxs cache to different clouds and data sources. Now with Powerpack, teams can use an officially-supported implementation of remote caching, without needing to use Nx Cloud.
Theres a Steve Jobs quote that I think rings true with all of us at Nx:
+15 -1
View File
@@ -6,7 +6,15 @@ tags: [nx, release]
cover_image: /blog/images/2024-10-03/nx-20-header.png
---
I know it's hard to believe but Nx 20 is here! There's a lot to cover in this release, so let's just dive right in.
I know it's hard to believe but Nx 20 is here! There's a lot of great updates in this release, but look back at some of the major features from Nx 19:
- Added [`nx import`][nx-import] to import existing external projects while maintaining git history.
- Added a [generator][crystalize-command] to convert all your Nx Plugins to use inferred tasks.
- Moved to [rspack][nx-rspack] as the default bundler for Module Federation
- Added [file-based versioning][file-based-versioning] for Nx Release
- Created a new [plugin for Gradle][nx-gradle] and support for [task atomization][gradle-atomizer]
With Nx 20 we're keeping the momentum going and bringing some quality improvements to the overall monorepo experience as well as a boost in speed for TypeScript projects.
## `@nx` All The Things!
@@ -73,3 +81,9 @@ There's a lot more in Nx 20, so be sure to check the full changelog for all the
[rspack]: https://rspack.dev
[rescope]: /deprecated/rescope
[colum]: https://x.com/FerryColum
[gradle-atomizer]: /blog/nx-19-5-adds-stackblitz-new-features-and-more#experimental-gradle-test-atomization
[nx-gradle]: /blog/nx-19-release#new-plugin-nxgradle
[file-based-versioning]: /recipes/nx-release/file-based-versioning-version-plans
[nx-rspack]: /nx-api/rspack
[crystalize-command]: /blog/nx-19-8-update#crystalize-your-entire-workspace-in-one-command
[nx-import]: /nx-api/nx/documents/import
@@ -48,6 +48,35 @@ There are four different ways to authenticate with AWS. They will be attempted i
Both the `AWS_ACCESS_KEY_ID` and the `AWS_SECRET_ACCESS_KEY` environment variables are required to use the environment variable authentication method.
Here's an example of using OICD in GitHub Actions to set the environment variables in CI:
```yaml {% fileName=".github/workflows/ci.yml" %}
name: CI
...
permissions:
id-token: write
...
env:
NX_DB_CACHE: true
jobs:
main:
runs-on: ubuntu-latest
steps:
...
- name: 'Configure AWS Credentials'
uses: aws-actions/configure-aws-credentials@v4.0.2
with:
role-to-assume: arn:aws:iam::123456789123:role/GhAIBucketUserRole
aws-region: us-east-1
...
- run: pnpm exec nx affected -t lint test build
```
#### INI Config Files
AWS can read your authentication credentials from [shared INI config files](https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html). The files are located at `~/.aws/credentials` and `~/.aws/config`. Both files are expected to be INI formatted with section names corresponding to profiles. Sections in the credentials file are treated as profile names, whereas profile sections in the config file must have the format of `[profile profile-name]`, except for the default profile. Profiles that appear in both files will not be merged, and the version that appears in the credentials file will be given precedence over the profile found in the config file.
+1 -1
View File
@@ -171,7 +171,7 @@ Named inputs targets can refer to reduce duplication
`Optional` **neverConnectToCloud**: `boolean`
Set this to false to disable connection to Nx Cloud
Set this to true to disable connection to Nx Cloud
---
+1 -1
View File
@@ -211,7 +211,7 @@ Named inputs targets can refer to reduce duplication
`Optional` **neverConnectToCloud**: `boolean`
Set this to false to disable connection to Nx Cloud
Set this to true to disable connection to Nx Cloud
#### Inherited from
@@ -77,7 +77,7 @@ npm add -D @nx/rspack
### Generate a new project using Rspack
You can generate a [React](/nx-api/react) application or library that uses Rspack. The [`@nx/react:app`](/nx-api/react/generators/application) and [`@nx/react:lib`](/nx-api/react/generators/library) generators accept the `bundler` option, where you can pass `rspack`. This will generate a new application configured to use Rspack, and it will also install all the necessary dependencies, including the `@nx/rspack` plugin.
You can generate a [React](/nx-api/react) application that uses Rspack. The [`@nx/react:app`](/nx-api/react/generators/application) generator accepts the `bundler` option, where you can pass `rspack`. This will generate a new application configured to use Rspack, and it will also install all the necessary dependencies, including the `@nx/rspack` plugin.
To generate a React application using Rspack, run the following:
@@ -85,12 +85,6 @@ To generate a React application using Rspack, run the following:
nx g @nx/react:app my-app --bundler=rspack
```
To generate a React library using Rspack, run the following:
```bash
nx g @nx/react:lib my-lib --bundler=rspack
```
### Modify an existing React project to use Rspack
You can use the `@nx/rspack:configuration` generator to change your React to use Rspack. This generator will modify your project's configuration to use Rspack, and it will also install all the necessary dependencies, including the `@nx/rspack` plugin.
+7 -7
View File
@@ -165,11 +165,11 @@ Along with all the UI changes to support agents (following their logs and track
When upgrading to this version and anything above it, you will need to use Helm version 0.12.0+:
| Chart Version | Compatible Images |
| ------------- | ---------------------------------- |
| Chart Version | Compatible Images |
| :-----------: | :--------------------------------: |
| <= `0.10.11` | `2306.01.2.patch4` **and earlier** |
| >= `0.11.0` | `2308.22.7` **and later** |
| >= `0.12.0` | `2312.11.7` **and later** |
| >= `0.11.0` | `2308.22.7` **and later** |
| >= `0.12.0` | `2312.11.7` **and later** |
##### New UI features and improvements
@@ -268,10 +268,10 @@ product. It's faster, it handles resource caching better, and should allow the f
When upgrading to this version and anything above it, you will need to use Helm version 0.11.1:
| Chart Version | Compatible Images |
| ------------- | ---------------------------------- |
| Chart Version | Compatible Images |
| :-----------: | :--------------------------------: |
| <= `0.10.11` | `2306.01.2.patch4` **and earlier** |
| >= `0.11.0` | `2308.22.7` **and later** |
| >= `0.11.0` | `2308.22.7` **and later** |
##### VCS proxy support
@@ -48,6 +48,35 @@ There are four different ways to authenticate with AWS. They will be attempted i
Both the `AWS_ACCESS_KEY_ID` and the `AWS_SECRET_ACCESS_KEY` environment variables are required to use the environment variable authentication method.
Here's an example of using OICD in GitHub Actions to set the environment variables in CI:
```yaml {% fileName=".github/workflows/ci.yml" %}
name: CI
...
permissions:
id-token: write
...
env:
NX_DB_CACHE: true
jobs:
main:
runs-on: ubuntu-latest
steps:
...
- name: 'Configure AWS Credentials'
uses: aws-actions/configure-aws-credentials@v4.0.2
with:
role-to-assume: arn:aws:iam::123456789123:role/GhAIBucketUserRole
aws-region: us-east-1
...
- run: pnpm exec nx affected -t lint test build
```
#### INI Config Files
AWS can read your authentication credentials from [shared INI config files](https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html). The files are located at `~/.aws/credentials` and `~/.aws/config`. Both files are expected to be INI formatted with section names corresponding to profiles. Sections in the credentials file are treated as profile names, whereas profile sections in the config file must have the format of `[profile profile-name]`, except for the default profile. Profiles that appear in both files will not be merged, and the version that appears in the credentials file will be given precedence over the profile found in the config file.
+1 -7
View File
@@ -77,7 +77,7 @@ npm add -D @nx/rspack
### Generate a new project using Rspack
You can generate a [React](/nx-api/react) application or library that uses Rspack. The [`@nx/react:app`](/nx-api/react/generators/application) and [`@nx/react:lib`](/nx-api/react/generators/library) generators accept the `bundler` option, where you can pass `rspack`. This will generate a new application configured to use Rspack, and it will also install all the necessary dependencies, including the `@nx/rspack` plugin.
You can generate a [React](/nx-api/react) application that uses Rspack. The [`@nx/react:app`](/nx-api/react/generators/application) generator accepts the `bundler` option, where you can pass `rspack`. This will generate a new application configured to use Rspack, and it will also install all the necessary dependencies, including the `@nx/rspack` plugin.
To generate a React application using Rspack, run the following:
@@ -85,12 +85,6 @@ To generate a React application using Rspack, run the following:
nx g @nx/react:app my-app --bundler=rspack
```
To generate a React library using Rspack, run the following:
```bash
nx g @nx/react:lib my-lib --bundler=rspack
```
### Modify an existing React project to use Rspack
You can use the `@nx/rspack:configuration` generator to change your React to use Rspack. This generator will modify your project's configuration to use Rspack, and it will also install all the necessary dependencies, including the `@nx/rspack` plugin.
@@ -10,7 +10,7 @@ Activating Powerpack is a two step process.
## 1. Purchase a License
You'll need to [purchase a license](https://cloud.nx.app/powerpack/purchase) online. The license is a seat-based license. If you have an open-source repository, reach out to [powerpack-support@nrwl.io](mailto:powerpack-support@nrwl.io) for a free license.
You'll need to [purchase a license](https://cloud.nx.app/powerpack/purchase) online. The license is a seat-based license. If you are a small team, the purchase form has an option to apply for a free license. If you have an open-source repository, you can [register for a free OSS license](https://forms.gle/mWjQo6Vrv5Kt6WYh9) as well.
{% call-to-action title="Buy a Powerpack License" icon="nx" description="Unlock all the features of Nx" url="https://cloud.nx.app/powerpack/purchase" /%}
+30 -32
View File
@@ -2,38 +2,36 @@
The following environment variables are ones that you can set to change the behavior of Nx in different environments.
| Property | Type | Description |
| --------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| NX_ADD_PLUGINS | boolean | If set to `false`, Nx will not add plugins to infer tasks. This is `true` by default. Workspaces created before Nx 18 will have this disabled via a migration for backwards compatibility |
| NX_ADD_TS_PLUGIN | boolean | If set to `false` when creating a new workspace using the `ts` preset, Nx will not add the `@nx/js/typescript` plugin to infer tasks and will not set up the workspace with [TypeScript project references](https://www.typescriptlang.org/docs/handbook/project-references.html). This is `true` by default. |
| NX_BASE | string | The default base branch to use when calculating the affected projects. Can be overridden on the command line with `--base`. |
| NX_CACHE_DIRECTORY | string | The cache for task outputs is stored in `.nx/cache` by default. Set this variable to use a different directory. |
| NX_CACHE_PROJECT_GRAPH | boolean | If set to `false`, disables the project graph cache. Most useful when developing a plugin that modifies the project graph. |
| NX_DAEMON | boolean | If set to `false`, disables the Nx daemon process. Disable the daemon to print `console.log` statements in plugin code you are developing. |
| NX_DEFAULT_PROJECT | string | The default project used for commands which require a project. e.g. `nx build`, `nx g component`, etc. |
| NX_HEAD | string | The default head branch to use when calculating the affected projects. Can be overridden on the command line with `--head`. |
| NX_PERF_LOGGING | boolean | If set to `true`, will print debug information useful for for profiling executors and Nx itself |
| NX_PROFILE | string | Prepend `NX_PROFILE=profile.json` before running targets with Nx to generate a file that be [loaded in Chrome dev tools](/troubleshooting/performance-profiling) to visualize the performance of Nx across multiple processes. |
| NX_WORKSPACE_DATA_CACHE_DIRECTORY | string | The project graph cache and some other internal nx caches are stored in `.nx/workspace-data` by default. Set this variable to use a different directory. |
| NX_PROJECT_GRAPH_MAX_WORKERS | number | The number of workers to use when calculating the project graph. |
| NX_PARALLEL | number | The number of tasks Nx should run in parallel. Overrides any configured value inside nx.json |
| NX_RUNNER | string | The name of task runner from the config to use. Can be overridden on the command line with `--runner`. Not read if `NX_TASKS_RUNNER` is set. |
| NX_SKIP_NX_CACHE | boolean | Rerun the tasks even when the results are available in the cache |
| NX_TASKS_RUNNER | string | The name of task runner from the config to use. Can be overridden on the command line with `--runner`. Preferred over `NX_RUNNER`. |
| NX_TASKS_RUNNER_DYNAMIC_OUTPUT | boolean | If set to `false`, will use non-dynamic terminal output strategy (what you see in CI), even when you terminal can support the dynamic version |
| NX_VERBOSE_LOGGING | boolean | If set to `true`, will print debug information useful for troubleshooting |
| NX_DRY_RUN | boolean | If set to `true`, will perform a dry run of the generator. No files will be created and no packages will be installed. |
| NX_INTERACTIVE | boolean | If set to `true`, will allow Nx to prompt you in the terminal to answer some further questions when running generators. |
| NX_GENERATE_QUIET | boolean | If set to `true`, will prevent Nx logging file operations during generate |
| NX_PREFER_TS_NODE | boolean | If set to `true`, Nx will use `ts-node` for local execution of plugins even if `@swc-node/register` is installed. |
| NX_IGNORE_CYCLES | boolean | If set to `true`, Nx will ignore errors created by a task graph circular dependency. Can be overriden on the command line with `--nxIgnoreCycles` |
| NX_BATCH_MODE | boolean | If set to `true`, Nx will run task(s) in batches for executors which support batches. |
| NX_SKIP_LOG_GROUPING | boolean | If set to `true`, Nx will not group command's logs on CI. |
| NX_MIGRATE_CLI_VERSION | string | The version of Nx to use for running the `nx migrate` command. If not set, it defaults to `latest`. |
| NX_LOAD_DOT_ENV_FILES | boolean | If set to 'false', Nx will not load any environment files (e.g. `.local.env`, `.env.local`) |
| NX_NATIVE_FILE_CACHE_DIRECTORY | string | The cache for native `.node` files is stored under a global temp directory by default. Set this variable to use a different directory. This is interpreted as an absolute path. |
| NX_PLUGIN_NO_TIMEOUTS | boolean | If set to `true`, plugin operations will not timeout |
| NX_SOCKET_DIRECTORY | string | Sets the directory that Nx will use when creating sockets to communicate with child processes. May be needed if the derived socket path is too long. |
| Property | Type | Description |
| ------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| NX_ADD_PLUGINS | boolean | If set to `false`, Nx will not add plugins to infer tasks. This is `true` by default. Workspaces created before Nx 18 will have this disabled via a migration for backwards compatibility |
| NX_ADD_TS_PLUGIN | boolean | If set to `false` when creating a new workspace using the `ts` preset, Nx will not add the `@nx/js/typescript` plugin to infer tasks and will not set up the workspace with [TypeScript project references](https://www.typescriptlang.org/docs/handbook/project-references.html). This is `true` by default. |
| NX_BASE | string | The default base branch to use when calculating the affected projects. Can be overridden on the command line with `--base`. |
| NX_CACHE_DIRECTORY | string | The cache for task outputs is stored in `.nx/cache` by default. Set this variable to use a different directory. |
| NX_CACHE_PROJECT_GRAPH | boolean | If set to `false`, disables the project graph cache. Most useful when developing a plugin that modifies the project graph. |
| NX_DAEMON | boolean | If set to `false`, disables the Nx daemon process. Disable the daemon to print `console.log` statements in plugin code you are developing. |
| NX_DEFAULT_PROJECT | string | The default project used for commands which require a project. e.g. `nx build`, `nx g component`, etc. |
| NX_HEAD | string | The default head branch to use when calculating the affected projects. Can be overridden on the command line with `--head`. |
| NX_PERF_LOGGING | boolean | If set to `true`, will print debug information useful for for profiling executors and Nx itself |
| NX_PROFILE | string | Prepend `NX_PROFILE=profile.json` before running targets with Nx to generate a file that be [loaded in Chrome dev tools](/troubleshooting/performance-profiling) to visualize the performance of Nx across multiple processes. |
| NX_WORKSPACE_DATA_DIRECTORY | string | The project graph cache and some other internal nx caches are stored in `.nx/workspace-data` by default. Set this variable to use a different directory. |
| NX_PARALLEL | number | The number of tasks Nx should run in parallel. Overrides any configured value inside nx.json |
| NX_RUNNER | string | The name of task runner from the config to use. Can be overridden on the command line with `--runner`. Not read if `NX_TASKS_RUNNER` is set. |
| NX_SKIP_NX_CACHE | boolean | Rerun the tasks even when the results are available in the cache |
| NX_TASKS_RUNNER | string | The name of task runner from the config to use. Can be overridden on the command line with `--runner`. Preferred over `NX_RUNNER`. |
| NX_TASKS_RUNNER_DYNAMIC_OUTPUT | boolean | If set to `false`, will use non-dynamic terminal output strategy (what you see in CI), even when you terminal can support the dynamic version |
| NX_VERBOSE_LOGGING | boolean | If set to `true`, will print debug information useful for troubleshooting |
| NX_DRY_RUN | boolean | If set to `true`, will perform a dry run of the generator. No files will be created and no packages will be installed. |
| NX_INTERACTIVE | boolean | If set to `true`, will allow Nx to prompt you in the terminal to answer some further questions when running generators. |
| NX_GENERATE_QUIET | boolean | If set to `true`, will prevent Nx logging file operations during generate |
| NX_PREFER_TS_NODE | boolean | If set to `true`, Nx will use `ts-node` for local execution of plugins even if `@swc-node/register` is installed. |
| NX_IGNORE_CYCLES | boolean | If set to `true`, Nx will ignore errors created by a task graph circular dependency. Can be overridden on the command line with `--nxIgnoreCycles` |
| NX_BATCH_MODE | boolean | If set to `true`, Nx will run task(s) in batches for executors which support batches. |
| NX_SKIP_LOG_GROUPING | boolean | If set to `true`, Nx will not group command's logs on CI. |
| NX_MIGRATE_CLI_VERSION | string | The version of Nx to use for running the `nx migrate` command. If not set, it defaults to `latest`. |
| NX_LOAD_DOT_ENV_FILES | boolean | If set to 'false', Nx will not load any environment files (e.g. `.local.env`, `.env.local`) |
| NX_NATIVE_FILE_CACHE_DIRECTORY | string | The cache for native `.node` files is stored under a global temp directory by default. Set this variable to use a different directory. This is interpreted as an absolute path. |
| NX_PLUGIN_NO_TIMEOUTS | boolean | If set to `true`, plugin operations will not timeout |
Nx will set the following environment variables so they can be accessible within the process even outside of executors and generators.
+5 -5
View File
@@ -19,11 +19,11 @@ should use `nx migrate` to ensure that they stay on a supported version.
The following are the currently supported major versions of Nx.
| Version | Support Type | Release Date |
| ------- | ------------ | ------------ |
| v19 | Current | 2024-05-06 |
| v18\* | LTS | 2024-02-03 |
| v17 | LTS | 2023-10-19 |
| v16 | LTS | 2023-04-27 |
| :-----: | :----------: | :----------: |
| v20 | Current | 2024-10-06 |
| v19 | LTS | 2024-05-06 |
| v18\* | LTS | 2024-02-03 |
| v17 | LTS | 2023-10-19 |
**\*Note:** v18 is a special release and does not fit into the normal release cycle. Thus, v16 continues to be supported
according to schedule.
+1 -1
View File
@@ -273,7 +273,7 @@ export function runCommandUntil(
...opts.env,
FORCE_COLOR: 'false',
},
windowsHide: true,
windowsHide: false,
});
return new Promise((res, rej) => {
let output = '';
+1 -1
View File
@@ -65,7 +65,7 @@ function getPublishedVersion(): Promise<string | undefined> {
exec(
'npm view nx@latest version',
{
windowsHide: true,
windowsHide: false,
},
(error, stdout, stderr) => {
if (error) {
@@ -1,16 +1,16 @@
import { useCallback } from 'react';
import { ProjectDetails } from '@nx/graph-internal/ui-project-details';
import {
ErrorToastUI,
ExpandedTargetsProvider,
getExternalApiService,
} from '@nx/graph/shared';
import { useMachine, useSelector } from '@xstate/react';
import { ProjectDetails } from '@nx/graph-internal/ui-project-details';
import { useSelector } from '@xstate/react';
import { useCallback } from 'react';
import { Interpreter } from 'xstate';
import {
ProjectDetailsEvents,
ProjectDetailsState,
} from './project-details.machine';
import { Interpreter } from 'xstate';
export function ProjectDetailsApp({
service,
@@ -26,6 +26,10 @@ export function ProjectDetailsApp({
service,
(state) => state.context.connectedToCloud
);
const disabledTaskSyncGenerators = useSelector(
service,
(state) => state.context.disabledTaskSyncGenerators
);
const handleViewInProjectGraph = useCallback(
(data: { projectName: string }) => {
@@ -83,6 +87,7 @@ export function ProjectDetailsApp({
viewInProjectGraphPosition="bottom"
connectedToCloud={connectedToCloud}
onNxConnect={handleNxConnect}
disabledTaskSyncGenerators={disabledTaskSyncGenerators}
/>
</ExpandedTargetsProvider>
<ErrorToastUI errors={errors} />
@@ -12,6 +12,7 @@ export interface ProjectDetailsState {
sourceMap: null | Record<string, string[]>;
errors?: GraphError[];
connectedToCloud?: boolean;
disabledTaskSyncGenerators?: string[];
}
export type ProjectDetailsEvents = {
@@ -20,6 +21,7 @@ export type ProjectDetailsEvents = {
sourceMap: Record<string, string[]>;
connectedToCloud: boolean;
errors?: GraphError[];
disabledTaskSyncGenerators?: string[];
};
const initialContext: ProjectDetailsState = {
@@ -50,6 +52,7 @@ export const projectDetailsMachine = createMachine<
ctx.sourceMap = event.sourceMap;
ctx.connectedToCloud = event.connectedToCloud;
ctx.errors = event.errors;
ctx.disabledTaskSyncGenerators = event.disabledTaskSyncGenerators;
}),
],
},
+2 -1
View File
@@ -1,7 +1,7 @@
import type { Metadata, Viewport } from 'next';
import AppRouterAnalytics from './app-router-analytics';
import GlobalScripts from './global-scripts';
import { LiveStreamNotifier } from '@nx/nx-dev/ui-common';
import '../styles/main.css';
// Metadata for the entire site
@@ -80,6 +80,7 @@ export default function RootLayout({
</head>
<body className="h-full bg-white text-slate-700 antialiased selection:bg-blue-500 selection:text-white dark:bg-slate-900 dark:text-slate-400 dark:selection:bg-sky-500">
{children}
<LiveStreamNotifier />
<GlobalScripts gaMeasurementId={gaMeasurementId} />
</body>
</html>
+2
View File
@@ -7,6 +7,7 @@ import Script from 'next/script';
import { useEffect } from 'react';
import '../styles/main.css';
import Link from 'next/link';
import { LiveStreamNotifier } from '@nx/nx-dev/ui-common';
export default function CustomApp({
Component,
@@ -79,6 +80,7 @@ export default function CustomApp({
Skip to content
</Link>
<Component {...pageProps} />
<LiveStreamNotifier />
{/* Global Site Tag (gtag.js) - Google Analytics */}
<Script
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

+6
View File
@@ -488,6 +488,7 @@ const nxCloudUrls = {
'/ci/recipes/set-up/connect-to-cloud': '/ci/intro/connect-to-nx-cloud',
'/ci/intro/connect-to-cloud': '/ci/intro/connect-to-nx-cloud',
'/pricing/special-offer': 'https://forms.gle/FBzvsspz1o63fDAz6',
'/powerpack/special-offer': 'https://forms.gle/mWjQo6Vrv5Kt6WYh9',
};
/**
@@ -862,6 +863,10 @@ const missingAndCatchAllRedirects = {
'/packages/:path*': '/nx-api/:path*',
};
const marketing = {
'/conf': 'https://monorepo.world',
};
const movePluginFeaturesToCore = {
'/plugin-features/use-task-executors':
'/concepts/executors-and-configurations',
@@ -1171,4 +1176,5 @@ module.exports = {
blogPosts,
decisionsSection,
featurePagesUpdate,
marketing,
};
+1
View File
@@ -22,6 +22,7 @@ export * from './lib/discord-icon';
export * from './lib/trusted-by';
export * from './lib/testimonials';
export * from './lib/square-dotted-pattern';
export * from './lib/live-stream-notifier';
export { resourceMenuItems } from './lib/headers/menu-items';
export { solutionsMenuItems } from './lib/headers/menu-items';
@@ -18,7 +18,6 @@ import {
solutionsMenuItems,
} from './menu-items';
import { SectionsMenu } from './sections-menu';
import { AnnouncementBanner } from '../announcement-banner';
import { DiscordIcon } from '../discord-icon';
import { NxCloudAnimatedIcon, NxIcon } from '@nx/nx-dev/ui-icons';
@@ -170,9 +169,6 @@ export function DocumentationHeader({
return (
<div className="border-b border-slate-200 bg-slate-50 dark:border-slate-700 dark:bg-slate-800/60 print:hidden">
<div className="hidden w-full md:block">
<AnnouncementBanner />
</div>
<div className="mx-auto flex w-full items-center gap-6 lg:px-8 lg:py-4">
{/*MOBILE MENU*/}
<div className="flex w-full items-center lg:hidden">
@@ -0,0 +1,114 @@
'use client';
import { useState, useEffect, ReactElement } from 'react';
import { motion } from 'framer-motion';
import { MonorepoWorldIcon } from '@nx/nx-dev/ui-icons';
import { ButtonLink } from './button';
import {
PlayIcon,
XMarkIcon,
ChatBubbleLeftRightIcon,
} from '@heroicons/react/24/outline';
export function LiveStreamNotifier(): ReactElement | null {
const [isVisible, setIsVisible] = useState<boolean>(true);
useEffect(() => {
const isClosedSession = sessionStorage.getItem(
'live-stream-notifier-closed'
);
if (isClosedSession === 'true') {
setIsVisible(false);
}
}, []);
const closeNotifier = (e: React.MouseEvent) => {
e.stopPropagation();
setIsVisible(false);
sessionStorage.setItem('live-stream-notifier-closed', 'true');
};
if (!isVisible) return null;
return (
<motion.div
layout
initial={{ y: '120%' }}
animate={{ y: 0 }}
exit={{ y: '120%' }}
transition={{
type: 'spring',
stiffness: 300,
damping: 30,
mass: 1,
}}
className="fixed bottom-0 left-0 right-0 z-30 w-full overflow-hidden bg-slate-950 text-white shadow-lg md:bottom-4 md:left-auto md:right-4 md:w-[512px] md:rounded-lg"
style={{ originY: 1 }}
>
<div className="relative p-4">
<button
onClick={closeNotifier}
className="absolute right-2 top-2 rounded-full p-1 hover:bg-slate-800 focus:outline-none focus:ring-2 focus:ring-white"
>
<XMarkIcon className="size-5" aria-hidden="true" />
<span className="sr-only">Close</span>
</button>
<div>
<motion.h3
layout="position"
className="flex items-center gap-2 pr-8 text-lg font-semibold"
>
<MonorepoWorldIcon
aria-hidden="true"
className="size-8 flex-shrink-0"
/>
<span>Monorepo World live replays available!</span>
</motion.h3>
<motion.div key="live-event" className="mt-4 space-y-4">
<p className="mb-2 text-sm">
Watch the replays of exciting talks on developer tooling and
monorepos! Catch all the insightful presentations from the event
on our YouTube channel.
</p>
<div className="flex flex-wrap items-center gap-1 sm:gap-4">
<a
title="Watch track 1"
href="http://go.nx.dev/MWTrack1"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center justify-center gap-2 rounded-lg bg-[#DDFB24] px-2 py-2 text-sm font-semibold text-black transition hover:bg-[#B2CF04] focus:outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500 active:text-black/70 md:px-4"
>
<PlayIcon aria-hidden="true" className="size-4" />
<span>Track 1</span>
</a>
<a
href="http://go.nx.dev/MWTrack2"
target="_blank"
title="Watch track 2"
rel="noopener noreferrer"
className="inline-flex items-center justify-center gap-2 rounded-lg bg-[#DDFB24] px-2 py-2 text-sm font-semibold text-black transition hover:bg-[#B2CF04] focus:outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500 active:text-black/70 md:px-4"
>
<PlayIcon aria-hidden="true" className="size-4" />
<span>Track 2</span>
</a>
<ButtonLink
variant="secondary"
size="small"
href="https://discord.gg/7yFabzBP"
target="_blank"
title="Join the discussion on Discord"
rel="noopener noreferrer"
>
<ChatBubbleLeftRightIcon
aria-hidden="true"
className="size-4"
/>
<span>#monorepo-world</span>
</ButtonLink>
</div>
</motion.div>
</div>
</div>
</motion.div>
);
}
+12 -52
View File
@@ -6,7 +6,11 @@ import { Theme, useTheme } from '@nx/nx-dev/ui-theme';
import { useState } from 'react';
import Link from 'next/link';
import { useIsomorphicLayoutEffect } from '@nx/nx-dev/ui-primitives';
import { MonorepoWorldIcon } from '@nx/nx-dev/ui-icons';
import {
MonorepoWorldIcon,
RustIcon,
TypeScriptIcon,
} from '@nx/nx-dev/ui-icons';
import { motion, MotionConfig } from 'framer-motion';
export function Hero(): JSX.Element {
@@ -80,57 +84,13 @@ export function Hero(): JSX.Element {
Contact us
</ButtonLink>
</div>
<div className="mt-12 flex justify-center">
<MotionConfig reducedMotion="user">
<motion.div
initial={{
y: 16,
opacity: 0,
}}
whileInView={{
y: 0,
opacity: 1,
}}
viewport={{ once: true }}
transition={{
ease: 'easeOut',
duration: 0.225,
delay: 1,
}}
className="pointer-events-auto relative mx-auto w-full max-w-lg overflow-hidden rounded-lg bg-slate-950 text-left text-white shadow-lg ring-1 ring-white ring-opacity-5 transition hover:bg-slate-800"
>
<div className="p-4">
<div className="flex items-start gap-6">
<div className="-m-4 hidden flex-shrink-0 sm:block">
<img
src="/images/conferences/monorepoworld-vertical-banner.avif"
alt="MonorepoWorld conference image"
className="size-32"
/>
</div>
<div className="w-0 flex-1 pt-1">
<p className="text-base font-semibold">
<a
href="https://monorepo.world/?utm_source=nxdev&utm_medium=website&utm_campaign=homepage_banner&utm_campaign=monorepoworld"
title="Join us at Monorepo World"
target="_blank"
>
<span className="absolute inset-0" />
The Nx team will be at Monorepo World!
</a>
</p>
<p className="mt-1 text-sm text-slate-300">
The ultimate conference for{' '}
<span className="text-[#DDFB24]">monorepos</span> and
developer{' '}
<span className="text-[#DDFB24]">tooling</span> on 0ct.
7. 2024, Mountain View, CA.
</p>
</div>
</div>
</div>
</motion.div>
</MotionConfig>
<div className="mt-4 flex items-center justify-center gap-2 text-sm italic">
Built with
<RustIcon aria-hidden="true" className="size-5 shrink-0" />
<span className="sr-only">Rust</span> for speed &
<TypeScriptIcon aria-hidden="true" className="size-4 shrink-0" />
<span className="sr-only">TypeScript</span> for extensibility.
</div>
</div>
</div>
-2
View File
@@ -56,7 +56,6 @@ import { pill } from './lib/tags/pill.schema';
import { fence } from './lib/nodes/fence.schema';
import { FenceWrapper } from './lib/nodes/fence-wrapper.component';
import { VideoPlayer, videoPlayer } from './lib/tags/video-player.component';
import { td } from './lib/nodes/td.schema';
// TODO fix this export
export { GithubRepository } from './lib/tags/github-repository.component';
@@ -70,7 +69,6 @@ export const getMarkdocCustomConfig = (
heading: getHeadingSchema(headingClass),
image: getImageSchema(documentFilePath),
link,
td,
},
tags: {
callout,
@@ -1,8 +0,0 @@
import { Schema } from '@markdoc/markdoc';
export const td: Schema = {
render: 'td',
attributes: {
className: { type: 'String', default: 'text-center' },
},
};
@@ -23,8 +23,11 @@ export function Tabs({
const [currentTab, setCurrentTab] = useState<string>(labels[0]);
useEffect(() => {
const handleTabSelectedEvent = (defaultTab?: string) => {
const handleTabSelectedEvent = (
tabSelectedEvent: CustomEvent<{ defaultTab?: string }>
) => {
const selectedTab = localStorage.getItem(SELECTED_TAB_KEY);
const defaultTab = tabSelectedEvent.detail.defaultTab;
if (selectedTab && labels.includes(selectedTab)) {
setCurrentTab(selectedTab);
} else if (defaultTab) {
@@ -32,15 +35,23 @@ export function Tabs({
}
};
handleTabSelectedEvent(labels[0]);
window.addEventListener(TAB_SELECTED_EVENT, handleTabSelectedEvent);
handleTabSelectedEvent(
new CustomEvent(TAB_SELECTED_EVENT, { detail: { defaultTab: labels[0] } })
);
window.addEventListener(
TAB_SELECTED_EVENT,
handleTabSelectedEvent as EventListener
);
return () =>
window.removeEventListener(TAB_SELECTED_EVENT, handleTabSelectedEvent);
window.removeEventListener(
TAB_SELECTED_EVENT,
handleTabSelectedEvent as EventListener
);
}, [labels]);
const handleTabClick = (label: string) => {
localStorage.setItem(SELECTED_TAB_KEY, label);
window.dispatchEvent(new Event(TAB_SELECTED_EVENT));
window.dispatchEvent(new CustomEvent(TAB_SELECTED_EVENT, { detail: {} }));
setCurrentTab(label);
};
+12
View File
@@ -2,6 +2,7 @@
import { ButtonLink, SectionHeading, Strong } from '@nx/nx-dev/ui-common';
import { ReactElement, useState, useEffect } from 'react';
import { Dialog, Transition } from '@headlessui/react';
import Link from 'next/link';
const MOBILE_BREAKPOINT = 768;
const YOUTUBE_URL = 'https://youtu.be/KZ0nh2lj8zE?si=D1hkyP3vy36e-VZt';
@@ -60,6 +61,17 @@ export function Hero(): ReactElement {
</span>
</a>
</div>
<p className="mt-6 text-sm italic">
Want to use Powerpack for OSS?
<br />
<Link
href="/powerpack/special-offer"
prefetch={false}
className="font-semibold underline"
>
Apply for a free OSS license.
</Link>
</p>
</div>
{!isMobile && (
@@ -8,7 +8,12 @@ import {
useRef,
useState,
} from 'react';
import { ButtonLink, SectionHeading, Strong } from '@nx/nx-dev/ui-common';
import {
ButtonLink,
SectionHeading,
Strong,
TextLink,
} from '@nx/nx-dev/ui-common';
import { cx } from '@nx/nx-dev/ui-primitives';
import { AnimatedCurvedBeam } from '@nx/nx-dev/ui-animations';
import { CircleStackIcon, ServerIcon } from '@heroicons/react/24/outline';
@@ -35,7 +40,14 @@ export function PowerpackFeatures(): ReactElement {
Nx Powerpack enables you to use <Strong>Amazon S3</Strong> or a{' '}
<Strong>shared network drive</Strong> as your remote cache
storage, offering a flexible, self-managed solution for faster
builds.
builds. Nx Powerpack self-hosted cache storage is{' '}
<TextLink
href="https://cloud.nx.app/powerpack/purchase?utm_source=nx.dev&utm_medium=referral&utm_campaign=nx-powerpackurl"
title="Get a Powerpack license"
>
free for small existing teams
</TextLink>
.
</p>
<div className="mt-16">
<ButtonLink
+4
View File
@@ -1127,6 +1127,10 @@
"ng-packagr": {
"version": "~18.2.0",
"alwaysAddToPackageJson": false
},
"zone.js": {
"version": "~0.14.10",
"alwaysAddToPackageJson": false
}
}
},
@@ -128,10 +128,12 @@ export async function* moduleFederationDevServerExecutor(
// Set NX_MF_DEV_REMOTES for the Nx Runtime Library Control Plugin
process.env.NX_MF_DEV_REMOTES = JSON.stringify([
...(remotes.devRemotes.map((r) =>
typeof r === 'string' ? r : r.remoteName
) ?? []),
project.name,
...(
remotes.devRemotes.map((r) =>
typeof r === 'string' ? r : r.remoteName
) ?? []
).map((r) => r.replace(/-/g, '_')),
project.name.replace(/-/g, '_'),
]);
const staticRemotesConfig = parseStaticRemotesConfig(
@@ -124,8 +124,12 @@ export async function* moduleFederationSsrDevServerExecutor(
// Set NX_MF_DEV_REMOTES for the Nx Runtime Library Control Plugin
process.env.NX_MF_DEV_REMOTES = JSON.stringify([
...(options.devRemotes ?? []),
project.name,
...(
options.devRemotes.map((r) =>
typeof r === 'string' ? r : r.remoteName
) ?? []
).map((r) => r.replace(/-/g, '_')),
project.name.replace(/-/g, '_'),
]);
const devRemotes = await startRemotes(
@@ -12,9 +12,9 @@ import { E2eTestRunner, UnitTestRunner } from '../../utils/test-runners';
describe('federate-module', () => {
let schema: Schema = {
name: 'my-federated-module',
remote: 'my-remote',
path: 'apps/my-remote/src/my-federated-module.ts',
remoteDirectory: 'apps/my-remote',
remote: 'myremote',
path: 'apps/myremote/src/my-federated-module.ts',
remoteDirectory: 'apps/myremote',
};
describe('no remote', () => {
@@ -29,32 +29,32 @@ describe('federate-module', () => {
const projects = getProjects(tree);
expect(projects.get('my-remote').root).toEqual('apps/my-remote');
expect(projects.get('myremote').root).toEqual('apps/myremote');
expect(tree.exists('apps/my-remote/module-federation.config.ts')).toBe(
expect(tree.exists('apps/myremote/module-federation.config.ts')).toBe(
true
);
const content = tree.read(
'apps/my-remote/module-federation.config.ts',
'apps/myremote/module-federation.config.ts',
'utf-8'
);
expect(content).toContain(
`'./my-federated-module': 'apps/my-remote/src/my-federated-module.ts'`
`'./my-federated-module': 'apps/myremote/src/my-federated-module.ts'`
);
const tsconfig = JSON.parse(tree.read('tsconfig.base.json', 'utf-8'));
expect(
tsconfig.compilerOptions.paths['my-remote/my-federated-module']
).toEqual(['apps/my-remote/src/my-federated-module.ts']);
tsconfig.compilerOptions.paths['myremote/my-federated-module']
).toEqual(['apps/myremote/src/my-federated-module.ts']);
});
});
describe('with remote', () => {
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
let remoteSchema: remoteSchma = {
name: 'my-remote',
directory: 'my-remote',
name: 'myremote',
directory: 'myremote',
e2eTestRunner: E2eTestRunner.Cypress,
skipFormat: true,
linter: Linter.EsLint,
@@ -78,7 +78,7 @@ describe('federate-module', () => {
);
expect(content).not.toContain(
`'./my-federated-module': 'apps/my-remote/src/my-federated-module.ts'`
`'./my-federated-module': 'apps/myremote/src/my-federated-module.ts'`
);
await federateModuleGenerator(tree, {
@@ -92,7 +92,7 @@ describe('federate-module', () => {
'utf-8'
);
expect(content).toContain(
`'./my-federated-module': 'apps/my-remote/src/my-federated-module.ts'`
`'./my-federated-module': 'apps/myremote/src/my-federated-module.ts'`
);
const tsconfig = JSON.parse(tree.read('tsconfig.base.json', 'utf-8'));
@@ -100,7 +100,7 @@ describe('federate-module', () => {
tsconfig.compilerOptions.paths[
`${remoteSchema.name}/my-federated-module`
]
).toEqual(['apps/my-remote/src/my-federated-module.ts']);
).toEqual(['apps/myremote/src/my-federated-module.ts']);
});
});
});
@@ -19,6 +19,7 @@ import { UsersFacade } from './+state/users.facade';
imports: [
BrowserModule,
RouterModule.forRoot(appRoutes),
EffectsModule.forRoot([]),
StoreModule.forRoot(
{},
{
@@ -29,7 +30,6 @@ import { UsersFacade } from './+state/users.facade';
},
}
),
EffectsModule.forRoot([]),
StoreRouterConnectingModule.forRoot(),
StoreModule.forFeature(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
EffectsModule.forFeature([UsersEffects]),
@@ -90,6 +90,7 @@ import { UsersEffects } from './+state/users.effects';
imports: [
BrowserModule,
RouterModule.forRoot(appRoutes),
EffectsModule.forRoot([]),
StoreModule.forRoot(
{},
{
@@ -100,7 +101,6 @@ import { UsersEffects } from './+state/users.effects';
},
}
),
EffectsModule.forRoot([]),
StoreRouterConnectingModule.forRoot(),
StoreModule.forFeature(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),
EffectsModule.forFeature([UsersEffects]),
@@ -373,6 +373,7 @@ import { StoreRouterConnectingModule } from '@ngrx/router-store';
imports: [
BrowserModule,
RouterModule.forRoot(appRoutes),
EffectsModule.forRoot([]),
StoreModule.forRoot({}, {
metaReducers: [],
runtimeChecks: {
@@ -380,7 +381,6 @@ import { StoreRouterConnectingModule } from '@ngrx/router-store';
strictStateImmutability: true
}
}),
EffectsModule.forRoot([]),
StoreRouterConnectingModule.forRoot(),
],
providers: [],
@@ -399,14 +399,16 @@ import { appRoutes } from './app.routes';
import { NxWelcomeComponent } from './nx-welcome.component';
import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { StoreRouterConnectingModule } from '@ngrx/router-store';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { StoreRouterConnectingModule } from '@ngrx/router-store';
@NgModule({
declarations: [AppComponent, NxWelcomeComponent],
imports: [
BrowserModule,
RouterModule.forRoot(appRoutes),
EffectsModule.forRoot([]),
StoreDevtoolsModule.instrument({ logOnly: !isDevMode() }),
StoreModule.forRoot({}, {
metaReducers: [],
runtimeChecks: {
@@ -414,9 +416,7 @@ import { StoreDevtoolsModule } from '@ngrx/store-devtools';
strictStateImmutability: true
}
}),
EffectsModule.forRoot([]),
StoreRouterConnectingModule.forRoot(),
StoreDevtoolsModule.instrument({ logOnly: !isDevMode() }),
],
providers: [],
bootstrap: [AppComponent],
@@ -436,7 +436,7 @@ import { UsersEffects } from './+state/users.effects';
import { UsersFacade } from './+state/users.facade';
export const appConfig: ApplicationConfig = {
providers: [provideEffects(UsersEffects),provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),UsersFacade,provideEffects(),provideStore(),provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes) ]
providers: [provideEffects(UsersEffects),provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),UsersFacade,provideStore(),provideEffects(),provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes) ]
};
"
`;
@@ -482,7 +482,7 @@ import * as fromUsers from './+state/users.reducer';
import { UsersEffects } from './+state/users.effects';
export const appConfig: ApplicationConfig = {
providers: [provideEffects(UsersEffects),provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),provideEffects(),provideStore(),provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes) ]
providers: [provideEffects(UsersEffects),provideState(fromUsers.USERS_FEATURE_KEY, fromUsers.usersReducer),provideStore(),provideEffects(),provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes) ]
};
"
`;
@@ -729,7 +729,7 @@ import { provideStore } from '@ngrx/store';
import { provideEffects } from '@ngrx/effects';
export const appConfig: ApplicationConfig = {
providers: [provideEffects(),provideStore(),provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes) ]
providers: [provideStore(),provideEffects(),provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes) ]
};
"
`;
@@ -743,7 +743,7 @@ import { provideEffects } from '@ngrx/effects';
import { provideStoreDevtools } from '@ngrx/store-devtools';
export const appConfig: ApplicationConfig = {
providers: [provideStoreDevtools({ logOnly: !isDevMode() }),provideEffects(),provideStore(),provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes) ]
providers: [provideStore(),provideStoreDevtools({ logOnly: !isDevMode() }),provideEffects(),provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(appRoutes) ]
};
"
`;
@@ -181,15 +181,6 @@ export function addImportsToModule(
sourceFile = addImport(sourceFile, 'EffectsModule', '@ngrx/effects');
}
sourceFile = addRootStoreImport(
tree,
isParentStandalone,
sourceFile,
parentPath,
provideRootStore,
storeForRoot
);
sourceFile = addRootEffectsImport(
tree,
isParentStandalone,
@@ -199,6 +190,25 @@ export function addImportsToModule(
effectsForEmptyRoot
);
if (options.addDevTools) {
sourceFile = addStoreDevTools(
tree,
sourceFile,
parentPath,
isParentStandalone,
addImport
);
}
sourceFile = addRootStoreImport(
tree,
isParentStandalone,
sourceFile,
parentPath,
provideRootStore,
storeForRoot
);
// this is just a heuristic
const hasRouter = sourceText.indexOf('RouterModule') > -1;
@@ -211,14 +221,4 @@ export function addImportsToModule(
storeRouterModule
);
}
if (options.addDevTools) {
sourceFile = addStoreDevTools(
tree,
sourceFile,
parentPath,
isParentStandalone,
addImport
);
}
}
@@ -443,4 +443,19 @@ describe('MF Remote App Generator', () => {
const packageJson = readJson(tree, 'package.json');
expect(packageJson).toEqual(initialPackageJson);
});
it('should error when an invalid remote name is passed to the remote generator', async () => {
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
await expect(
generateTestRemoteApplication(tree, {
directory: 'test/my-remote',
})
).rejects.toMatchInlineSnapshot(`
[Error: Invalid remote name: my-remote. Remote project names must:
- Start with a letter, dollar sign ($) or underscore (_)
- Followed by any valid character (letters, digits, underscores, or dollar signs)
The regular expression used is ^[a-zA-Z_$][a-zA-Z_$0-9]*$.]
`);
});
});
@@ -3,6 +3,7 @@ import {
formatFiles,
getProjects,
runTasksInSerial,
stripIndents,
Tree,
} from '@nx/devkit';
import {
@@ -39,6 +40,16 @@ export async function remote(tree: Tree, schema: Schema) {
directory: options.directory,
});
const REMOTE_NAME_REGEX = '^[a-zA-Z_$][a-zA-Z_$0-9]*$';
const remoteNameRegex = new RegExp(REMOTE_NAME_REGEX);
if (!remoteNameRegex.test(remoteProjectName)) {
throw new Error(
stripIndents`Invalid remote name: ${remoteProjectName}. Remote project names must:
- Start with a letter, dollar sign ($) or underscore (_)
- Followed by any valid character (letters, digits, underscores, or dollar signs)
The regular expression used is ${REMOTE_NAME_REGEX}.`
);
}
const port = options.port ?? findNextAvailablePort(tree);
const appInstallTask = await applicationGenerator(tree, {
@@ -166,8 +166,11 @@ function addLazyLoadedRouteToHostAppModule(
: 'RemoteEntryModule';
const routeToAdd =
hostFederationType === 'dynamic'
? `loadRemoteModule('${options.appName}', './${routePathName}')`
: `import('${options.appName}/${routePathName}')`;
? `loadRemoteModule('${options.appName.replace(
/-/g,
'_'
)}', './${routePathName}')`
: `import('${options.appName.replace(/-/g, '_')}/${routePathName}')`;
addRoute(
tree,
@@ -12,7 +12,7 @@ export function setupTspathForRemote(tree: Tree, options: Schema) {
const exportName = options.standalone ? 'Routes' : 'Module';
addTsConfigPath(tree, `${options.appName}/${exportName}`, [
addTsConfigPath(tree, `${options.appName.replace(/-/g, '_')}/${exportName}`, [
joinPathFragments(project.root, exportPath),
]);
}
@@ -19,7 +19,7 @@ export function spawnAndWait(command: string, args: string[], cwd: string) {
ESLINT_USE_FLAT_CONFIG: process.env.ESLINT_USE_FLAT_CONFIG ?? 'true',
},
shell: true,
windowsHide: true,
windowsHide: false,
});
childProcess.on('exit', (code) => {
@@ -36,7 +36,7 @@ export function execAndWait(command: string, cwd: string) {
return new Promise<{ code: number; stdout: string }>((res, rej) => {
exec(
command,
{ cwd, env: { ...process.env, NX_DAEMON: 'false' }, windowsHide: true },
{ cwd, env: { ...process.env, NX_DAEMON: 'false' }, windowsHide: false },
(error, stdout, stderr) => {
if (error) {
const logFile = join(cwd, 'error.log');
@@ -8,7 +8,7 @@ export function deduceDefaultBase(): string {
const nxDefaultBase = 'main';
try {
return (
execSync('git config --get init.defaultBranch', { windowsHide: true })
execSync('git config --get init.defaultBranch', { windowsHide: false })
.toString()
.trim() || nxDefaultBase
);
@@ -4,7 +4,7 @@ import { output } from '../output';
export function checkGitVersion(): string | null | undefined {
try {
let gitVersionOutput = execSync('git --version', { windowsHide: true })
let gitVersionOutput = execSync('git --version', { windowsHide: false })
.toString()
.trim();
return gitVersionOutput.match(/[0-9]+\.[0-9]+\.+[0-9]+/)?.[0];
@@ -43,7 +43,7 @@ export async function initializeGitRepo(
}
: {}),
},
windowsHide: true,
windowsHide: false,
};
return new Promise<void>((resolve, reject) => {
spawn('git', args, spawnOptions).on('close', (code) => {
@@ -139,7 +139,7 @@ function shouldRecordStats(): boolean {
try {
const stdout = execSync(pmc.getRegistryUrl, {
encoding: 'utf-8',
windowsHide: true,
windowsHide: false,
});
const url = new URL(stdout.trim());
@@ -9,7 +9,7 @@ export function showNxWarning(workspaceName: string) {
execSync('nx --version', {
cwd: pathToRunNxCommand,
stdio: ['ignore', 'ignore', 'ignore'],
windowsHide: true,
windowsHide: false,
});
} catch (e) {
// no nx found
@@ -123,7 +123,7 @@ export function getPackageManagerVersion(
const version = execSync(`${packageManager} --version`, {
cwd,
encoding: 'utf-8',
windowsHide: true,
windowsHide: false,
}).trim();
pmVersionCache.set(packageManager, version);
return version;
+2 -2
View File
@@ -78,14 +78,14 @@ function startWebServer(webServerCommand: string) {
// Windows is fine so we leave it attached to this process
detached: process.platform !== 'win32',
stdio: 'inherit',
windowsHide: true,
windowsHide: false,
});
return () => {
if (process.platform === 'win32') {
try {
execSync('taskkill /pid ' + serverProcess.pid + ' /T /F', {
windowsHide: true,
windowsHide: false,
});
} catch (e) {
if (process.env.NX_VERBOSE_LOGGING === 'true') {
@@ -43,7 +43,7 @@ export function installPackagesTask(
const execSyncOptions: ExecSyncOptions = {
cwd: join(tree.root, cwd),
stdio: process.env.NX_GENERATE_QUIET === 'true' ? 'ignore' : 'inherit',
windowsHide: true,
windowsHide: false,
};
// ensure local registry from process is not interfering with the install
// when we start the process from temp folder the local registry would override the custom registry
+2 -2
View File
@@ -497,7 +497,7 @@ export function ensurePackage<T extends any = any>(
execSync(preInstallCommand, {
cwd: tempDir,
stdio: isVerbose ? 'inherit' : 'ignore',
windowsHide: true,
windowsHide: false,
});
}
let addCommand = getPackageManagerCommand(packageManager).addDev;
@@ -508,7 +508,7 @@ export function ensurePackage<T extends any = any>(
execSync(`${addCommand} ${pkg}@${requiredVersion}`, {
cwd: tempDir,
stdio: isVerbose ? 'inherit' : 'ignore',
windowsHide: true,
windowsHide: false,
});
addToNodePath(join(workspaceRoot, 'node_modules'));
@@ -23,8 +23,10 @@ const isPrettierAvailable =
* related plugins and rules below.
*/
export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommended,
{
files: ['**/*.js', '**/*.jsx'],
extends: [eslint.configs.recommended, ...tseslint.configs.recommended],
},
...(isPrettierAvailable ? [require('eslint-config-prettier')] : []),
{
languageOptions: {
@@ -14,8 +14,10 @@ const isPrettierAvailable =
* to one ecosystem, such as React, Angular, Node etc.
*/
export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommended,
{
files: ['**/*.ts', '**/*.tsx'],
extends: [eslint.configs.recommended, ...tseslint.configs.recommended],
},
...(isPrettierAvailable ? [require('eslint-config-prettier')] : []),
{
plugins: { '@typescript-eslint': tseslint.plugin },
@@ -114,7 +114,7 @@ function copyPackageJsonAndLock(
packageManager: PackageManager,
workspaceRoot: string,
projectRoot: string
) {
): () => void {
const packageJson = pathResolve(workspaceRoot, 'package.json');
const rootPackageJson = readJsonFile<PackageJson>(packageJson);
// do not copy package.json and lock file if workspaces are enabled
@@ -123,7 +123,8 @@ function copyPackageJsonAndLock(
existsSync(pathResolve(workspaceRoot, 'pnpm-workspace.yaml'))) ||
rootPackageJson.workspaces
) {
return;
// no resource taken, no resource cleaned up
return () => {};
}
const packageJsonProject = pathResolve(projectRoot, 'package.json');
+2 -2
View File
@@ -68,7 +68,7 @@ export function podInstall(
execSync('touch .xcode.env', {
cwd: iosDirectory,
stdio: 'inherit',
windowsHide: true,
windowsHide: false,
});
}
execSync(
@@ -78,7 +78,7 @@ export function podInstall(
{
cwd: iosDirectory,
stdio: 'inherit',
windowsHide: true,
windowsHide: false,
}
);
} catch (e) {
+2 -2
View File
@@ -11,13 +11,13 @@ export function resolveEas(workspaceRoot: string): string {
let npmGlobalPath: string, yarnGlobalPath: string;
try {
npmGlobalPath = execSync('npm root -g', { windowsHide: true })
npmGlobalPath = execSync('npm root -g', { windowsHide: false })
?.toString()
?.trim()
?.replace('\u001b[2K\u001b[1G', ''); // strip out ansi codes
} catch {}
try {
yarnGlobalPath = execSync('yarn global dir', { windowsHide: true })
yarnGlobalPath = execSync('yarn global dir', { windowsHide: false })
?.toString()
?.trim()
?.replace('\u001b[2K\u001b[1G', ''); // strip out ansi codes
@@ -21,7 +21,7 @@ export async function killTree(pid: number, signal: NodeJS.Signals) {
exec(
'taskkill /pid ' + pid + ' /T /F',
{
windowsHide: true,
windowsHide: false,
},
(error) => {
// Ignore Fatal errors (128) because it might be due to the process already being killed.
@@ -37,7 +37,7 @@ export async function killTree(pid: number, signal: NodeJS.Signals) {
pidsToProcess,
function (parentPid) {
return spawn('pgrep', ['-P', parentPid], {
windowsHide: true,
windowsHide: false,
});
},
function () {
@@ -55,7 +55,7 @@ export async function killTree(pid: number, signal: NodeJS.Signals) {
'ps',
['-o', 'pid', '--no-headers', '--ppid', parentPid],
{
windowsHide: true,
windowsHide: false,
}
);
},
@@ -128,7 +128,7 @@ Please update the local dependency on "${depName}" to be a valid semantic versio
env: processEnv(true),
cwd: context.root,
stdio: ['ignore', 'pipe', 'pipe'],
windowsHide: true,
windowsHide: false,
});
const resultJson = JSON.parse(result.toString());
@@ -154,7 +154,7 @@ Please update the local dependency on "${depName}" to be a valid semantic versio
env: processEnv(true),
cwd: context.root,
stdio: 'ignore',
windowsHide: true,
windowsHide: false,
});
console.log(
`Added the dist-tag ${tag} to v${currentVersion} for registry ${registry}.\n`
@@ -269,7 +269,7 @@ Please update the local dependency on "${depName}" to be a valid semantic versio
env: processEnv(true),
cwd: context.root,
stdio: ['ignore', 'pipe', 'pipe'],
windowsHide: true,
windowsHide: false,
});
/**
@@ -49,12 +49,12 @@ export async function verdaccioExecutor(
options.location === 'none' ? [] : [setupNpm(options), setupYarn(options)];
const processExitListener = (signal?: number | NodeJS.Signals) => {
if (childProcess) {
childProcess.kill(signal);
}
for (const fn of cleanupFunctions) {
fn();
}
if (childProcess) {
childProcess.kill(signal);
}
};
process.on('exit', processExitListener);
process.on('SIGTERM', processExitListener);
@@ -136,7 +136,7 @@ function createVerdaccioOptions(
function setupNpm(options: VerdaccioExecutorSchema) {
try {
execSync('npm --version', { env, windowsHide: true });
execSync('npm --version', { env, windowsHide: false });
} catch (e) {
return () => {};
}
@@ -151,7 +151,7 @@ function setupNpm(options: VerdaccioExecutorSchema) {
npmRegistryPaths.push(
execSync(
`npm config get ${registryName} --location ${options.location}`,
{ env, windowsHide: true }
{ env, windowsHide: false }
)
?.toString()
?.trim()
@@ -159,12 +159,12 @@ function setupNpm(options: VerdaccioExecutorSchema) {
);
execSync(
`npm config set ${registryName} http://localhost:${options.port}/ --location ${options.location}`,
{ env, windowsHide: true }
{ env, windowsHide: false }
);
execSync(
`npm config set //localhost:${options.port}/:_authToken="secretVerdaccioToken" --location ${options.location}`,
{ env, windowsHide: true }
{ env, windowsHide: false }
);
logger.info(
@@ -181,7 +181,7 @@ function setupNpm(options: VerdaccioExecutorSchema) {
try {
const currentNpmRegistryPath = execSync(
`npm config get registry --location ${options.location}`,
{ env, windowsHide: true }
{ env, windowsHide: false }
)
?.toString()
?.trim()
@@ -194,7 +194,7 @@ function setupNpm(options: VerdaccioExecutorSchema) {
) {
execSync(
`npm config set ${registryName} ${npmRegistryPaths[index]} --location ${options.location}`,
{ env, windowsHide: true }
{ env, windowsHide: false }
);
logger.info(
`Reset npm ${registryName} to ${npmRegistryPaths[index]}`
@@ -204,7 +204,7 @@ function setupNpm(options: VerdaccioExecutorSchema) {
`npm config delete ${registryName} --location ${options.location}`,
{
env,
windowsHide: true,
windowsHide: false,
}
);
logger.info('Cleared custom npm registry');
@@ -212,7 +212,7 @@ function setupNpm(options: VerdaccioExecutorSchema) {
});
execSync(
`npm config delete //localhost:${options.port}/:_authToken --location ${options.location}`,
{ env, windowsHide: true }
{ env, windowsHide: false }
);
} catch (e) {
throw new Error(`Failed to reset npm registry: ${e.message}`);
@@ -231,7 +231,7 @@ function getYarnUnsafeHttpWhitelist(isYarnV1: boolean) {
JSON.parse(
execSync(`yarn config get unsafeHttpWhitelist --json`, {
env,
windowsHide: true,
windowsHide: false,
}).toString()
)
)
@@ -247,13 +247,13 @@ function setYarnUnsafeHttpWhitelist(
`yarn config set unsafeHttpWhitelist --json '${JSON.stringify(
Array.from(currentWhitelist)
)}'` + (options.location === 'user' ? ' --home' : ''),
{ env, windowsHide: true }
{ env, windowsHide: false }
);
} else {
execSync(
`yarn config unset unsafeHttpWhitelist` +
(options.location === 'user' ? ' --home' : ''),
{ env, windowsHide: true }
{ env, windowsHide: false }
);
}
}
@@ -266,7 +266,9 @@ function setupYarn(options: VerdaccioExecutorSchema) {
try {
isYarnV1 =
major(
execSync('yarn --version', { env, windowsHide: true }).toString().trim()
execSync('yarn --version', { env, windowsHide: false })
.toString()
.trim()
) === 1;
} catch {
// This would fail if yarn is not installed which is okay
@@ -281,7 +283,7 @@ function setupYarn(options: VerdaccioExecutorSchema) {
yarnRegistryPaths.push(
execSync(`yarn config get ${scopeName}${registryConfigName}`, {
env,
windowsHide: true,
windowsHide: false,
})
?.toString()
?.trim()
@@ -291,7 +293,7 @@ function setupYarn(options: VerdaccioExecutorSchema) {
execSync(
`yarn config set ${scopeName}${registryConfigName} http://localhost:${options.port}/` +
(options.location === 'user' ? ' --home' : ''),
{ env, windowsHide: true }
{ env, windowsHide: false }
);
logger.info(
@@ -318,7 +320,7 @@ function setupYarn(options: VerdaccioExecutorSchema) {
try {
const currentYarnRegistryPath = execSync(
`yarn config get ${registryConfigName}`,
{ env, windowsHide: true }
{ env, windowsHide: false }
)
?.toString()
?.trim()
@@ -339,7 +341,7 @@ function setupYarn(options: VerdaccioExecutorSchema) {
{
env,
windowsHide: true,
windowsHide: false,
}
);
logger.info(
@@ -349,7 +351,7 @@ function setupYarn(options: VerdaccioExecutorSchema) {
execSync(
`yarn config ${isYarnV1 ? 'delete' : 'unset'} ${registryName}` +
(options.location === 'user' ? ' --home' : ''),
{ env, windowsHide: true }
{ env, windowsHide: false }
);
logger.info(`Cleared custom yarn ${registryConfigName}`);
}
@@ -213,7 +213,7 @@ To fix this you will either need to add a package.json file at that location, or
exec(
`npm view ${packageName} version --"${registryConfigKey}=${registry}" --tag=${tag}`,
{
windowsHide: true,
windowsHide: false,
},
(error, stdout, stderr) => {
if (error) {
@@ -133,7 +133,7 @@ function execLockFileUpdate(
...process.env,
...env,
},
windowsHide: true,
windowsHide: false,
});
} catch (e) {
output.error({
@@ -23,7 +23,7 @@ export async function setupVerdaccio(
generateFiles(tree, path.join(__dirname, 'files'), '.verdaccio', {
npmUplinkRegistry:
execSync('npm config get registry', {
windowsHide: true,
windowsHide: false,
})
?.toString()
?.trim() ?? 'https://registry.npmjs.org',
@@ -51,6 +51,12 @@ type GeneratorOptions = {
};
type NormalizedGeneratorOptions = Required<GeneratorOptions>;
type TsconfigInfoCaches = {
composite: Map<string, boolean>;
content: Map<string, string>;
exists: Map<string, boolean>;
isFile: Map<string, boolean>;
};
export async function syncGenerator(tree: Tree): Promise<SyncGeneratorResult> {
// Ensure that the plugin has been wired up in nx.json
@@ -71,24 +77,28 @@ export async function syncGenerator(tree: Tree): Promise<SyncGeneratorResult> {
]);
}
const tsconfigInfoCaches: TsconfigInfoCaches = {
composite: new Map(),
content: new Map(),
exists: new Map(),
isFile: new Map(),
};
// Root tsconfig containing project references for the whole workspace
const rootTsconfigPath = 'tsconfig.json';
if (!tree.exists(rootTsconfigPath)) {
if (!tsconfigExists(tree, tsconfigInfoCaches, rootTsconfigPath)) {
throw new SyncError('Missing root "tsconfig.json"', [
`A "tsconfig.json" file must exist in the workspace root in order to sync the project graph information to the TypeScript configuration files.`,
]);
}
const rawTsconfigContentsCache = new Map<string, string>();
const stringifiedRootJsonContents = readRawTsconfigContents(
tree,
rawTsconfigContentsCache,
tsconfigInfoCaches,
rootTsconfigPath
);
const rootTsconfig = parseJson<Tsconfig>(stringifiedRootJsonContents);
const projectGraph = await createProjectGraphAsync();
const projectRoots = new Set<string>();
const tsconfigHasCompositeEnabledCache = new Map<string, boolean>();
const tsconfigProjectNodeValues = Object.values(projectGraph.nodes).filter(
(node) => {
@@ -97,18 +107,17 @@ export async function syncGenerator(tree: Tree): Promise<SyncGeneratorResult> {
node.data.root,
'tsconfig.json'
);
return tsconfigExists(
tree,
rawTsconfigContentsCache,
projectTsconfigPath
);
return tsconfigExists(tree, tsconfigInfoCaches, projectTsconfigPath);
}
);
const tsSysFromTree: ts.System = {
...ts.sys,
fileExists(path) {
return tsconfigExists(tree, tsconfigInfoCaches, path);
},
readFile(path) {
return readRawTsconfigContents(tree, rawTsconfigContentsCache, path);
return readRawTsconfigContents(tree, tsconfigInfoCaches, path);
},
};
@@ -125,9 +134,10 @@ export async function syncGenerator(tree: Tree): Promise<SyncGeneratorResult> {
const resolvedRefPath = getTsConfigPathFromReferencePath(
tree,
rootTsconfigPath,
ref.path
ref.path,
tsconfigInfoCaches
);
if (tsconfigExists(tree, rawTsconfigContentsCache, resolvedRefPath)) {
if (tsconfigExists(tree, tsconfigInfoCaches, resolvedRefPath)) {
// we only keep the references that still exist
referencesSet.add(normalizeReferencePath(ref.path));
} else {
@@ -150,7 +160,7 @@ export async function syncGenerator(tree: Tree): Promise<SyncGeneratorResult> {
.filter((ref) =>
hasCompositeEnabled(
tsSysFromTree,
tsconfigHasCompositeEnabledCache,
tsconfigInfoCaches,
joinPathFragments(ref, 'tsconfig.json')
)
)
@@ -159,7 +169,7 @@ export async function syncGenerator(tree: Tree): Promise<SyncGeneratorResult> {
}));
patchTsconfigJsonReferences(
tree,
rawTsconfigContentsCache,
tsconfigInfoCaches,
rootTsconfigPath,
updatedReferences
);
@@ -192,9 +202,7 @@ export async function syncGenerator(tree: Tree): Promise<SyncGeneratorResult> {
sourceProjectNode.data.root,
'tsconfig.json'
);
if (
!tsconfigExists(tree, rawTsconfigContentsCache, sourceProjectTsconfigPath)
) {
if (!tsconfigExists(tree, tsconfigInfoCaches, sourceProjectTsconfigPath)) {
if (process.env.NX_VERBOSE_LOGGING === 'true') {
logger.warn(
`Skipping project "${projectName}" as there is no tsconfig.json file found in the project root "${sourceProjectNode.data.root}".`
@@ -216,9 +224,7 @@ export async function syncGenerator(tree: Tree): Promise<SyncGeneratorResult> {
sourceProjectNode.data.root,
runtimeTsConfigFileName
);
if (
!tsconfigExists(tree, rawTsconfigContentsCache, runtimeTsConfigPath)
) {
if (!tsconfigExists(tree, tsconfigInfoCaches, runtimeTsConfigPath)) {
continue;
}
@@ -227,8 +233,7 @@ export async function syncGenerator(tree: Tree): Promise<SyncGeneratorResult> {
updateTsConfigReferences(
tree,
tsSysFromTree,
rawTsconfigContentsCache,
tsconfigHasCompositeEnabledCache,
tsconfigInfoCaches,
runtimeTsConfigPath,
dependencies,
sourceProjectNode.data.root,
@@ -243,8 +248,7 @@ export async function syncGenerator(tree: Tree): Promise<SyncGeneratorResult> {
updateTsConfigReferences(
tree,
tsSysFromTree,
rawTsconfigContentsCache,
tsconfigHasCompositeEnabledCache,
tsconfigInfoCaches,
sourceProjectTsconfigPath,
dependencies,
sourceProjectNode.data.root,
@@ -270,16 +274,17 @@ export default syncGenerator;
*/
function readRawTsconfigContents(
tree: Tree,
rawTsconfigContentsCache: Map<string, string>,
tsconfigInfoCaches: TsconfigInfoCaches,
tsconfigPath: string
): string {
if (!rawTsconfigContentsCache.has(tsconfigPath)) {
rawTsconfigContentsCache.set(
if (!tsconfigInfoCaches.content.has(tsconfigPath)) {
tsconfigInfoCaches.content.set(
tsconfigPath,
tree.read(tsconfigPath, 'utf-8')
);
}
return rawTsconfigContentsCache.get(tsconfigPath);
return tsconfigInfoCaches.content.get(tsconfigPath);
}
/**
@@ -288,19 +293,20 @@ function readRawTsconfigContents(
*/
function tsconfigExists(
tree: Tree,
rawTsconfigContentsCache: Map<string, string>,
tsconfigInfoCaches: TsconfigInfoCaches,
tsconfigPath: string
): boolean {
return rawTsconfigContentsCache.has(tsconfigPath)
? true
: tree.exists(tsconfigPath);
if (!tsconfigInfoCaches.exists.has(tsconfigPath)) {
tsconfigInfoCaches.exists.set(tsconfigPath, tree.exists(tsconfigPath));
}
return tsconfigInfoCaches.exists.get(tsconfigPath);
}
function updateTsConfigReferences(
tree: Tree,
tsSysFromTree: ts.System,
rawTsconfigContentsCache: Map<string, string>,
tsconfigHasCompositeEnabledCache: Map<string, boolean>,
tsconfigInfoCaches: TsconfigInfoCaches,
tsConfigPath: string,
dependencies: ProjectGraphProjectNode[],
projectRoot: string,
@@ -310,7 +316,7 @@ function updateTsConfigReferences(
): boolean {
const stringifiedJsonContents = readRawTsconfigContents(
tree,
rawTsconfigContentsCache,
tsconfigInfoCaches,
tsConfigPath
);
const tsConfig = parseJson<Tsconfig>(stringifiedJsonContents);
@@ -335,12 +341,13 @@ function updateTsConfigReferences(
const resolvedRefPath = getTsConfigPathFromReferencePath(
tree,
tsConfigPath,
ref.path
ref.path,
tsconfigInfoCaches
);
if (
isProjectReferenceWithinNxProject(
tree,
rawTsconfigContentsCache,
tsconfigInfoCaches,
resolvedRefPath,
projectRoot,
projectRoots
@@ -362,12 +369,12 @@ function updateTsConfigReferences(
dep.data.root,
runtimeTsConfigFileName
);
if (tsconfigExists(tree, rawTsconfigContentsCache, runtimeTsConfigPath)) {
if (tsconfigExists(tree, tsconfigInfoCaches, runtimeTsConfigPath)) {
// Check composite is true in the dependency runtime tsconfig file before proceeding
if (
!hasCompositeEnabled(
tsSysFromTree,
tsconfigHasCompositeEnabledCache,
tsconfigInfoCaches,
runtimeTsConfigPath
)
) {
@@ -386,7 +393,7 @@ function updateTsConfigReferences(
if (
tsconfigExists(
tree,
rawTsconfigContentsCache,
tsconfigInfoCaches,
possibleRuntimeTsConfigPath
)
) {
@@ -394,7 +401,7 @@ function updateTsConfigReferences(
if (
!hasCompositeEnabled(
tsSysFromTree,
tsconfigHasCompositeEnabledCache,
tsconfigInfoCaches,
possibleRuntimeTsConfigPath
)
) {
@@ -410,7 +417,7 @@ function updateTsConfigReferences(
if (
!hasCompositeEnabled(
tsSysFromTree,
tsconfigHasCompositeEnabledCache,
tsconfigInfoCaches,
joinPathFragments(dep.data.root, 'tsconfig.json')
)
) {
@@ -433,7 +440,7 @@ function updateTsConfigReferences(
if (hasChanges) {
patchTsconfigJsonReferences(
tree,
rawTsconfigContentsCache,
tsconfigInfoCaches,
tsConfigPath,
references
);
@@ -508,14 +515,14 @@ function normalizeReferencePath(path: string): string {
function isProjectReferenceWithinNxProject(
tree: Tree,
rawTsconfigContentsCache: Map<string, string>,
tsconfigInfoCaches: TsconfigInfoCaches,
refTsConfigPath: string,
projectRoot: string,
projectRoots: Set<string>
): boolean {
let currentPath = getTsConfigDirName(
tree,
rawTsconfigContentsCache,
tsconfigInfoCaches,
refTsConfigPath
);
@@ -554,14 +561,10 @@ function isProjectReferenceIgnored(
function getTsConfigDirName(
tree: Tree,
rawTsconfigContentsCache: Map<string, string>,
tsconfigInfoCaches: TsconfigInfoCaches,
tsConfigPath: string
): string {
return (
rawTsconfigContentsCache.has(tsConfigPath)
? true
: tree.isFile(tsConfigPath)
)
return tsconfigIsFile(tree, tsconfigInfoCaches, tsConfigPath)
? dirname(tsConfigPath)
: normalize(tsConfigPath);
}
@@ -569,14 +572,15 @@ function getTsConfigDirName(
function getTsConfigPathFromReferencePath(
tree: Tree,
ownerTsConfigPath: string,
referencePath: string
referencePath: string,
tsconfigInfoCaches: TsconfigInfoCaches
): string {
const resolvedRefPath = joinPathFragments(
dirname(ownerTsConfigPath),
referencePath
);
return tree.isFile(resolvedRefPath)
return tsconfigIsFile(tree, tsconfigInfoCaches, resolvedRefPath)
? resolvedRefPath
: joinPathFragments(resolvedRefPath, 'tsconfig.json');
}
@@ -587,13 +591,13 @@ function getTsConfigPathFromReferencePath(
*/
function patchTsconfigJsonReferences(
tree: Tree,
rawTsconfigContentsCache: Map<string, string>,
tsconfigInfoCaches: TsconfigInfoCaches,
tsconfigPath: string,
updatedReferences: { path: string }[]
) {
const stringifiedJsonContents = readRawTsconfigContents(
tree,
rawTsconfigContentsCache,
tsconfigInfoCaches,
tsconfigPath
);
const edits = modify(
@@ -609,17 +613,40 @@ function patchTsconfigJsonReferences(
function hasCompositeEnabled(
tsSysFromTree: ts.System,
tsconfigHasCompositeEnabledCache: Map<string, boolean>,
tsconfigInfoCaches: TsconfigInfoCaches,
tsconfigPath: string
): boolean {
if (!tsconfigHasCompositeEnabledCache.has(tsconfigPath)) {
if (!tsconfigInfoCaches.composite.has(tsconfigPath)) {
const parsed = ts.parseJsonConfigFileContent(
ts.readConfigFile(tsconfigPath, tsSysFromTree.readFile).config,
tsSysFromTree,
dirname(tsconfigPath)
);
const enabledVal = parsed.options.composite === true;
tsconfigHasCompositeEnabledCache.set(tsconfigPath, enabledVal);
tsconfigInfoCaches.composite.set(
tsconfigPath,
parsed.options.composite === true
);
}
return tsconfigHasCompositeEnabledCache.get(tsconfigPath);
return tsconfigInfoCaches.composite.get(tsconfigPath);
}
function tsconfigIsFile(
tree: Tree,
tsconfigInfoCaches: TsconfigInfoCaches,
tsconfigPath: string
): boolean {
if (tsconfigInfoCaches.isFile.has(tsconfigPath)) {
return tsconfigInfoCaches.isFile.get(tsconfigPath);
}
if (tsconfigInfoCaches.content.has(tsconfigPath)) {
// if it has content, it's a file
tsconfigInfoCaches.isFile.set(tsconfigPath, true);
return true;
}
tsconfigInfoCaches.isFile.set(tsconfigPath, tree.isFile(tsconfigPath));
return tsconfigInfoCaches.isFile.get(tsconfigPath);
}
@@ -48,7 +48,7 @@ export function startLocalRegistry({
execSync(
`npm config set //localhost:${port}/:_authToken "secretVerdaccioToken"`,
{
windowsHide: true,
windowsHide: false,
}
);
@@ -63,7 +63,7 @@ export function startLocalRegistry({
resolve(() => {
childProcess.kill();
execSync(`npm config delete //localhost:${port}/:_authToken`, {
windowsHide: true,
windowsHide: false,
});
});
childProcess?.stdout?.off('data', listener);
@@ -1,6 +1,8 @@
import { type CreateNodesContext } from '@nx/devkit';
import { detectPackageManager, type CreateNodesContext } from '@nx/devkit';
import { TempFs } from '@nx/devkit/internal-testing-utils';
import { minimatch } from 'minimatch';
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
import { getLockFileName } from 'nx/src/plugins/js/lock-file/lock-file';
import { setupWorkspaceContext } from 'nx/src/utils/workspace-context';
import { PLUGIN_NAME, createNodesV2, type TscPluginOptions } from './plugin';
@@ -25,6 +27,10 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
process.chdir(tempFs.tempDir);
originalCacheProjectGraph = process.env.NX_CACHE_PROJECT_GRAPH;
process.env.NX_CACHE_PROJECT_GRAPH = 'false';
const lockFileName = getLockFileName(
detectPackageManager(context.workspaceRoot)
);
applyFilesToTempFsAndContext(tempFs, context, { [lockFileName]: '' });
});
afterEach(() => {
+38 -10
View File
@@ -16,12 +16,11 @@ import {
type ProjectConfiguration,
type TargetConfiguration,
} from '@nx/devkit';
import { calculateHashForCreateNodes } from '@nx/devkit/src/utils/calculate-hash-for-create-nodes';
import { getNamedInputs } from '@nx/devkit/src/utils/get-named-inputs';
import { minimatch } from 'minimatch';
import { existsSync, readdirSync, statSync } from 'node:fs';
import { basename, dirname, join, normalize, relative } from 'node:path';
import { hashObject } from 'nx/src/hasher/file-hasher';
import { hashArray, hashFile, hashObject } from 'nx/src/hasher/file-hasher';
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
import { getLockFileName } from 'nx/src/plugins/js/lock-file/lock-file';
import { workspaceDataDirectory } from 'nx/src/utils/cache-directory';
@@ -91,10 +90,19 @@ export const createNodesV2: CreateNodesV2<TscPluginOptions> = [
const cachePath = join(workspaceDataDirectory, `tsc-${optionsHash}.hash`);
const targetsCache = readTargetsCache(cachePath);
const normalizedOptions = normalizePluginOptions(options);
const lockFileName = getLockFileName(
detectPackageManager(context.workspaceRoot)
);
try {
return await createNodesFromFiles(
(configFile, options, context) =>
createNodesInternal(configFile, options, context, targetsCache),
createNodesInternal(
configFile,
options,
context,
lockFileName,
targetsCache
),
configFilePaths,
normalizedOptions,
context
@@ -112,7 +120,16 @@ export const createNodes: CreateNodes<TscPluginOptions> = [
'`createNodes` is deprecated. Update your plugin to utilize createNodesV2 instead. In Nx 20, this will change to the createNodesV2 API.'
);
const normalizedOptions = normalizePluginOptions(options);
return createNodesInternal(configFilePath, normalizedOptions, context, {});
const lockFileName = getLockFileName(
detectPackageManager(context.workspaceRoot)
);
return createNodesInternal(
configFilePath,
normalizedOptions,
context,
lockFileName,
{}
);
},
];
@@ -120,6 +137,7 @@ async function createNodesInternal(
configFilePath: string,
options: NormalizedPluginOptions,
context: CreateNodesContext,
lockFileName: string,
targetsCache: Record<string, TscProjectResult>
): Promise<CreateNodesResult> {
const projectRoot = dirname(configFilePath);
@@ -150,13 +168,23 @@ async function createNodesInternal(
return {};
}
const nodeHash = await calculateHashForCreateNodes(
projectRoot,
options,
context,
[getLockFileName(detectPackageManager(context.workspaceRoot))]
/**
* The cache key is composed by:
* - hashes of the content of the relevant files that can affect what's inferred by the plugin:
* - current config file
* - config files extended by the current config file (recursively up to the root config file)
* - lock file
* - hash of the plugin options
* - current config file path
*/
const extendedConfigFiles = getExtendedConfigFiles(
fullConfigPath,
readCachedTsConfig(fullConfigPath)
);
// The hash is calculated at the node/project level, so we add the config file path to avoid conflicts when caching
const nodeHash = hashArray([
...[configFilePath, ...extendedConfigFiles, lockFileName].map(hashFile),
hashObject(options),
]);
const cacheKey = `${nodeHash}_${configFilePath}`;
targetsCache[cacheKey] ??= buildTscTargets(
+1 -1
View File
@@ -108,7 +108,7 @@ async function getNpmConfigValue(key: string, cwd: string): Promise<string> {
async function execAsync(command: string, cwd: string): Promise<string> {
// Must be non-blocking async to allow spinner to render
return new Promise<string>((resolve, reject) => {
exec(command, { cwd, windowsHide: true }, (error, stdout, stderr) => {
exec(command, { cwd, windowsHide: false }, (error, stdout, stderr) => {
if (error) {
return reject(error);
}
+2 -2
View File
@@ -85,7 +85,7 @@ export async function compileSwc(
const swcCmdLog = execSync(getSwcCmd(normalizedOptions), {
encoding: 'utf8',
cwd: normalizedOptions.swcCliOptions.swcCwd,
windowsHide: true,
windowsHide: false,
});
logger.log(swcCmdLog.replace(/\n/, ''));
const isCompileSuccess = swcCmdLog.includes('Successfully compiled');
@@ -138,7 +138,7 @@ export async function* compileSwcWatch(
const swcWatcher = exec(getSwcCmd(normalizedOptions, true), {
cwd: normalizedOptions.swcCliOptions.swcCwd,
windowsHide: true,
windowsHide: false,
});
processOnExit = () => {
@@ -1,13 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`app generated files content - as-provided - my-app general application should add nuxt entries in .gitignore 1`] = `
"
# Nuxt dev/build outputs
"# Nuxt dev/build outputs
.output
.data
.nuxt
.nitro
.cache"
.cache
**/vite.config.{js,ts,mjs,mts,cjs,cts}.timestamp*"
`;
exports[`app generated files content - as-provided - my-app general application should add the nuxt and vitest plugins 1`] = `
@@ -364,13 +364,13 @@ export default defineNuxtConfig({
`;
exports[`app generated files content - as-provided - myApp general application should add nuxt entries in .gitignore 1`] = `
"
# Nuxt dev/build outputs
"# Nuxt dev/build outputs
.output
.data
.nuxt
.nitro
.cache"
.cache
**/vite.config.{js,ts,mjs,mts,cjs,cts}.timestamp*"
`;
exports[`app generated files content - as-provided - myApp general application should add the nuxt and vitest plugins 1`] = `
@@ -159,7 +159,7 @@ export async function applicationGenerator(tree: Tree, schema: Schema) {
execSync(`npx -y nuxi prepare`, {
cwd: options.appProjectRoot,
windowsHide: true,
windowsHide: false,
});
} catch (e) {
console.error(
+2 -2
View File
@@ -252,14 +252,14 @@ function getLocalNxVersion(workspace: WorkspaceTypeAndRoot): string | null {
function _getLatestVersionOfNx(): string {
try {
return execSync('npm view nx@latest version', {
windowsHide: true,
windowsHide: false,
})
.toString()
.trim();
} catch {
try {
return execSync('pnpm view nx@latest version', {
windowsHide: true,
windowsHide: false,
})
.toString()
.trim();
+6
View File
@@ -57,6 +57,12 @@
"version": "20.0.0-beta.7",
"description": "Migration for v20.0.0-beta.7",
"implementation": "./src/migrations/update-20-0-0/move-use-daemon-process"
},
"use-legacy-cache": {
"version": "20.0.1",
"description": "Set `useLegacyCache` to true for migrating workspaces",
"implementation": "./src/migrations/update-20-0-1/use-legacy-cache",
"x-repair-skip": true
}
}
}
+4
View File
@@ -89,6 +89,10 @@
"type": "string",
"description": "Specifies the encryption key used to encrypt artifacts data before sending it to nx cloud."
},
"neverConnectToCloud": {
"type": "boolean",
"description": "Set this to true to disable all connections to Nx Cloud."
},
"parallel": {
"type": "number",
"description": "Specifies how many tasks are ran in parallel by Nx for the default tasks runner."
@@ -26,7 +26,7 @@ async function requirePowerpack(): Promise<any> {
execSync(
`${getPackageManagerCommand().addDev} @nx/powerpack-license@latest`,
{
windowsHide: true,
windowsHide: false,
}
);
+1 -1
View File
@@ -46,7 +46,7 @@ async function installPackage(
exec(
`${pmc.addDev} ${pkgName}@${version}`,
{
windowsHide: true,
windowsHide: false,
},
(error, stdout) => {
if (error) {
@@ -50,7 +50,7 @@ export async function viewLogs(): Promise<number> {
const pmc = getPackageManagerCommand();
execSync(`${pmc.exec} nx-cloud upload-and-show-run-details`, {
stdio: [0, 1, 2],
windowsHide: true,
windowsHide: false,
});
if (!cloudUsed) {
+3 -3
View File
@@ -54,7 +54,7 @@ export async function nxExecCommand(
NX_PROJECT_ROOT_PATH:
projectGraph.nodes?.[process.env.NX_TASK_TARGET_PROJECT]?.data?.root,
},
windowsHide: true,
windowsHide: false,
});
} else {
// nx exec is being ran inside of Nx's context
@@ -105,7 +105,7 @@ async function runScriptAsNxTarget(
projectGraph.nodes?.[projectName]?.data?.root
)
: workspaceRoot,
windowsHide: true,
windowsHide: false,
});
});
}
@@ -132,7 +132,7 @@ function runTargetOnProject(
execSync(command, {
stdio: 'inherit',
windowsHide: true,
windowsHide: false,
});
}
@@ -211,7 +211,7 @@ function write(patterns: string[]) {
)}`,
{
stdio: [0, 1, 2],
windowsHide: true,
windowsHide: false,
}
);
@@ -222,7 +222,7 @@ function write(patterns: string[]) {
)} --parser json`,
{
stdio: [0, 1, 2],
windowsHide: true,
windowsHide: false,
}
);
}
@@ -239,7 +239,7 @@ async function check(patterns: string[]): Promise<string[]> {
return new Promise((resolve) => {
exec(
`node "${prettierPath}" --list-different ${patterns.join(' ')}`,
{ encoding: 'utf-8', windowsHide: true },
{ encoding: 'utf-8', windowsHide: false },
(error, stdout) => {
if (error) {
// The command failed so there are files with different formatting. Prettier writes them to stdout, newline separated.
+1 -1
View File
@@ -1270,6 +1270,6 @@ function getHelpTextFromTarget(
return execSync(command, {
cwd: target.options?.cwd ?? workspaceRoot,
windowsHide: true,
windowsHide: false,
}).toString();
}
@@ -6,6 +6,6 @@ export function setupIntegratedWorkspace(): void {
execSync(`${pmc.exec} nx g @nx/angular:ng-add`, {
stdio: [0, 1, 2],
windowsHide: true,
windowsHide: false,
});
}
@@ -108,7 +108,7 @@ export async function getLegacyMigrationFunctionIfApplicable(
output.log({ title: '📝 Setting up workspace' });
execSync(`${pmc.exec} ${legacyMigrationCommand}`, {
stdio: [0, 1, 2],
windowsHide: true,
windowsHide: false,
});
if (useNxCloud) {
@@ -149,7 +149,7 @@ async function installDependencies(
}
writeJsonFile(`package.json`, json);
execSync(pmc.install, { stdio: [0, 1, 2], windowsHide: true });
execSync(pmc.install, { stdio: [0, 1, 2], windowsHide: false });
}
async function resolvePackageVersion(
@@ -68,7 +68,7 @@ export function generateDotNxSetup(version?: string) {
export function normalizeVersionForNxJson(pkg: string, version: string) {
if (!valid(version)) {
version = execSync(`npm view ${pkg}@${version} version`, {
windowsHide: true,
windowsHide: false,
}).toString();
}
return version.trimEnd();
@@ -90,7 +90,7 @@ function performInstallation(
cp.execSync('npm i', {
cwd: path.dirname(installationPath),
stdio: 'inherit',
windowsHide: true,
windowsHide: false,
});
} catch (e) {
// revert possible changes to the current installation
@@ -2,7 +2,7 @@ import { execSync } from 'child_process';
export function checkForUncommittedChanges() {
const gitResult = execSync('git status --porcelain', {
windowsHide: true,
windowsHide: false,
}).toString();
const filteredResults = gitResult
@@ -70,7 +70,7 @@ function installDependencies(options: NormalizedOptions) {
execSync(`${options.pmc.addDev} ${dependencies.join(' ')}`, {
stdio: [0, 1, 2],
windowsHide: true,
windowsHide: false,
});
}
@@ -88,7 +88,7 @@ async function normalizeOptions(options: Options): Promise<NormalizedOptions> {
};
const isCRA5 = /^[^~]?5/.test(deps['react-scripts']);
const npmVersion = execSync('npm -v', {
windowsHide: true,
windowsHide: false,
}).toString();
// Should remove this check 04/2023 once Node 14 & npm 6 reach EOL
const npxYesFlagNeeded = !npmVersion.startsWith('6'); // npm 7 added -y flag to npx
@@ -131,11 +131,11 @@ async function reorgnizeWorkspaceStructure(options: NormalizedOptions) {
execSync(`echo "node_modules" >> .gitignore`, {
stdio: [0, 1, 2],
windowsHide: true,
windowsHide: false,
});
execSync(`echo "dist" >> .gitignore`, {
stdio: [0, 1, 2],
windowsHide: true,
windowsHide: false,
});
process.chdir('..');
@@ -177,7 +177,7 @@ function createTempWorkspace(options: NormalizedOptions) {
} ${
options.addE2e ? '--e2eTestRunner=playwright' : '--e2eTestRunner=none'
}`,
{ stdio: [0, 1, 2], windowsHide: true }
{ stdio: [0, 1, 2], windowsHide: false }
);
output.log({ title: '👋 Welcome to Nx!' });
@@ -330,7 +330,7 @@ async function addBundler(options: NormalizedOptions) {
execSync(`echo "SKIP_PREFLIGHT_CHECK=true" > .env`, {
stdio: [0, 1, 2],
windowsHide: true,
windowsHide: false,
});
}
}
@@ -68,28 +68,28 @@ function deduceDefaultBase() {
try {
execSync(`git rev-parse --verify main`, {
stdio: ['ignore', 'ignore', 'ignore'],
windowsHide: true,
windowsHide: false,
});
return 'main';
} catch {
try {
execSync(`git rev-parse --verify dev`, {
stdio: ['ignore', 'ignore', 'ignore'],
windowsHide: true,
windowsHide: false,
});
return 'dev';
} catch {
try {
execSync(`git rev-parse --verify develop`, {
stdio: ['ignore', 'ignore', 'ignore'],
windowsHide: true,
windowsHide: false,
});
return 'develop';
} catch {
try {
execSync(`git rev-parse --verify next`, {
stdio: ['ignore', 'ignore', 'ignore'],
windowsHide: true,
windowsHide: false,
});
return 'next';
} catch {
@@ -144,7 +144,11 @@ export function runInstall(
repoRoot: string,
pmc: PackageManagerCommands = getPackageManagerCommand()
) {
execSync(pmc.install, { stdio: [0, 1, 2], cwd: repoRoot, windowsHide: true });
execSync(pmc.install, {
stdio: [0, 1, 2],
cwd: repoRoot,
windowsHide: false,
});
}
export async function initCloud(
+1 -1
View File
@@ -95,7 +95,7 @@ export async function initHandler(options: InitArgs) {
} else {
execSync(`npx --yes create-nx-workspace@${version} ${args}`, {
stdio: [0, 1, 2],
windowsHide: true,
windowsHide: false,
});
}
}
+1 -1
View File
@@ -59,7 +59,7 @@ export function installPlugins(
{
stdio: [0, 1, 2],
cwd: repoRoot,
windowsHide: true,
windowsHide: false,
}
);
}
@@ -128,7 +128,7 @@ function runMigration() {
}
execSync(`${p} _migrate ${process.argv.slice(3).join(' ')}`, {
stdio: ['inherit', 'inherit', 'inherit'],
windowsHide: true,
windowsHide: false,
});
}
} else {
@@ -156,14 +156,14 @@ function nxCliPath() {
execSync(pmc.preInstall, {
cwd: tmpDir,
stdio: ['ignore', 'ignore', 'ignore'],
windowsHide: true,
windowsHide: false,
});
// if it's berry ensure we set the node_linker to node-modules
if (packageManager === 'yarn' && pmc.ciInstall.includes('immutable')) {
execSync('yarn config set nodeLinker node-modules', {
cwd: tmpDir,
stdio: ['ignore', 'ignore', 'ignore'],
windowsHide: true,
windowsHide: false,
});
}
}
@@ -171,7 +171,7 @@ function nxCliPath() {
execSync(pmc.install, {
cwd: tmpDir,
stdio: ['ignore', 'ignore', 'ignore'],
windowsHide: true,
windowsHide: false,
});
// Set NODE_PATH so that these modules can be used for module resolution
@@ -1387,7 +1387,7 @@ function runInstall() {
output.log({
title: `Running '${pmCommands.install}' to make sure necessary packages are installed`,
});
execSync(pmCommands.install, { stdio: [0, 1, 2], windowsHide: true });
execSync(pmCommands.install, { stdio: [0, 1, 2], windowsHide: false });
}
export async function executeMigrations(
@@ -323,7 +323,7 @@ async function getCommitForVersionPlanFile(
exec(
`git log --diff-filter=A --pretty=format:"%s|%h|%an|%ae|%b" -n 1 -- ${rawVersionPlan.absolutePath}`,
{
windowsHide: true,
windowsHide: false,
},
(error, stdout, stderr) => {
if (error) {
+1 -1
View File
@@ -77,7 +77,7 @@ export function createAPI(overrideReleaseConfig: NxReleaseConfiguration) {
}
// If no release groups have version plans enabled, it doesn't make sense to use the plan command only to set yourself up for an error at release time
if (!releaseGroups.some((group) => group.versionPlans === true)) {
if (!releaseGroups.some((group) => !!group.versionPlans)) {
if (releaseGroups.length === 1) {
output.warn({
title: `Version plans are not enabled in your release configuration`,
@@ -10,7 +10,7 @@ export async function execCommand(
...options,
stdio: ['pipe', 'pipe', 'pipe'], // stdin, stdout, stderr
encoding: 'utf-8',
windowsHide: true,
windowsHide: false,
});
let stdout = '';
@@ -367,7 +367,7 @@ async function resolveGithubToken(hostname: string): Promise<string | null> {
return execSync(`gh auth token`, {
encoding: 'utf8',
stdio: 'pipe',
windowsHide: true,
windowsHide: false,
}).trim();
}
}
@@ -14,7 +14,7 @@ export async function launchEditor(filePath: string) {
return new Promise((resolve, reject) => {
const editorProcess = spawn(cmd, [...args, filePath], {
stdio: 'inherit', // This will ensure the editor uses the current terminal
windowsHide: true,
windowsHide: false,
});
editorProcess.on('exit', (code) => {
@@ -30,7 +30,7 @@ export async function launchEditor(filePath: string) {
function getGitConfig(key): string | null {
try {
return execSync(`git config --get ${key}`, {
windowsHide: true,
windowsHide: false,
})
.toString()
.trim();
@@ -762,7 +762,7 @@ function runPreVersionCommand(
maxBuffer: LARGE_BUFFER,
stdio,
env,
windowsHide: true,
windowsHide: false,
});
} catch (e) {
const title = verbose
+1 -1
View File
@@ -134,7 +134,7 @@ async function printTargetRunHelpInternal(
} else {
const cp = exec(helpCommand, {
env,
windowsHide: true,
windowsHide: false,
});
cp.on('exit', (code) => {
process.exit(code);
+1 -1
View File
@@ -132,7 +132,7 @@ class BatchCommandRunner extends BatchFunctionRunner {
[this.projectNameEnv]: env[this.projectNameEnv],
[this.fileChangesEnv]: env[this.fileChangesEnv],
},
windowsHide: true,
windowsHide: false,
});
commandExec.on('close', () => {
resolve();
+1 -1
View File
@@ -507,7 +507,7 @@ export interface NxJsonConfiguration<T = '*' | string[]> {
useInferencePlugins?: boolean;
/**
* Set this to false to disable connection to Nx Cloud
* Set this to true to disable connection to Nx Cloud
*/
neverConnectToCloud?: boolean;

Some files were not shown because too many files have changed in this diff Show More