Compare commits

...

16 Commits

Author SHA1 Message Date
FrozenPandaz 2468db1a50 chore(misc): publish 15.7.1 2023-02-15 13:44:28 -05:00
Leosvel Pérez Espinosa bb2e790ff4 fix(misc): fix moving a project into a subfolder (#14988)
(cherry picked from commit 3bb87eac3f)
2023-02-15 11:10:35 -05:00
Phillip Barta f64003735f cleanup(webpack): replace fs-extra.removeSync() with fs.rmSync() and remove dependency fs-extra (#15008)
(cherry picked from commit 673fff6dfb)
2023-02-15 11:10:31 -05:00
William Sedlacek 3b5df23ca0 fix(linter): ng-package.json format (#14996)
(cherry picked from commit 8db4673a67)
2023-02-15 11:10:23 -05:00
Katerina Skroumpelou 298f719d13 fix(storybook): v7 vite settings docs remove rootMain (#14992)
(cherry picked from commit 1b64e17d4e)
2023-02-15 11:10:20 -05:00
CallMe AsYouFeel ed0e6c7297 feat(bundling): make rollup executor return outfile for node executor (#14989)
(cherry picked from commit bd2a1aea03)
2023-02-15 11:10:08 -05:00
Nicholas Cunningham a276bcdfd5 fix(js): remove plugins from esbuild will be done as a feature (#14997)
(cherry picked from commit ba19dc00ac)
2023-02-15 11:09:59 -05:00
Craigory Coppola 68d09430b5 feat(core): allow loading env vars by target and configuration (#14998)
(cherry picked from commit 24e87e6cc4)
2023-02-15 11:09:52 -05:00
Craigory Coppola 7cbb2825e3 fix(core): local plugins should work under yarn workspaces (#14995)
(cherry picked from commit d7c8e03b5e)
2023-02-15 11:09:48 -05:00
Miroslav Jonaš de3e50421c feat(linter): add support for full regexes in tag matching (#14982)
(cherry picked from commit 8165459568)
2023-02-15 11:09:45 -05:00
Miroslav Jonaš c21e9fb18e fix(core): skip peer deps from devDependencies on createPackageJson (#14958)
(cherry picked from commit b583f89095)
2023-02-15 11:09:32 -05:00
Emily Xiong 27e43d0572 fix(angular): ensure peer deps are installed when initializing the plugin (#14906)
Co-authored-by: Leosvel Pérez Espinosa <leosvel.perez.espinosa@gmail.com>
(cherry picked from commit 032efc2cfb)
2023-02-15 11:09:24 -05:00
Victor Savkin 7954426cc4 fix(core): correctly set default configuration name for dependent tasks
(cherry picked from commit ea440ae33a)
2023-02-15 11:09:16 -05:00
JKapitein 14cd02b322 fix(core): do not always use yarn as package manager in the gitlab ci t… (#14978)
(cherry picked from commit 3032c7592b)
2023-02-15 11:09:10 -05:00
Katerina Skroumpelou 5c6497e8ce fix(vite): set root and path on dts plugin (#14964)
(cherry picked from commit bff786962b)
2023-02-15 11:09:05 -05:00
MaxKless ff2c50c4f3 fix(core): sort --help output by flag priority (#14869)
(cherry picked from commit 20b66fc750)
2023-02-15 11:09:00 -05:00
93 changed files with 1568 additions and 1054 deletions
+3 -3
View File
@@ -147,7 +147,7 @@ jobs:
SELECTED_PM: << parameters.pm >>
NX_E2E_RUN_CYPRESS: 'false'
NX_VERBOSE_LOGGING: 'true'
NX_PERF_LOGGING: 'true'
NX_PERF_LOGGING: 'false'
NX_NATIVE_HASHER: 'true'
steps:
- run:
@@ -175,7 +175,7 @@ jobs:
NX_E2E_CI_CACHE_KEY: e2e-circleci-linux
NX_VERBOSE_LOGGING: 'true'
NX_DAEMON: 'true'
NX_PERF_LOGGING: 'true'
NX_PERF_LOGGING: 'false'
NX_NATIVE_HASHER: 'true'
steps:
- run:
@@ -222,7 +222,7 @@ jobs:
environment:
NX_E2E_CI_CACHE_KEY: e2e-circleci-macos
NX_DAEMON: 'true'
NX_PERF_LOGGING: 'true'
NX_PERF_LOGGING: 'false'
NX_NATIVE_HASHER: 'true'
steps:
- run:
-11
View File
@@ -1,11 +0,0 @@
module.exports = {
stories: [],
addons: ['@storybook/addon-essentials'],
// uncomment the property below if you want to apply some webpack config globally
// webpackFinal: async (config, { configType }) => {
// // Make whatever fine-grained changes you need that should apply to all storybook configs
// // Return the altered config
// return config;
// },
};
@@ -52,7 +52,7 @@ The Storybook CLI will prompt you to run some code generators and modifiers.
Say `yes` to the following:
- `mainjsFramework`: It will add the `framework` field in your root `.storybook/main.js|ts` file. We are going to delete it since it's not needed in the root file, but it's handy to have it ready to copy. Also, it shows you an indication of what it looks like.
- `mainjsFramework`: It will try to add the `framework` field in your project's `.storybook/main.js|ts` file.
- `eslintPlugin`: installs the `eslint-plugin-storybook`
- `storybook-binary`: installs Storybook's `storybook` binary
- `newFrameworks`: removes unused dependencies (eg. `@storybook/builder-webpack5`, `@storybook/manager-webpack5`, `@storybook/builder-vite`)
@@ -61,21 +61,6 @@ Say `no` to the following:
- `autodocsTrue`: we don't need it and it can potentially cause issues with missing dependencies on your Nx workspace
### 3. Restore the root `.storybook/main.js|ts` file
You will have noticed that the Storybook automigrator added the `framework` option to your root `.storybook/main.js|ts` file. Let's remove that.
So, remove:
```ts
framework: {
name: '@storybook/angular',
options: {}
}
```
from your root `.storybook/main.js|ts` file.
### 3. Edit all the project-level `.storybook/main.js|ts` files
Find all your project-level `.storybook/main.js|ts` files and edit them to add the `framework` option. While you are at it, remove the `builder` from `core` options.
@@ -87,7 +72,7 @@ In your project-level `.storybook/main.js|ts` files, remove the `builder` from `
Your core options most probably look like this:
```ts
core: { ...rootMain.core, builder: '@storybook/builder-vite' },
core: { builder: '@storybook/builder-vite' },
```
You must remove the `builder`, or you can also delete the `core` object entirely.
@@ -126,12 +111,16 @@ Choose the `@storybook/angular` framework. So add this in your project-level `.s
#### For React projects using `'@storybook/builder-vite'`
Choose the `@storybook/react-vite` framework. So add this in your project-level `.storybook/main.js|ts` file:
Choose the `@storybook/react-vite` framework. You must also point the builder to the Vite configuration file path, so that it can read the settings from there. If your project's root path is `apps/my-app` and it's using a Vite configuration file at `apps/my-app/vite.config.ts`, then you must add this in your project-level `.storybook/main.js|ts` file:
```ts
framework: {
name: '@storybook/react-vite',
options: {}
options: {
builder: {
viteConfigPath: 'apps/my-app/vite.config.ts',
},
}
}
```
@@ -159,12 +148,16 @@ Choose the `@storybook/nextjs` framework. So add this in your project-level `.st
#### For Web Components projects using `'@storybook/builder-vite'`
Choose the `@storybook/web-components-vite` framework. So add this in your project-level `.storybook/main.js|ts` file:
Choose the `@storybook/web-components-vite` framework. You must also point the builder to the Vite configuration file path, so that it can read the settings from there. If your project's root path is `apps/my-app` and it's using a Vite configuration file at `apps/my-app/vite.config.ts`, then you must add this in your project-level `.storybook/main.js|ts` file:
```ts
framework: {
name: '@storybook/web-components-vite',
options: {}
options: {
builder: {
viteConfigPath: 'apps/my-app/vite.config.ts',
},
}
}
```
@@ -183,79 +176,67 @@ Choose the `@storybook/web-components-webpack5` framework. So add this in your p
You can easily find the correct framework by looking at the `builder` option in your project-level `.storybook/main.js|ts` file.
#### Resulting project-level `.storybook/main.js|ts` file
### 4. Check result of project-level `.storybook/main.js|ts` file
#### Full example for Angular projects
Here is an example of a project-level `.storybook/main.js|ts` file for an Angular project:
```ts
// apps/my-angular-app/.storybook/main.js|ts
const rootMain = require('../../../.storybook/main');
module.exports = {
...rootMain,
stories: [
...rootMain.stories,
'../src/app/**/*.stories.mdx',
'../src/app/**/*.stories.@(js|jsx|ts|tsx)',
],
addons: [...rootMain.addons],
```ts {% fileName="apps/my-angular-app/.storybook/main.js" %}
const config = {
stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
addons: ['@storybook/addon-essentials'],
framework: {
name: '@storybook/angular',
options: {},
},
};
export default config;
```
### 4. For Vite.js projects
#### Full example for React projects with Vite
Make sure to add the `viteFinal` option to your project-level `.storybook/main.js|ts` files on projects that use Vite.js.
Here is an example of a project-level `.storybook/main.js|ts` file for a React project using Vite:
```ts
async viteFinal(config, { configType }) {
return mergeConfig(config, {
plugins: [
viteTsConfigPaths({
root: '<PATH_TO_PROJECT_ROOT>',
}),
],
});
},
```
This will take care of any path resolution issues.
An example of a project-level `.storybook/main.js|ts` file for a React project that uses Vite.js:
```ts
// apps/my-react-vite-app/.storybook/main.js|ts
const { mergeConfig } = require('vite');
const viteTsConfigPaths = require('vite-tsconfig-paths').default;
const rootMain = require('../../../.storybook/main');
module.exports = {
...rootMain,
stories: [
...rootMain.stories,
'../src/app/**/*.stories.mdx',
'../src/app/**/*.stories.@(js|jsx|ts|tsx)',
],
addons: [...rootMain.addons],
async viteFinal(config, { configType }) {
return mergeConfig(config, {
plugins: [
viteTsConfigPaths({
root: '../../../',
}),
],
});
},
```ts {% fileName="apps/my-react-app/.storybook/main.js" %}
const config = {
stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
addons: ['@storybook/addon-essentials'],
framework: {
name: '@storybook/react-vite',
options: {},
options: {
builder: {
viteConfigPath: 'apps/rv1/vite.config.ts',
},
},
},
};
export default config;
```
### 5. Remove `uiFramework` from `project.json`
You can now remove the `uiFramework` option from your `storybook` and `build-storybook` targets in your project's `project.json` file.
So, for example, this is what a resulting `storybook` target would look for a non-Angular project:
```json {% fileName="apps/my-react-app/project.json" %}
{
...
"targets": {
...
"storybook": {
"executor": "@nrwl/storybook:storybook",
"options": {
"port": 4400,
"configDir": "apps/my-react-app/.storybook"
},
"configurations": {
...
}
},
```
## Use Storybook 7 beta
@@ -83,8 +83,62 @@ You need to use the [`vite-tsconfig-paths` plugin](https://www.npmjs.com/package
If you are using React, you need to use the [`@vitejs/plugin-react` plugin](https://www.npmjs.com/package/@vitejs/plugin-react).
### DTS plugin
If you are building a library, you need to use the [`vite-plugin-dts` plugin](https://www.npmjs.com/package/vite-plugin-dts) to generate the `.d.ts` files for your library.
#### Skip diagnostics
If you are building a library, you can set the `skipDiagnostics` option to `true` to speed up the build. This means that type diagnostic will be skipped during the build process. However, if there are some files with type errors which interrupt the build process, these files will not be emitted and `.d.ts` declaration files will not be generated.
If you choose to skip diagnostics, here is what your `'vite-plugin-dts'` plugin setup will look like:
```ts {% fileName="libs/my-lib/vite.config.ts" %}
...
import dts from 'vite-plugin-dts';
import { join } from 'path';
...
...
export default defineConfig({
plugins: [
...,
dts({
entryRoot: 'src',
tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'),
skipDiagnostics: true,
}),
```
#### Do not skip diagnostics
If you are building a library, and you want to make sure that all the files are type checked, you can set the `skipDiagnostics` option to `false` to make sure that all the files are type checked. This means that type diagnostic will be run during the build process.
If you choose to enable diagnostics, here is what your `'vite-plugin-dts'` plugin setup will look like:
```ts {% fileName="libs/my-lib/vite.config.ts" %}
...
import dts from 'vite-plugin-dts';
...
...
export default defineConfig({
plugins: [
...,
dts({
root: '../../',
entryRoot: 'packages/one/src',
tsConfigFilePath: 'packages/one/tsconfig.lib.json',
include: ['packages/one/src/**/*.ts'],
outputDir: 'dist/packages/one',
skipDiagnostics: false,
}),
```
You can read more about the configuration options in the [`vite-plugin-dts` plugin documentation](https://www.npmjs.com/package/vite-plugin-dts)).
### How your `vite.config.ts` looks like
#### For applications
Add a `vite.config.ts` file to the root of your project. If you are not using React, you can skip adding the `react` plugin, of course.
```ts {% fileName="apps/my-app/vite.config.ts" %}
@@ -102,7 +156,9 @@ export default defineConfig({
});
```
If you are converting a library (rather than an application) to use vite, your `vite.config.ts` file should look like this:
#### For libraries
If you are setting up a library (rather than an application) to use vite, your `vite.config.ts` file should look like this:
```ts {% fileName="libs/my-lib/vite.config.ts" %}
import { defineConfig } from 'vite';
@@ -114,13 +170,13 @@ import { join } from 'path';
export default defineConfig({
plugins: [
dts({
entryRoot: 'src',
tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'),
// Faster builds by skipping tests. Set this to false to enable type checking.
skipDiagnostics: true,
}),
react(),
viteTsConfigPaths({
root: '../../../',
root: '../../',
}),
],
@@ -9,16 +9,20 @@ the runtime of an app.
By default, Nx will load any environment variables you place in the following files:
1. `apps/my-app/.[target-name].env`
2. `apps/my-app/.env.[target-name]`
3. `apps/my-app/.local.env`
4. `apps/my-app/.env.local`
5. `apps/my-app/.env`
6. `.[target-name].env`
7. `.env.[target-name]`
8. `.local.env`
9. `.env.local`
10. `.env`
1. `apps/my-app/.env.[target-name].[configuration-name]`
2. `apps/my-app/.[target-name].[configuration-name].env`
3. `apps/my-app/.env.[target-name]`
4. `apps/my-app/.[target-name].env`
5. `apps/my-app/.env.local`
6. `apps/my-app/.local.env`
7. `apps/my-app/.env`
8. `.env.[target-name].[configuration-name]`
9. `.[target-name].[configuration-name].env`
10. `.env.[target-name]`
11. `.[target-name].env`
12. `.local.env`
13. `.env.local`
14. `.env`
{% callout type="warning" title="Order is important" %}
Nx will move through the above list, ignoring files it can't find, and loading environment variables
@@ -52,7 +52,7 @@ The Storybook CLI will prompt you to run some code generators and modifiers.
Say `yes` to the following:
- `mainjsFramework`: It will add the `framework` field in your root `.storybook/main.js|ts` file. We are going to delete it since it's not needed in the root file, but it's handy to have it ready to copy. Also, it shows you an indication of what it looks like.
- `mainjsFramework`: It will try to add the `framework` field in your project's `.storybook/main.js|ts` file.
- `eslintPlugin`: installs the `eslint-plugin-storybook`
- `storybook-binary`: installs Storybook's `storybook` binary
- `newFrameworks`: removes unused dependencies (eg. `@storybook/builder-webpack5`, `@storybook/manager-webpack5`, `@storybook/builder-vite`)
@@ -61,21 +61,6 @@ Say `no` to the following:
- `autodocsTrue`: we don't need it and it can potentially cause issues with missing dependencies on your Nx workspace
### 3. Restore the root `.storybook/main.js|ts` file
You will have noticed that the Storybook automigrator added the `framework` option to your root `.storybook/main.js|ts` file. Let's remove that.
So, remove:
```ts
framework: {
name: '@storybook/angular',
options: {}
}
```
from your root `.storybook/main.js|ts` file.
### 3. Edit all the project-level `.storybook/main.js|ts` files
Find all your project-level `.storybook/main.js|ts` files and edit them to add the `framework` option. While you are at it, remove the `builder` from `core` options.
@@ -87,7 +72,7 @@ In your project-level `.storybook/main.js|ts` files, remove the `builder` from `
Your core options most probably look like this:
```ts
core: { ...rootMain.core, builder: '@storybook/builder-vite' },
core: { builder: '@storybook/builder-vite' },
```
You must remove the `builder`, or you can also delete the `core` object entirely.
@@ -126,12 +111,16 @@ Choose the `@storybook/angular` framework. So add this in your project-level `.s
#### For React projects using `'@storybook/builder-vite'`
Choose the `@storybook/react-vite` framework. So add this in your project-level `.storybook/main.js|ts` file:
Choose the `@storybook/react-vite` framework. You must also point the builder to the Vite configuration file path, so that it can read the settings from there. If your project's root path is `apps/my-app` and it's using a Vite configuration file at `apps/my-app/vite.config.ts`, then you must add this in your project-level `.storybook/main.js|ts` file:
```ts
framework: {
name: '@storybook/react-vite',
options: {}
options: {
builder: {
viteConfigPath: 'apps/my-app/vite.config.ts',
},
}
}
```
@@ -159,12 +148,16 @@ Choose the `@storybook/nextjs` framework. So add this in your project-level `.st
#### For Web Components projects using `'@storybook/builder-vite'`
Choose the `@storybook/web-components-vite` framework. So add this in your project-level `.storybook/main.js|ts` file:
Choose the `@storybook/web-components-vite` framework. You must also point the builder to the Vite configuration file path, so that it can read the settings from there. If your project's root path is `apps/my-app` and it's using a Vite configuration file at `apps/my-app/vite.config.ts`, then you must add this in your project-level `.storybook/main.js|ts` file:
```ts
framework: {
name: '@storybook/web-components-vite',
options: {}
options: {
builder: {
viteConfigPath: 'apps/my-app/vite.config.ts',
},
}
}
```
@@ -183,79 +176,67 @@ Choose the `@storybook/web-components-webpack5` framework. So add this in your p
You can easily find the correct framework by looking at the `builder` option in your project-level `.storybook/main.js|ts` file.
#### Resulting project-level `.storybook/main.js|ts` file
### 4. Check result of project-level `.storybook/main.js|ts` file
#### Full example for Angular projects
Here is an example of a project-level `.storybook/main.js|ts` file for an Angular project:
```ts
// apps/my-angular-app/.storybook/main.js|ts
const rootMain = require('../../../.storybook/main');
module.exports = {
...rootMain,
stories: [
...rootMain.stories,
'../src/app/**/*.stories.mdx',
'../src/app/**/*.stories.@(js|jsx|ts|tsx)',
],
addons: [...rootMain.addons],
```ts {% fileName="apps/my-angular-app/.storybook/main.js" %}
const config = {
stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
addons: ['@storybook/addon-essentials'],
framework: {
name: '@storybook/angular',
options: {},
},
};
export default config;
```
### 4. For Vite.js projects
#### Full example for React projects with Vite
Make sure to add the `viteFinal` option to your project-level `.storybook/main.js|ts` files on projects that use Vite.js.
Here is an example of a project-level `.storybook/main.js|ts` file for a React project using Vite:
```ts
async viteFinal(config, { configType }) {
return mergeConfig(config, {
plugins: [
viteTsConfigPaths({
root: '<PATH_TO_PROJECT_ROOT>',
}),
],
});
},
```
This will take care of any path resolution issues.
An example of a project-level `.storybook/main.js|ts` file for a React project that uses Vite.js:
```ts
// apps/my-react-vite-app/.storybook/main.js|ts
const { mergeConfig } = require('vite');
const viteTsConfigPaths = require('vite-tsconfig-paths').default;
const rootMain = require('../../../.storybook/main');
module.exports = {
...rootMain,
stories: [
...rootMain.stories,
'../src/app/**/*.stories.mdx',
'../src/app/**/*.stories.@(js|jsx|ts|tsx)',
],
addons: [...rootMain.addons],
async viteFinal(config, { configType }) {
return mergeConfig(config, {
plugins: [
viteTsConfigPaths({
root: '../../../',
}),
],
});
},
```ts {% fileName="apps/my-react-app/.storybook/main.js" %}
const config = {
stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
addons: ['@storybook/addon-essentials'],
framework: {
name: '@storybook/react-vite',
options: {},
options: {
builder: {
viteConfigPath: 'apps/rv1/vite.config.ts',
},
},
},
};
export default config;
```
### 5. Remove `uiFramework` from `project.json`
You can now remove the `uiFramework` option from your `storybook` and `build-storybook` targets in your project's `project.json` file.
So, for example, this is what a resulting `storybook` target would look for a non-Angular project:
```json {% fileName="apps/my-react-app/project.json" %}
{
...
"targets": {
...
"storybook": {
"executor": "@nrwl/storybook:storybook",
"options": {
"port": 4400,
"configDir": "apps/my-react-app/.storybook"
},
"configurations": {
...
}
},
```
## Use Storybook 7 beta
@@ -83,8 +83,62 @@ You need to use the [`vite-tsconfig-paths` plugin](https://www.npmjs.com/package
If you are using React, you need to use the [`@vitejs/plugin-react` plugin](https://www.npmjs.com/package/@vitejs/plugin-react).
### DTS plugin
If you are building a library, you need to use the [`vite-plugin-dts` plugin](https://www.npmjs.com/package/vite-plugin-dts) to generate the `.d.ts` files for your library.
#### Skip diagnostics
If you are building a library, you can set the `skipDiagnostics` option to `true` to speed up the build. This means that type diagnostic will be skipped during the build process. However, if there are some files with type errors which interrupt the build process, these files will not be emitted and `.d.ts` declaration files will not be generated.
If you choose to skip diagnostics, here is what your `'vite-plugin-dts'` plugin setup will look like:
```ts {% fileName="libs/my-lib/vite.config.ts" %}
...
import dts from 'vite-plugin-dts';
import { join } from 'path';
...
...
export default defineConfig({
plugins: [
...,
dts({
entryRoot: 'src',
tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'),
skipDiagnostics: true,
}),
```
#### Do not skip diagnostics
If you are building a library, and you want to make sure that all the files are type checked, you can set the `skipDiagnostics` option to `false` to make sure that all the files are type checked. This means that type diagnostic will be run during the build process.
If you choose to enable diagnostics, here is what your `'vite-plugin-dts'` plugin setup will look like:
```ts {% fileName="libs/my-lib/vite.config.ts" %}
...
import dts from 'vite-plugin-dts';
...
...
export default defineConfig({
plugins: [
...,
dts({
root: '../../',
entryRoot: 'packages/one/src',
tsConfigFilePath: 'packages/one/tsconfig.lib.json',
include: ['packages/one/src/**/*.ts'],
outputDir: 'dist/packages/one',
skipDiagnostics: false,
}),
```
You can read more about the configuration options in the [`vite-plugin-dts` plugin documentation](https://www.npmjs.com/package/vite-plugin-dts)).
### How your `vite.config.ts` looks like
#### For applications
Add a `vite.config.ts` file to the root of your project. If you are not using React, you can skip adding the `react` plugin, of course.
```ts {% fileName="apps/my-app/vite.config.ts" %}
@@ -102,7 +156,9 @@ export default defineConfig({
});
```
If you are converting a library (rather than an application) to use vite, your `vite.config.ts` file should look like this:
#### For libraries
If you are setting up a library (rather than an application) to use vite, your `vite.config.ts` file should look like this:
```ts {% fileName="libs/my-lib/vite.config.ts" %}
import { defineConfig } from 'vite';
@@ -114,13 +170,13 @@ import { join } from 'path';
export default defineConfig({
plugins: [
dts({
entryRoot: 'src',
tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'),
// Faster builds by skipping tests. Set this to false to enable type checking.
skipDiagnostics: true,
}),
react(),
viteTsConfigPaths({
root: '../../../',
root: '../../',
}),
],
@@ -111,7 +111,6 @@ Thanks to our folder structure, we can easily configure Storybook to import all
For example, `libs/storybook-host-admin/.storybook/main.js`:
```javascript {% fileName="libs/storybook-host-admin/.storybook/main.js" %}
const rootMain = require('../../../.storybook/main');
module.exports = {
core: { builder: 'webpack5' },
stories: ['../../admin/ui/**/src/lib/**/*.stories.ts'],
+2 -2
View File
@@ -1,6 +1,6 @@
import {
cleanupProject,
newAngularProject,
newProject,
runCLI,
uniq,
updateFile,
@@ -9,7 +9,7 @@ import * as path from 'path';
describe('Angular Package', () => {
describe('linting', () => {
beforeAll(() => newAngularProject());
beforeAll(() => newProject());
afterAll(() => cleanupProject());
it('should support eslint and pass linting on the standard generated code', async () => {
+2 -2
View File
@@ -1,7 +1,7 @@
import {
cleanupProject,
expectTestsPass,
newAngularProject,
newProject,
readJson,
runCLI,
runCLIAsync,
@@ -10,7 +10,7 @@ import {
} from '@nrwl/e2e/utils';
describe('Angular Config', () => {
beforeAll(() => newAngularProject());
beforeAll(() => newProject());
afterAll(() => cleanupProject());
it('should upgrade the config correctly', async () => {
@@ -1,6 +1,6 @@
import {
cleanupProject,
newAngularProject,
newProject,
promisifiedTreeKill,
readProjectConfig,
runCLI,
@@ -16,7 +16,7 @@ import { names } from '@nrwl/devkit';
describe('Angular Projects', () => {
let proj: string;
beforeAll(() => (proj = newAngularProject()));
beforeAll(() => (proj = newProject()));
afterAll(() => cleanupProject());
it('should serve the host and remote apps successfully, even with a shared library with a secondary entry point between them', async () => {
+2 -2
View File
@@ -3,7 +3,7 @@ import {
cleanupProject,
getSize,
killPorts,
newAngularProject,
newProject,
promisifiedTreeKill,
readFile,
runCLI,
@@ -20,7 +20,7 @@ import { names } from '@nrwl/devkit';
describe('Angular Projects', () => {
let proj: string;
beforeAll(() => (proj = newAngularProject()));
beforeAll(() => (proj = newProject()));
afterAll(() => cleanupProject());
it('should generate an app, a lib, link them, build, serve and test both correctly', async () => {
@@ -2,7 +2,7 @@ import {
checkFilesDoNotExist,
cleanupProject,
createFile,
newAngularProject,
newProject,
runCLI,
uniq,
updateFile,
@@ -17,7 +17,7 @@ describe('Angular Cypress Component Tests', () => {
const buildableLibName = uniq('cy-angular-buildable-lib');
beforeAll(async () => {
projectName = newAngularProject({ name: uniq('cy-ng') });
projectName = newProject({ name: uniq('cy-ng') });
runCLI(`generate @nrwl/angular:app ${appName} --no-interactive`);
runCLI(
`generate @nrwl/angular:component fancy-component --project=${appName} --no-interactive`
+125 -122
View File
@@ -1,9 +1,13 @@
import {
checkFilesExist,
cleanupProject,
newAngularProject,
newProject,
readFile,
runCLI,
uniq,
updateFile,
} from '@nrwl/e2e/utils';
import { classify } from '@nrwl/workspace/src/utils/strings';
describe('Move Angular Project', () => {
let proj: string;
@@ -12,7 +16,7 @@ describe('Move Angular Project', () => {
let newPath: string;
beforeAll(() => {
proj = newAngularProject();
proj = newProject();
app1 = uniq('app1');
app2 = uniq('app2');
newPath = `subfolder/${app2}`;
@@ -21,127 +25,126 @@ describe('Move Angular Project', () => {
afterAll(() => cleanupProject());
it('reenabe', () => {});
/**
* Tries moving an app from ${app1} -> subfolder/${app2}
*/
// it('should work for apps', () => {
// const moveOutput = runCLI(
// `generate @nrwl/angular:move --project ${app1} ${newPath}`
// );
//
// // just check the output
// expect(moveOutput).toContain(`DELETE apps/${app1}`);
// expect(moveOutput).toContain(`CREATE apps/${newPath}/jest.config.ts`);
// expect(moveOutput).toContain(`CREATE apps/${newPath}/tsconfig.app.json`);
// expect(moveOutput).toContain(`CREATE apps/${newPath}/tsconfig.json`);
// expect(moveOutput).toContain(`CREATE apps/${newPath}/tsconfig.spec.json`);
// expect(moveOutput).toContain(`CREATE apps/${newPath}/.eslintrc.json`);
// expect(moveOutput).toContain(`CREATE apps/${newPath}/src/favicon.ico`);
// expect(moveOutput).toContain(`CREATE apps/${newPath}/src/index.html`);
// expect(moveOutput).toContain(`CREATE apps/${newPath}/src/main.ts`);
// expect(moveOutput).toContain(`CREATE apps/${newPath}/src/styles.css`);
// expect(moveOutput).toContain(`CREATE apps/${newPath}/src/test-setup.ts`);
// expect(moveOutput).toContain(
// `CREATE apps/${newPath}/src/app/app.component.html`
// );
// expect(moveOutput).toContain(
// `CREATE apps/${newPath}/src/app/app.module.ts`
// );
// expect(moveOutput).toContain(`CREATE apps/${newPath}/src/assets/.gitkeep`);
// });
//
// /**
// * Tries moving an e2e project from ${app1} -> ${newPath}
// */
// it('should work for e2e projects w/custom cypress config', () => {
// // by default the cypress config doesn't contain any app specific paths
// // create a custom config with some app specific paths
// updateFile(
// `apps/${app1}-e2e/cypress.config.ts`,
// `
// import { defineConfig } from 'cypress';
// import { nxE2EPreset } from '@nrwl/cypress/plugins/cypress-preset';
//
// export default defineConfig({
// e2e: {
// ...nxE2EPreset(__dirname),
// videosFolder: '../../dist/cypress/apps/${app1}-e2e/videos',
// screenshotsFolder: '../../dist/cypress/apps/${app1}-e2e/screenshots',
// },
// });
// `
// );
// const moveOutput = runCLI(
// `generate @nrwl/angular:move --projectName=${app1}-e2e --destination=${newPath}-e2e`
// );
//
// // just check that the cypress.config.ts is updated correctly
// const cypressConfigPath = `apps/${newPath}-e2e/cypress.config.ts`;
// expect(moveOutput).toContain(`CREATE ${cypressConfigPath}`);
// checkFilesExist(cypressConfigPath);
// const cypressConfig = readFile(cypressConfigPath);
//
// expect(cypressConfig).toContain(
// `../../../dist/cypress/apps/${newPath}-e2e/videos`
// );
// expect(cypressConfig).toContain(
// `../../../dist/cypress/apps/${newPath}-e2e/screenshots`
// );
// });
//
// /**
// * Tries moving a library from ${lib} -> shared/${lib}
// */
// it('should work for libraries', () => {
// const lib1 = uniq('mylib');
// const lib2 = uniq('mylib');
// runCLI(`generate @nrwl/angular:lib ${lib1}`);
//
// /**
// * Create a library which imports the module from the other lib
// */
//
// runCLI(`generate @nrwl/angular:lib ${lib2}`);
//
// updateFile(
// `libs/${lib2}/src/lib/${lib2}.module.ts`,
// `import { ${classify(lib1)}Module } from '@${proj}/${lib1}';
//
// export class ExtendedModule extends ${classify(lib1)}Module { }`
// );
//
// const moveOutput = runCLI(
// `generate @nrwl/angular:move --projectName=${lib1} --destination=shared/${lib1}`
// );
//
// const newPath = `libs/shared/${lib1}`;
// const newModule = `Shared${classify(lib1)}Module`;
//
// const testSetupPath = `${newPath}/src/test-setup.ts`;
// expect(moveOutput).toContain(`CREATE ${testSetupPath}`);
// checkFilesExist(testSetupPath);
//
// const modulePath = `${newPath}/src/lib/shared-${lib1}.module.ts`;
// expect(moveOutput).toContain(`CREATE ${modulePath}`);
// checkFilesExist(modulePath);
// const moduleFile = readFile(modulePath);
// expect(moduleFile).toContain(`export class ${newModule}`);
//
// const indexPath = `${newPath}/src/index.ts`;
// expect(moveOutput).toContain(`CREATE ${indexPath}`);
// checkFilesExist(indexPath);
// const index = readFile(indexPath);
// expect(index).toContain(`export * from './lib/shared-${lib1}.module'`);
//
// /**
// * Check that the import in lib2 has been updated
// */
// const lib2FilePath = `libs/${lib2}/src/lib/${lib2}.module.ts`;
// const lib2File = readFile(lib2FilePath);
// expect(lib2File).toContain(
// `import { ${newModule} } from '@${proj}/shared/${lib1}';`
// );
// expect(lib2File).toContain(`extends ${newModule}`);
// });
it('should work for apps', () => {
const moveOutput = runCLI(
`generate @nrwl/angular:move --project ${app1} ${newPath}`
);
// just check the output
expect(moveOutput).toContain(`DELETE apps/${app1}`);
expect(moveOutput).toContain(`CREATE apps/${newPath}/jest.config.ts`);
expect(moveOutput).toContain(`CREATE apps/${newPath}/tsconfig.app.json`);
expect(moveOutput).toContain(`CREATE apps/${newPath}/tsconfig.json`);
expect(moveOutput).toContain(`CREATE apps/${newPath}/tsconfig.spec.json`);
expect(moveOutput).toContain(`CREATE apps/${newPath}/.eslintrc.json`);
expect(moveOutput).toContain(`CREATE apps/${newPath}/src/favicon.ico`);
expect(moveOutput).toContain(`CREATE apps/${newPath}/src/index.html`);
expect(moveOutput).toContain(`CREATE apps/${newPath}/src/main.ts`);
expect(moveOutput).toContain(`CREATE apps/${newPath}/src/styles.css`);
expect(moveOutput).toContain(`CREATE apps/${newPath}/src/test-setup.ts`);
expect(moveOutput).toContain(
`CREATE apps/${newPath}/src/app/app.component.html`
);
expect(moveOutput).toContain(
`CREATE apps/${newPath}/src/app/app.module.ts`
);
expect(moveOutput).toContain(`CREATE apps/${newPath}/src/assets/.gitkeep`);
});
/**
* Tries moving an e2e project from ${app1} -> ${newPath}
*/
it('should work for e2e projects w/custom cypress config', () => {
// by default the cypress config doesn't contain any app specific paths
// create a custom config with some app specific paths
updateFile(
`apps/${app1}-e2e/cypress.config.ts`,
`
import { defineConfig } from 'cypress';
import { nxE2EPreset } from '@nrwl/cypress/plugins/cypress-preset';
export default defineConfig({
e2e: {
...nxE2EPreset(__dirname),
videosFolder: '../../dist/cypress/apps/${app1}-e2e/videos',
screenshotsFolder: '../../dist/cypress/apps/${app1}-e2e/screenshots',
},
});
`
);
const moveOutput = runCLI(
`generate @nrwl/angular:move --projectName=${app1}-e2e --destination=${newPath}-e2e`
);
// just check that the cypress.config.ts is updated correctly
const cypressConfigPath = `apps/${newPath}-e2e/cypress.config.ts`;
expect(moveOutput).toContain(`CREATE ${cypressConfigPath}`);
checkFilesExist(cypressConfigPath);
const cypressConfig = readFile(cypressConfigPath);
expect(cypressConfig).toContain(
`../../../dist/cypress/apps/${newPath}-e2e/videos`
);
expect(cypressConfig).toContain(
`../../../dist/cypress/apps/${newPath}-e2e/screenshots`
);
});
/**
* Tries moving a library from ${lib} -> shared/${lib}
*/
it('should work for libraries', () => {
const lib1 = uniq('mylib');
const lib2 = uniq('mylib');
runCLI(`generate @nrwl/angular:lib ${lib1}`);
/**
* Create a library which imports the module from the other lib
*/
runCLI(`generate @nrwl/angular:lib ${lib2}`);
updateFile(
`libs/${lib2}/src/lib/${lib2}.module.ts`,
`import { ${classify(lib1)}Module } from '@${proj}/${lib1}';
export class ExtendedModule extends ${classify(lib1)}Module { }`
);
const moveOutput = runCLI(
`generate @nrwl/angular:move --projectName=${lib1} --destination=shared/${lib1}`
);
const newPath = `libs/shared/${lib1}`;
const newModule = `Shared${classify(lib1)}Module`;
const testSetupPath = `${newPath}/src/test-setup.ts`;
expect(moveOutput).toContain(`CREATE ${testSetupPath}`);
checkFilesExist(testSetupPath);
const modulePath = `${newPath}/src/lib/shared-${lib1}.module.ts`;
expect(moveOutput).toContain(`CREATE ${modulePath}`);
checkFilesExist(modulePath);
const moduleFile = readFile(modulePath);
expect(moduleFile).toContain(`export class ${newModule}`);
const indexPath = `${newPath}/src/index.ts`;
expect(moveOutput).toContain(`CREATE ${indexPath}`);
checkFilesExist(indexPath);
const index = readFile(indexPath);
expect(index).toContain(`export * from './lib/shared-${lib1}.module'`);
/**
* Check that the import in lib2 has been updated
*/
const lib2FilePath = `libs/${lib2}/src/lib/${lib2}.module.ts`;
const lib2File = readFile(lib2FilePath);
expect(lib2File).toContain(
`import { ${newModule} } from '@${proj}/shared/${lib1}';`
);
expect(lib2File).toContain(`extends ${newModule}`);
});
});
+2 -2
View File
@@ -2,7 +2,7 @@ import {
cleanupProject,
expectTestsPass,
getSelectedPackageManager,
newAngularProject,
newProject,
readJson,
runCLI,
runCLIAsync,
@@ -12,7 +12,7 @@ import {
describe('Angular Package', () => {
describe('ngrx', () => {
beforeAll(() => {
newAngularProject();
newProject();
});
afterAll(() => {
cleanupProject();
+2 -2
View File
@@ -1,7 +1,7 @@
import {
cleanupProject,
listFiles,
newAngularProject,
newProject,
readFile,
removeFile,
runCLI,
@@ -117,7 +117,7 @@ describe('Tailwind support', () => {
};
beforeAll(() => {
project = newAngularProject();
project = newProject();
// Create tailwind config in the workspace root
createWorkspaceTailwindConfigFile();
+2 -8
View File
@@ -1,10 +1,4 @@
import {
newAngularProject,
newProject,
runCLI,
runCLIAsync,
uniq,
} from '@nrwl/e2e/utils';
import { newProject, runCLI, runCLIAsync, uniq } from '@nrwl/e2e/utils';
describe('Jest root projects', () => {
const myapp = uniq('myapp');
@@ -12,7 +6,7 @@ describe('Jest root projects', () => {
describe('angular', () => {
beforeAll(() => {
newAngularProject();
newProject();
});
it('should test root level app projects', async () => {
+2 -3
View File
@@ -3,7 +3,6 @@ import {
checkFilesExist,
cleanupProject,
createFile,
newAngularProject,
newProject,
readFile,
readJson,
@@ -186,7 +185,7 @@ describe('Linter', () => {
}, 1000000);
it('lint plugin should ensure module boundaries', () => {
const proj = newAngularProject();
const proj = newProject();
const myapp = uniq('myapp');
const myapp2 = uniq('myapp2');
const mylib = uniq('mylib');
@@ -516,7 +515,7 @@ export function tslibC(): string {
const myapp = uniq('myapp');
const mylib = uniq('mylib');
newAngularProject();
newProject();
runCLI(`generate @nrwl/angular:app ${myapp} --rootProject=true`);
let rootEslint = readJson('.eslintrc.json');
+1 -1
View File
@@ -22,7 +22,7 @@ describe('Nx Commands', () => {
afterAll(() => cleanupProject());
describe('show', () => {
it('ttt should show the list of projects', () => {
it('should show the list of projects', () => {
const app1 = uniq('myapp');
const app2 = uniq('myapp');
expect(runCLI('show projects')).toEqual('');
+130 -2
View File
@@ -9,12 +9,10 @@ import {
expectJestTestsToPass,
readFile,
exists,
renameFile,
updateProjectConfig,
readProjectConfig,
tmpProjPath,
readResolvedConfiguration,
removeFile,
getPackageManagerCommand,
getSelectedPackageManager,
runCommand,
@@ -705,6 +703,136 @@ describe('Workspace Tests', () => {
updateFile('nx.json', JSON.stringify(nxJson));
});
it('should work when moving a lib to a subfolder', async () => {
const lib1 = uniq('lib1');
const lib2 = uniq('lib2');
const lib3 = uniq('lib3');
runCLI(`generate @nrwl/workspace:lib ${lib1}`);
updateFile(
`libs/${lib1}/src/lib/${lib1}.ts`,
`export function fromLibOne() { console.log('This is completely pointless'); }`
);
updateFile(
`libs/${lib1}/src/index.ts`,
`export * from './lib/${lib1}.ts'`
);
/**
* Create a library which imports a class from lib1
*/
runCLI(`generate @nrwl/workspace:lib ${lib2}/ui`);
updateFile(
`libs/${lib2}/ui/src/lib/${lib2}-ui.ts`,
`import { fromLibOne } from '@${proj}/${lib1}';
export const fromLibTwo = () => fromLibOne();`
);
/**
* Create a library which has an implicit dependency on lib1
*/
runCLI(`generate @nrwl/workspace:lib ${lib3}`);
updateProjectConfig(lib3, (config) => {
config.implicitDependencies = [lib1];
return config;
});
/**
* Now try to move lib1
*/
const moveOutput = runCLI(
`generate @nrwl/workspace:move --project ${lib1} ${lib1}/data-access`
);
expect(moveOutput).toContain(`DELETE libs/${lib1}/project.json`);
expect(exists(`libs/${lib1}/project.json`)).toBeFalsy();
const newPath = `libs/${lib1}/data-access`;
const newName = `${lib1}-data-access`;
const readmePath = `${newPath}/README.md`;
expect(moveOutput).toContain(`CREATE ${readmePath}`);
checkFilesExist(readmePath);
const jestConfigPath = `${newPath}/jest.config.ts`;
expect(moveOutput).toContain(`CREATE ${jestConfigPath}`);
checkFilesExist(jestConfigPath);
const jestConfig = readFile(jestConfigPath);
expect(jestConfig).toContain(`displayName: '${lib1}-data-access'`);
expect(jestConfig).toContain(`preset: '../../../jest.preset.js'`);
expect(jestConfig).toContain(`'../../../coverage/${newPath}'`);
const tsConfigPath = `${newPath}/tsconfig.json`;
expect(moveOutput).toContain(`CREATE ${tsConfigPath}`);
checkFilesExist(tsConfigPath);
const tsConfigLibPath = `${newPath}/tsconfig.lib.json`;
expect(moveOutput).toContain(`CREATE ${tsConfigLibPath}`);
checkFilesExist(tsConfigLibPath);
const tsConfigLib = readJson(tsConfigLibPath);
expect(tsConfigLib.compilerOptions.outDir).toEqual(
'../../../dist/out-tsc'
);
const tsConfigSpecPath = `${newPath}/tsconfig.spec.json`;
expect(moveOutput).toContain(`CREATE ${tsConfigSpecPath}`);
checkFilesExist(tsConfigSpecPath);
const tsConfigSpec = readJson(tsConfigSpecPath);
expect(tsConfigSpec.compilerOptions.outDir).toEqual(
'../../../dist/out-tsc'
);
const indexPath = `${newPath}/src/index.ts`;
expect(moveOutput).toContain(`CREATE ${indexPath}`);
checkFilesExist(indexPath);
const rootClassPath = `${newPath}/src/lib/${lib1}.ts`;
expect(moveOutput).toContain(`CREATE ${rootClassPath}`);
checkFilesExist(rootClassPath);
let workspace = readResolvedConfiguration();
expect(workspace.projects[lib1]).toBeUndefined();
const newConfig = readProjectConfig(newName);
expect(newConfig).toMatchObject({
tags: [],
});
const lib3Config = readProjectConfig(lib3);
expect(lib3Config.implicitDependencies).toEqual([`${lib1}-data-access`]);
expect(moveOutput).toContain('UPDATE tsconfig.base.json');
const rootTsConfig = readJson('tsconfig.base.json');
expect(
rootTsConfig.compilerOptions.paths[`@${proj}/${lib1}`]
).toBeUndefined();
expect(
rootTsConfig.compilerOptions.paths[`@${proj}/${lib1}/data-access`]
).toEqual([`libs/${lib1}/data-access/src/index.ts`]);
workspace = readResolvedConfiguration();
expect(workspace.projects[lib1]).toBeUndefined();
const project = readProjectConfig(newName);
expect(project).toBeTruthy();
expect(project.sourceRoot).toBe(`${newPath}/src`);
expect(project.targets.lint.options.lintFilePatterns).toEqual([
`libs/${lib1}/data-access/**/*.ts`,
]);
/**
* Check that the import in lib2 has been updated
*/
const lib2FilePath = `libs/${lib2}/ui/src/lib/${lib2}-ui.ts`;
const lib2File = readFile(lib2FilePath);
expect(lib2File).toContain(
`import { fromLibOne } from '@${proj}/${lib1}/data-access';`
);
});
it('should work for libraries when scope is unset', async () => {
const json = readJson('nx.json');
delete json.npmScope;
-15
View File
@@ -368,21 +368,6 @@ export function newProject({
}
}
export function newAngularProject({
name = uniq('proj'),
packageManager = getSelectedPackageManager(),
} = {}): string {
const projScope = newProject({ name, packageManager });
const angularPackages = [
'@angular-devkit/core',
'@angular-devkit/schematics',
'@schematics/angular',
];
packageInstall(angularPackages.join(` `), projScope, 'latest');
return projScope;
}
export function newLernaWorkspace({
name = uniq('lerna-proj'),
packageManager = getSelectedPackageManager(),
-11
View File
@@ -1,11 +0,0 @@
module.exports = {
stories: [],
addons: ['@storybook/addon-essentials'],
// uncomment the property below if you want to apply some webpack config globally
// webpackFinal: async (config, { configType }) => {
// // Make whatever fine-grained changes you need that should apply to all storybook configs
// // Return the altered config
// return config;
// },
};
View File
-14
View File
@@ -1,14 +0,0 @@
{
"extends": "../../tsconfig.base.json",
"exclude": [
"../**/*.spec.js",
"../**/*.test.js",
"../**/*.spec.ts",
"../**/*.test.ts",
"../**/*.spec.tsx",
"../**/*.test.tsx",
"../**/*.spec.jsx",
"../**/*.test.jsx"
],
"include": ["../**/*"]
}
+2 -18
View File
@@ -1,28 +1,12 @@
const rootMain = require('../../.storybook/main');
module.exports = {
...rootMain,
core: { ...rootMain.core, builder: 'webpack5' },
core: { builder: 'webpack5' },
stories: [
...rootMain.stories,
'../src/app/**/*.stories.mdx',
'../src/app/**/*.stories.@(js|jsx|ts|tsx)',
],
addons: [
...rootMain.addons,
'@storybook/addon-essentials',
'@nrwl/react/plugins/storybook',
'storybook-dark-mode',
],
webpackFinal: async (config, { configType }) => {
// apply any global webpack configs that might have been specified in .storybook/main.js
if (rootMain.webpackFinal) {
config = await rootMain.webpackFinal(config, { configType });
}
// add your own webpack tweaks if needed
return config;
},
};
+2 -18
View File
@@ -1,24 +1,8 @@
const rootMain = require('../../.storybook/main');
module.exports = {
...rootMain,
core: { ...rootMain.core, builder: 'webpack5' },
core: { builder: 'webpack5' },
stories: [
...rootMain.stories,
'../src/lib/**/*.stories.mdx',
'../src/lib/**/*.stories.@(js|jsx|ts|tsx)',
],
addons: [...rootMain.addons, '@nrwl/react/plugins/storybook'],
webpackFinal: async (config, { configType }) => {
// apply any global webpack configs that might have been specified in .storybook/main.js
if (rootMain.webpackFinal) {
config = await rootMain.webpackFinal(config, { configType });
}
// add your own webpack tweaks if needed
return config;
},
addons: ['@storybook/addon-essentials', '@nrwl/react/plugins/storybook'],
};
+2 -18
View File
@@ -1,24 +1,8 @@
const rootMain = require('../../.storybook/main');
module.exports = {
...rootMain,
core: { ...rootMain.core, builder: 'webpack5' },
core: { builder: 'webpack5' },
stories: [
...rootMain.stories,
'../src/lib/**/*.stories.mdx',
'../src/lib/**/*.stories.@(js|jsx|ts|tsx)',
],
addons: [...rootMain.addons, '@nrwl/react/plugins/storybook'],
webpackFinal: async (config, { configType }) => {
// apply any global webpack configs that might have been specified in .storybook/main.js
if (rootMain.webpackFinal) {
config = await rootMain.webpackFinal(config, { configType });
}
// add your own webpack tweaks if needed
return config;
},
addons: ['@storybook/addon-essentials', '@nrwl/react/plugins/storybook'],
};
+2 -16
View File
@@ -1,22 +1,8 @@
const rootMain = require('../../.storybook/main');
module.exports = {
...rootMain,
core: { ...rootMain.core, builder: 'webpack5' },
core: { builder: 'webpack5' },
stories: [
...rootMain.stories,
'../src/lib/**/*.stories.mdx',
'../src/lib/**/*.stories.@(js|jsx|ts|tsx)',
],
addons: [...rootMain.addons, '@nrwl/react/plugins/storybook'],
webpackFinal: async (config, { configType }) => {
// apply any global webpack configs that might have been specified in .storybook/main.js
if (rootMain.webpackFinal) {
config = await rootMain.webpackFinal(config, { configType });
}
// add your own webpack tweaks if needed
return config;
},
addons: ['@storybook/addon-essentials', '@nrwl/react/plugins/storybook'],
};
+1 -1
View File
@@ -1,6 +1,6 @@
{
"packages": ["build/packages/*", "build/packages/nx/native-packages/*"],
"version": "15.7.0",
"version": "15.7.1",
"granularPathspec": false,
"command": {
"publish": {
@@ -4,7 +4,6 @@ import {
moveFilesToNewDirectory,
Tree,
} from '@nrwl/devkit';
import { wrapAngularDevkitSchematic } from '@nrwl/devkit/ngcli-adapter';
import { UnitTestRunner } from '../../../utils/test-runners';
import { angularInitGenerator } from '../../init/init';
import { setupTailwindGenerator } from '../../setup-tailwind/setup-tailwind';
@@ -38,6 +37,7 @@ export async function applicationGenerator(
skipFormat: true,
});
const { wrapAngularDevkitSchematic } = require('@nrwl/devkit/ngcli-adapter');
const angularAppSchematic = wrapAngularDevkitSchematic(
'@schematics/angular',
'application'
@@ -1,9 +1,9 @@
import type { Tree } from '@nrwl/devkit';
import { joinPathFragments, moveFilesToNewDirectory } from '@nrwl/devkit';
import { wrapAngularDevkitSchematic } from '@nrwl/devkit/ngcli-adapter';
import type { NormalizedSchema } from './normalized-schema';
export async function addProtractor(host: Tree, options: NormalizedSchema) {
const { wrapAngularDevkitSchematic } = require('@nrwl/devkit/ngcli-adapter');
const protractorSchematic = wrapAngularDevkitSchematic(
'@schematics/angular',
'e2e'
@@ -7,7 +7,6 @@ import {
Tree,
updateNxJson,
} from '@nrwl/devkit';
import { wrapAngularDevkitSchematic } from '@nrwl/devkit/ngcli-adapter';
import { join } from 'path';
import { UnitTestRunner } from '../../utils/test-runners';
import { angularInitGenerator } from '../init/init';
@@ -63,6 +62,7 @@ export async function applicationGenerator(
skipFormat: true,
});
const { wrapAngularDevkitSchematic } = require('@nrwl/devkit/ngcli-adapter');
const angularAppSchematic = wrapAngularDevkitSchematic(
'@schematics/angular',
'application'
@@ -1,9 +1,9 @@
import type { Tree } from '@nrwl/devkit';
import { joinPathFragments, moveFilesToNewDirectory } from '@nrwl/devkit';
import { wrapAngularDevkitSchematic } from '@nrwl/devkit/ngcli-adapter';
import type { NormalizedSchema } from './normalized-schema';
export async function addProtractor(host: Tree, options: NormalizedSchema) {
const { wrapAngularDevkitSchematic } = require('@nrwl/devkit/ngcli-adapter');
const protractorSchematic = wrapAngularDevkitSchematic(
'@schematics/angular',
'e2e'
@@ -6,7 +6,6 @@ import {
readProjectConfiguration,
stripIndents,
} from '@nrwl/devkit';
import { wrapAngularDevkitSchematic } from '@nrwl/devkit/ngcli-adapter';
import { pathStartsWith } from '../utils/path';
import { exportComponentInEntryPoint } from './lib/component';
import { normalizeOptions } from './lib/normalize-options';
@@ -30,6 +29,7 @@ export async function componentGenerator(tree: Tree, rawOptions: Schema) {
checkPathUnderProjectRoot(tree, options);
const { wrapAngularDevkitSchematic } = require('@nrwl/devkit/ngcli-adapter');
const angularComponentSchematic = wrapAngularDevkitSchematic(
'@schematics/angular',
'component'
@@ -1,5 +1,6 @@
import { cypressInitGenerator } from '@nrwl/cypress';
import {
ensurePackage,
formatFiles,
GeneratorCallback,
logger,
@@ -26,6 +27,23 @@ export async function angularInitGenerator(
const options = normalizeOptions(rawOptions);
setDefaults(host, options);
const peerDepsToInstall = [
'@angular-devkit/core',
'@angular-devkit/schematics',
'@schematics/angular',
];
let devkitVersion: string;
peerDepsToInstall.forEach((pkg) => {
const packageVersion = getInstalledPackageVersion(host, pkg);
if (!packageVersion) {
devkitVersion ??=
getInstalledPackageVersion(host, '@angular-devkit/build-angular') ??
backwardCompatibleVersions.angularV14.angularDevkitVersion;
ensurePackage(host, pkg, devkitVersion);
}
});
const depsTask = !options.skipPackageJson
? updateDependencies(host)
: () => {};
@@ -1,3 +1,22 @@
jest.mock('@nrwl/devkit', () => ({
...jest.requireActual('@nrwl/devkit'),
// need to mock so it doesn't resolve what the workspace has installed
// and be able to test with different versions
ensurePackage: jest.fn().mockImplementation((tree, pkg, version, options) => {
updateJson(tree, 'package.json', (json) => ({
...json,
dependencies: {
...json.dependencies,
...(options?.dev === false ? { [pkg]: version } : {}),
},
devDependencies: {
...json.devDependencies,
...(options?.dev ?? true ? { [pkg]: version } : {}),
},
}));
}),
}));
import { NxJsonConfiguration, readJson, Tree, updateJson } from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { Linter } from '@nrwl/linter';
@@ -1,5 +1,6 @@
import { cypressInitGenerator } from '@nrwl/cypress';
import {
ensurePackage,
formatFiles,
GeneratorCallback,
logger,
@@ -48,6 +49,23 @@ export async function angularInitGenerator(
return;
}
const peerDepsToInstall = [
'@angular-devkit/core',
'@angular-devkit/schematics',
'@schematics/angular',
];
let devkitVersion: string;
peerDepsToInstall.forEach((pkg) => {
const packageVersion = getInstalledPackageVersion(tree, pkg);
if (!packageVersion) {
devkitVersion ??=
getInstalledPackageVersion(tree, '@angular-devkit/build-angular') ??
angularDevkitVersion;
ensurePackage(tree, pkg, devkitVersion);
}
});
const options = normalizeOptions(rawOptions);
setDefaults(tree, options);
@@ -27,6 +27,23 @@ jest.mock('@nrwl/devkit', () => {
return {
...jest.requireActual('@nrwl/devkit'),
createProjectGraphAsync: jest.fn().mockImplementation(() => projectGraph),
// need to mock so it doesn't resolve what the workspace has installed
// and be able to test with different versions
ensurePackage: jest
.fn()
.mockImplementation((tree, pkg, version, options) => {
updateJson(tree, 'package.json', (json) => ({
...json,
dependencies: {
...json.dependencies,
...(options?.dev === false ? { [pkg]: version } : {}),
},
devDependencies: {
...json.devDependencies,
...(options?.dev ?? true ? { [pkg]: version } : {}),
},
}));
}),
};
});
@@ -6,7 +6,6 @@ import {
removeDependenciesFromPackageJson,
Tree,
} from '@nrwl/devkit';
import { wrapAngularDevkitSchematic } from '@nrwl/devkit/ngcli-adapter';
import { jestProjectGenerator } from '@nrwl/jest';
import { Linter } from '@nrwl/linter';
import { lt } from 'semver';
@@ -65,6 +64,7 @@ export async function libraryGenerator(tree: Tree, schema: Schema) {
e2eTestRunner: E2eTestRunner.None,
});
const { wrapAngularDevkitSchematic } = require('@nrwl/devkit/ngcli-adapter');
const runAngularLibrarySchematic = wrapAngularDevkitSchematic(
'@schematics/angular',
'library'
@@ -5,7 +5,6 @@ import {
readNxJson,
readProjectConfiguration,
} from '@nrwl/devkit';
import { wrapAngularDevkitSchematic } from '@nrwl/devkit/ngcli-adapter';
import { exportScam } from '../utils/export-scam';
import { getDirectiveFileInfo } from '../utils/file-info';
import { pathStartsWith } from '../utils/path';
@@ -18,6 +17,7 @@ export async function scamDirectiveGenerator(tree: Tree, rawOptions: Schema) {
checkPathUnderProjectRoot(tree, options);
const { wrapAngularDevkitSchematic } = require('@nrwl/devkit/ngcli-adapter');
const angularDirectiveSchematic = wrapAngularDevkitSchematic(
'@schematics/angular',
'directive'
@@ -5,7 +5,6 @@ import {
readNxJson,
readProjectConfiguration,
} from '@nrwl/devkit';
import { wrapAngularDevkitSchematic } from '@nrwl/devkit/ngcli-adapter';
import { exportScam } from '../utils/export-scam';
import { getPipeFileInfo } from '../utils/file-info';
import { pathStartsWith } from '../utils/path';
@@ -18,6 +17,7 @@ export async function scamPipeGenerator(tree: Tree, rawOptions: Schema) {
checkPathUnderProjectRoot(tree, options);
const { wrapAngularDevkitSchematic } = require('@nrwl/devkit/ngcli-adapter');
const angularPipeSchematic = wrapAngularDevkitSchematic(
'@schematics/angular',
'pipe'
+1 -1
View File
@@ -5,7 +5,6 @@ import {
readNxJson,
readProjectConfiguration,
} from '@nrwl/devkit';
import { wrapAngularDevkitSchematic } from '@nrwl/devkit/ngcli-adapter';
import { exportScam } from '../utils/export-scam';
import { getComponentFileInfo } from '../utils/file-info';
import { pathStartsWith } from '../utils/path';
@@ -18,6 +17,7 @@ export async function scamGenerator(tree: Tree, rawOptions: Schema) {
checkPathUnderProjectRoot(tree, options);
const { wrapAngularDevkitSchematic } = require('@nrwl/devkit/ngcli-adapter');
const angularComponentSchematic = wrapAngularDevkitSchematic(
'@schematics/angular',
'component'
@@ -1,5 +1,4 @@
import type { Tree } from '@nrwl/devkit';
import { wrapAngularDevkitSchematic } from '@nrwl/devkit/ngcli-adapter';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { Linter } from '@nrwl/linter';
import { UnitTestRunner } from '../../utils/test-runners';
@@ -10,6 +9,7 @@ export async function createStorybookTestWorkspaceForLib(
): Promise<Tree> {
let tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
const { wrapAngularDevkitSchematic } = require('@nrwl/devkit/ngcli-adapter');
const moduleGenerator = wrapAngularDevkitSchematic(
'@schematics/angular',
'module'
@@ -1,6 +1,5 @@
import type { Tree } from '@nrwl/devkit';
import { formatFiles } from '@nrwl/devkit';
import { wrapAngularDevkitSchematic } from '@nrwl/devkit/ngcli-adapter';
import { normalizeOptions, updateTsConfig } from './lib';
import type { WebWorkerGeneratorOptions } from './schema';
@@ -10,6 +9,7 @@ export async function webWorkerGenerator(
): Promise<void> {
const options = normalizeOptions(rawOptions);
const { skipFormat, ...schematicOptions } = options;
const { wrapAngularDevkitSchematic } = require('@nrwl/devkit/ngcli-adapter');
const webWorkerSchematic = wrapAngularDevkitSchematic(
'@schematics/angular',
'web-worker'
+1 -1
View File
@@ -1,6 +1,6 @@
import { join } from 'path';
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
import { Tree, Rule } from '@angular-devkit/schematics';
import type { Tree, Rule } from '@angular-devkit/schematics';
const testRunner = new SchematicTestRunner(
'@nrwl/cypress',
@@ -100,7 +100,6 @@ export async function* esbuildExecutor(
const ctx = await esbuild.context({
...esbuildOptions,
plugins: [
...(esbuildOptions.plugins ?? []),
// Only emit info on one of the watch processes.
idx === 0
? {
@@ -7,6 +7,7 @@ import {
} from '@nrwl/devkit';
import {
DepConstraint,
findConstraintsFor,
findTransitiveExternalDependencies,
hasBannedDependencies,
hasBannedImport,
@@ -19,6 +20,68 @@ jest.mock('nx/src/utils/workspace-root', () => ({
workspaceRoot: '/root',
}));
describe('findConstraintsFor', () => {
it('should find constraints matching tag', () => {
const constriants: DepConstraint[] = [
{ sourceTag: 'a', onlyDependOnLibsWithTags: ['b'] },
{ sourceTag: 'b', onlyDependOnLibsWithTags: ['c'] },
{ sourceTag: 'c', onlyDependOnLibsWithTags: ['a'] },
];
expect(
findConstraintsFor(constriants, {
type: 'lib',
name: 'someLib',
data: { root: '.', files: [], tags: ['b'] },
})
).toEqual([{ sourceTag: 'b', onlyDependOnLibsWithTags: ['c'] }]);
});
it('should find constraints matching *', () => {
const constriants: DepConstraint[] = [
{ sourceTag: 'a', onlyDependOnLibsWithTags: ['b'] },
{ sourceTag: 'b', onlyDependOnLibsWithTags: ['c'] },
{ sourceTag: '*', onlyDependOnLibsWithTags: ['a'] },
];
expect(
findConstraintsFor(constriants, {
type: 'lib',
name: 'someLib',
data: { root: '.', files: [], tags: ['b'] },
})
).toEqual([
{ sourceTag: 'b', onlyDependOnLibsWithTags: ['c'] },
{ sourceTag: '*', onlyDependOnLibsWithTags: ['a'] },
]);
});
it('should find constraints matching regex', () => {
const constriants: DepConstraint[] = [
{ sourceTag: 'a', onlyDependOnLibsWithTags: ['a'] },
{ sourceTag: '/^b$/', onlyDependOnLibsWithTags: ['c'] },
{ sourceTag: '/a|b/', onlyDependOnLibsWithTags: ['c'] },
];
expect(
findConstraintsFor(constriants, {
type: 'lib',
name: 'someLib',
data: { root: '.', files: [], tags: ['b'] },
})
).toEqual([
{ sourceTag: '/^b$/', onlyDependOnLibsWithTags: ['c'] },
{ sourceTag: '/a|b/', onlyDependOnLibsWithTags: ['c'] },
]);
expect(
findConstraintsFor(constriants, {
type: 'lib',
name: 'someLib',
data: { root: '.', files: [], tags: ['baz'] },
})
).toEqual([{ sourceTag: '/a|b/', onlyDependOnLibsWithTags: ['c'] }]);
});
});
describe('hasBannedImport', () => {
const source: ProjectGraphProjectNode = {
type: 'lib',
@@ -346,19 +409,16 @@ describe('isAngularSecondaryEntrypoint', () => {
'apps/app.ts': '',
'libs/standard/package.json': '{ "version": "0.0.0" }',
'libs/standard/secondary/ng-package.json': JSON.stringify({
version: '0.0.0',
ngPackage: { lib: { entryFile: 'src/index.ts' } },
lib: { entryFile: 'src/index.ts' },
}),
'libs/standard/secondary/src/index.ts': 'const bla = "foo"',
'libs/standard/tertiary/ng-package.json': JSON.stringify({
version: '0.0.0',
ngPackage: { lib: { entryFile: 'src/public_api.ts' } },
lib: { entryFile: 'src/public_api.ts' },
}),
'libs/standard/tertiary/src/public_api.ts': 'const bla = "foo"',
'libs/features/package.json': '{ "version": "0.0.0" }',
'libs/features/secondary/ng-package.json': JSON.stringify({
version: '0.0.0',
ngPackage: { lib: { entryFile: 'random/folder/api.ts' } },
lib: { entryFile: 'random/folder/api.ts' },
}),
'libs/features/secondary/random/folder/api.ts': 'const bla = "foo"',
};
@@ -86,8 +86,23 @@ export function findDependenciesWithTags(
);
}
function hasTag(proj: ProjectGraphProjectNode, tag: string) {
return tag === '*' || (proj.data.tags || []).indexOf(tag) > -1;
const regexMap = new Map<string, RegExp>();
function hasTag(proj: ProjectGraphProjectNode, tag: string): boolean {
if (tag === '*') return true;
// if the tag is a regex, check if the project matches the regex
if (tag.startsWith('/') && tag.endsWith('/')) {
let regex;
if (regexMap.has(tag)) {
regex = regexMap.get(tag);
} else {
regex = new RegExp(tag.substring(1, tag.length - 1));
regexMap.set(tag, regex);
}
return (proj.data.tags || []).some((t) => regex.test(t));
}
return (proj.data.tags || []).indexOf(tag) > -1;
}
export function matchImportWithWildcard(
@@ -439,7 +454,8 @@ function fileIsSecondaryEntryPoint(file: string): boolean {
joinPathFragments(workspaceRoot, parent, 'ng-package.json')
);
if (ngPackageContent) {
const entryFile = parseJson(ngPackageContent)?.ngPackage?.lib?.entryFile;
// https://github.com/ng-packagr/ng-packagr/blob/23c718d04eea85e015b4c261310b7bd0c39e5311/src/ng-package.schema.json#L54
const entryFile = parseJson(ngPackageContent)?.lib?.entryFile;
return entryFile && file === joinPathFragments(parent, entryFile);
}
parent = joinPathFragments(parent, '../');
@@ -1,7 +1,7 @@
import * as ts from 'typescript';
import { InsertChange, ReplaceChange } from '@nrwl/workspace';
import { findNodes } from 'nx/src/utils/typescript';
import { Tree } from '@angular-devkit/schematics';
import type { Tree } from '@angular-devkit/schematics';
import { stripJsonComments } from '@nrwl/devkit';
import { Config } from '@jest/types';
@@ -1,4 +1,4 @@
import { Tree } from '@angular-devkit/schematics';
import type { Tree } from '@angular-devkit/schematics';
import { insert, RemoveChange } from '@nrwl/workspace';
import {
addOrUpdateProperty,
+1 -1
View File
@@ -1,6 +1,6 @@
import { join } from 'path';
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
import { Tree, Rule } from '@angular-devkit/schematics';
import type { Tree, Rule } from '@angular-devkit/schematics';
const testRunner = new SchematicTestRunner(
'@nrwl/jest',
+1 -1
View File
@@ -1,6 +1,6 @@
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
import { join } from 'path';
import { Tree } from '@angular-devkit/schematics';
import type { Tree } from '@angular-devkit/schematics';
const migrationTestRunner = new SchematicTestRunner(
'@nrwl/linter-migrations',
@@ -1,7 +1,6 @@
import type { Tree } from '@nrwl/devkit';
import { formatFiles } from '@nrwl/devkit';
import type { NestSchematic, NormalizedOptions } from './types';
import { wrapAngularDevkitSchematic } from '@nrwl/devkit/ngcli-adapter';
export async function runNestSchematic(
tree: Tree,
@@ -10,6 +9,7 @@ export async function runNestSchematic(
): Promise<any> {
const { skipFormat, ...schematicOptions } = options;
const { wrapAngularDevkitSchematic } = require('@nrwl/devkit/ngcli-adapter');
const nestSchematic = wrapAngularDevkitSchematic(
'@nestjs/schematics',
schematic
+16 -4
View File
@@ -1,14 +1,18 @@
import { sync as globSync } from 'fast-glob';
import { existsSync, readFileSync } from 'fs';
import { existsSync, readFileSync, statSync } from 'fs';
import ignore, { Ignore } from 'ignore';
import * as path from 'path';
import { basename, dirname, join } from 'path';
import { basename, dirname, extname, join } from 'path';
import { performance } from 'perf_hooks';
import { workspaceRoot } from '../utils/workspace-root';
import { readJsonFile } from '../utils/fileutils';
import { logger, NX_PREFIX } from '../utils/logger';
import { loadNxPlugins, readPluginPackageJson } from '../utils/nx-plugin';
import {
loadNxPlugins,
readPluginPackageJson,
registerPluginTSTranspiler,
} from '../utils/nx-plugin';
import * as yaml from 'js-yaml';
import type { NxJsonConfiguration, TargetDefaults } from './nx-json';
@@ -313,7 +317,15 @@ export class Workspaces {
const [implementationModulePath, implementationExportName] =
implementation.split('#');
return () => {
const module = require(path.join(directory, implementationModulePath));
const possibleModulePath = path.join(directory, implementationModulePath);
const validImplementations = ['', '.js', '.ts'].map(
(x) => possibleModulePath + x
);
const modulePath = validImplementations.find((f) => existsSync(f));
if (extname(modulePath) === '.ts') {
registerPluginTSTranspiler();
}
const module = require(modulePath);
return implementationExportName
? module[implementationExportName]
: module.default ?? module;
@@ -149,6 +149,278 @@ describe('createTaskGraph', () => {
});
});
it('should correctly set default configuration', () => {
const projectGraph = {
nodes: {
app1: {
name: 'app1',
type: 'app',
data: {
root: 'app1-root',
files: [],
targets: {
build: {
executor: 'my-executor',
configurations: {
ci: {},
},
dependsOn: [
{
projects: 'dependencies',
target: 'build',
},
],
},
},
},
},
lib1: {
name: 'lib1',
type: 'lib',
data: {
root: 'lib1-root',
files: [],
targets: {
build: {
executor: 'my-executor',
configurations: {
libDefault: {},
},
defaultConfiguration: 'libDefault',
dependsOn: [
{
projects: 'dependencies',
target: 'build',
},
],
},
},
},
},
lib2: {
name: 'lib2',
type: 'lib',
data: {
root: 'lib2-root',
files: [],
targets: {
build: {
executor: 'my-executor',
configurations: {
ci: {},
},
},
},
},
},
},
dependencies: {
app1: [{ source: 'app1', target: 'lib1', type: 'static' }],
lib1: [{ source: 'lib1', target: 'lib2', type: 'static' }],
lib2: [],
},
} as any;
const buildLib = createTaskGraph(
projectGraph,
{},
['lib1'],
['build'],
null,
{}
);
expect(buildLib).toEqual({
roots: ['lib2:build'],
tasks: {
'lib1:build:libDefault': {
id: 'lib1:build:libDefault',
target: {
project: 'lib1',
target: 'build',
configuration: 'libDefault',
},
overrides: {},
projectRoot: 'lib1-root',
},
'lib2:build': {
id: 'lib2:build',
target: {
project: 'lib2',
target: 'build',
},
overrides: {
__overrides_unparsed__: [],
},
projectRoot: 'lib2-root',
},
},
dependencies: {
'lib1:build:libDefault': ['lib2:build'],
'lib2:build': [],
},
});
const buildApp = createTaskGraph(
projectGraph,
{},
['app1'],
['build'],
'ci',
{}
);
expect(buildApp).toEqual({
roots: ['lib2:build:ci'],
tasks: {
'app1:build:ci': {
id: 'app1:build:ci',
target: {
project: 'app1',
target: 'build',
configuration: 'ci',
},
overrides: {},
projectRoot: 'app1-root',
},
'lib1:build:libDefault': {
id: 'lib1:build:libDefault',
target: {
project: 'lib1',
target: 'build',
configuration: 'libDefault',
},
overrides: {
__overrides_unparsed__: [],
},
projectRoot: 'lib1-root',
},
'lib2:build:ci': {
id: 'lib2:build:ci',
target: {
project: 'lib2',
target: 'build',
configuration: 'ci',
},
overrides: {
__overrides_unparsed__: [],
},
projectRoot: 'lib2-root',
},
},
dependencies: {
'app1:build:ci': ['lib1:build:libDefault'],
'lib1:build:libDefault': ['lib2:build:ci'],
'lib2:build:ci': [],
},
});
});
it('should not duplicate dependencies', () => {
const projectGraph = {
nodes: {
app1: {
name: 'app1',
type: 'app',
data: {
root: 'app1-root',
files: [],
targets: {
build: {
executor: 'my-executor',
dependsOn: [
{
projects: 'dependencies',
target: 'build',
},
],
},
},
},
},
lib1: {
name: 'lib1',
type: 'lib',
data: {
root: 'lib1-root',
files: [],
targets: {},
},
},
lib2: {
name: 'lib2',
type: 'lib',
data: {
root: 'lib2-root',
files: [],
targets: {},
},
},
lib3: {
name: 'lib3',
type: 'lib',
data: {
root: 'lib3-root',
files: [],
targets: {
build: {
executor: 'my-executor',
},
},
},
},
},
dependencies: {
app1: [
{ source: 'app1', target: 'lib1', type: 'static' },
{ source: 'app1', target: 'lib2', type: 'static' },
],
lib1: [{ source: 'lib1', target: 'lib3', type: 'static' }],
lib2: [{ source: 'lib2', target: 'lib3', type: 'static' }],
lib3: [],
},
} as any;
const buildApp = createTaskGraph(
projectGraph,
{},
['app1'],
['build'],
null,
{}
);
expect(buildApp).toEqual({
dependencies: {
'app1:build': ['lib3:build'],
'lib3:build': [],
},
roots: ['lib3:build'],
tasks: {
'app1:build': {
id: 'app1:build',
overrides: {},
projectRoot: 'app1-root',
target: {
project: 'app1',
target: 'build',
},
},
'lib3:build': {
id: 'lib3:build',
overrides: {
__overrides_unparsed__: [],
},
projectRoot: 'lib3-root',
target: {
project: 'lib3',
target: 'build',
},
},
},
});
});
it('should interpolate overrides', () => {
const oneTask = createTaskGraph(
projectGraph,
@@ -758,7 +1030,6 @@ describe('createTaskGraph', () => {
'app2:build',
'coreInfra:apply',
'app1:build',
'coreInfra:apply',
'infra2:apply',
],
'app2:build': [],
@@ -69,6 +69,14 @@ export class ProcessTasks {
}
}
for (const projectName of Object.keys(this.dependencies)) {
if (this.dependencies[projectName].length > 1) {
this.dependencies[projectName] = [
...new Set(this.dependencies[projectName]).values(),
];
}
}
return Object.keys(this.dependencies).filter(
(d) => this.dependencies[d].length === 0
);
@@ -224,10 +232,12 @@ export class ProcessTasks {
target: string,
configuration: string | undefined
) {
configuration ??= project.data.targets?.[target]?.defaultConfiguration;
const defaultConfiguration =
project.data.targets?.[target]?.defaultConfiguration;
configuration ??= defaultConfiguration;
return projectHasTargetAndConfiguration(project, target, configuration)
? configuration
: undefined;
: defaultConfiguration;
}
getId(
@@ -385,11 +385,27 @@ export class ForkedProcessTaskRunner {
...this.getDotenvVariablesForForkedProcess(),
...parseEnv(`.${task.target.target}.env`),
...parseEnv(`.env.${task.target.target}`),
...(task.target.configuration
? parseEnv(`.${task.target.target}.${task.target.configuration}.env`)
: {}),
...(task.target.configuration
? parseEnv(`.env.${task.target.target}.${task.target.configuration}`)
: {}),
...parseEnv(`${task.projectRoot}/.env`),
...parseEnv(`${task.projectRoot}/.local.env`),
...parseEnv(`${task.projectRoot}/.env.local`),
...parseEnv(`${task.projectRoot}/.${task.target.target}.env`),
...parseEnv(`${task.projectRoot}/.env.${task.target.target}`),
...(task.target.configuration
? parseEnv(
`${task.projectRoot}/.${task.target.target}.${task.target.configuration}.env`
)
: {}),
...(task.target.configuration
? parseEnv(
`${task.projectRoot}/.env.${task.target.target}.${task.target.configuration}`
)
: {}),
};
} else {
return {};
+7 -15
View File
@@ -72,8 +72,13 @@ export function createPackageJson(
const isOptionalPeer =
npmDeps.peerDependenciesMeta[packageName]?.optional;
if (!isOptionalPeer) {
packageJson.peerDependencies ??= {};
packageJson.peerDependencies[packageName] = version;
if (
!options.isProduction ||
rootPackageJson.dependencies?.[packageName]
) {
packageJson.peerDependencies ??= {};
packageJson.peerDependencies[packageName] = version;
}
} else if (!options.isProduction) {
// add peer optional dependencies if not in production
packageJson.peerDependencies ??= {};
@@ -184,16 +189,3 @@ function recursivelyCollectPeerDependencies(
return list;
}
}
function filterOptionalPeerDependencies(
packageJson: PackageJson
): Record<string, string> {
let peerDependencies;
Object.keys(packageJson.peerDependencies).forEach((key) => {
if (!packageJson.peerDependenciesMeta?.[key]?.optional) {
peerDependencies = peerDependencies || {};
peerDependencies[key] = packageJson.peerDependencies[key];
}
});
return peerDependencies;
}
+6 -2
View File
@@ -181,7 +181,11 @@ export function resolveLocalNxPlugin(
let tsNodeAndPathsRegistered = false;
function registerTSTranspiler() {
/**
* Register swc-node or ts-node if they are not currently registered
* with some default settings which work well for Nx plugins.
*/
export function registerPluginTSTranspiler() {
if (!tsNodeAndPathsRegistered) {
// nx-ignore-next-line
const ts: typeof import('typescript') = require('typescript');
@@ -208,7 +212,7 @@ function lookupLocalPlugin(importPath: string, root = workspaceRoot) {
}
if (!tsNodeAndPathsRegistered) {
registerTSTranspiler();
registerPluginTSTranspiler();
}
const projectConfig = workspace.projects[plugin];
+65
View File
@@ -0,0 +1,65 @@
import { Schema } from './params';
import { logger } from './logger';
import { printHelp } from './print-help';
describe('printHelp', () => {
it('should sort options by priority and name', () => {
const schema: Schema = {
properties: {
aImp: {
'x-priority': 'important',
},
bImp: {
'x-priority': 'important',
},
aNormal: {},
bNormal: {},
aDep: {
'x-deprecated': 'great reason',
},
bDep: {
'x-deprecated': 'even better reason',
},
aReq: {},
bReq: {},
aInt: {
'x-priority': 'internal',
},
bInt: {
'x-priority': 'internal',
},
},
required: ['aReq', 'bReq'],
description: 'description',
};
let output = '';
jest.spyOn(logger, 'info').mockImplementation((x) => (output = x));
printHelp('nx g @nrwl/demo:example', schema, {
mode: 'generate',
plugin: '@nrwl/demo',
entity: 'example',
aliases: ['ex'],
});
const flagsFromOutput = output
.match(/--[a|b]\S*/g)
.map((x) => x.replace('--', ''));
expect(flagsFromOutput).toMatchInlineSnapshot(`
Array [
"aReq",
"bReq",
"aImp",
"bImp",
"aNormal",
"bNormal",
"aInt",
"bInt",
"aDep",
"bDep",
]
`);
});
});
+45 -2
View File
@@ -214,8 +214,10 @@ function generateOptionsOutput(schema: Schema): string {
}
>();
let requiredSpaceToRenderAllFlagsAndAliases = 0;
for (const [optionName, optionConfig] of Object.entries(schema.properties)) {
const sorted = Object.entries(schema.properties).sort((a, b) =>
compareByPriority(a, b, schema)
);
for (const [optionName, optionConfig] of sorted) {
const renderedFlagAndAlias =
`--${optionName}` +
(optionConfig.alias ? `, -${optionConfig.alias}` : '');
@@ -336,3 +338,44 @@ function generateLinkOutput({
'Find more information and examples at:'
)} ${chalk.bold(link)}`;
}
/**
* sorts properties in the following order
* - required
* - x-priority: important
* - everything else
* - x-priority: internal
* - deprecated
* if two properties have equal priority, they are sorted by name
*/
function compareByPriority(
a: [string, Schema['properties'][0]],
b: [string, Schema['properties'][0]],
schema: Schema
): number {
function getPriority([name, property]: [
string,
Schema['properties'][0]
]): number {
if (schema.required?.includes(name)) {
return 0;
}
if (property['x-priority'] === 'important') {
return 1;
}
if (property['x-deprecated']) {
return 4;
}
if (property['x-priority'] === 'internal') {
return 3;
}
return 2;
}
const aPriority = getPriority(a);
const bPriority = getPriority(b);
if (aPriority === bPriority) {
return a[0].localeCompare(b[0]);
}
return aPriority - bPriority;
}
@@ -3,7 +3,7 @@ import * as ts from 'typescript';
import * as rollup from 'rollup';
import * as peerDepsExternal from 'rollup-plugin-peer-deps-external';
import { getBabelInputPlugin } from '@rollup/plugin-babel';
import { dirname, join, parse } from 'path';
import { dirname, join, parse, resolve } from 'path';
import { from, Observable, of } from 'rxjs';
import { catchError, concatMap, last, scan, tap } from 'rxjs/operators';
import { eachValueFrom } from '@nrwl/devkit/src/utils/rxjs-for-await';
@@ -15,7 +15,7 @@ import {
computeCompilerOptionsPaths,
DependentBuildableProjectNode,
} from '@nrwl/workspace/src/utilities/buildable-libs-utils';
import resolve from '@rollup/plugin-node-resolve';
import nodeResolve from '@rollup/plugin-node-resolve';
import { AssetGlobPattern, RollupExecutorOptions } from './schema';
import { runRollup } from './lib/run-rollup';
@@ -29,6 +29,11 @@ import { swc } from './lib/swc-plugin';
import { validateTypes } from './lib/validate-types';
import { updatePackageJson } from './lib/update-package-json';
export type RollupExecutorEvent = {
success: boolean;
outfile?: string;
};
// These use require because the ES import isn't correct.
const commonjs = require('@rollup/plugin-commonjs');
const image = require('@rollup/plugin-image');
@@ -77,6 +82,8 @@ export async function* rollupExecutor(
npmDeps
);
const outfile = resolveOutfile(context, options);
if (options.compiler === 'swc') {
try {
await validateTypes({
@@ -92,7 +99,7 @@ export async function* rollupExecutor(
if (options.watch) {
const watcher = rollup.watch(rollupOptions);
return yield* eachValueFrom(
new Observable<{ success: boolean }>((obs) => {
new Observable<RollupExecutorEvent>((obs) => {
watcher.on('event', (data) => {
if (data.code === 'START') {
logger.info(`Bundling ${context.projectName}...`);
@@ -105,7 +112,7 @@ export async function* rollupExecutor(
packageJson
);
logger.info('Bundle complete. Watching for file changes...');
obs.next({ success: true });
obs.next({ success: true, outfile });
} else if (data.code === 'ERROR') {
logger.error(`Error during bundle: ${data.error.message}`);
obs.next({ success: false });
@@ -135,12 +142,12 @@ export async function* rollupExecutor(
})
)
),
scan(
scan<RollupExecutorEvent>(
(acc, result) => {
if (!acc.success) return acc;
return result;
},
{ success: true }
{ success: true, outfile }
),
last(),
tap({
@@ -231,7 +238,7 @@ export function createRollupOptions(
},
},
}),
resolve({
nodeResolve({
preferBuiltins: true,
extensions: fileExtensions,
}),
@@ -341,4 +348,13 @@ function readCompatibleFormats(config: ts.ParsedCommandLine) {
}
}
function resolveOutfile(
context: ExecutorContext,
options: NormalizedRollupExecutorOptions
) {
if (!options.format?.includes('cjs')) return undefined;
const { name } = parse(options.outputFileName ?? options.main);
return resolve(context.root, options.outputPath, `${name}.cjs`);
}
export default rollupExecutor;
+11 -26
View File
@@ -6,11 +6,8 @@ describe('testing utilities', () => {
describe('builderIsWebpackButNotWebpack5', () => {
it('should return false if builder is webpack5', () => {
const sourceCode = stripIndents`
const rootMain = require('../../../.storybook/main');
module.exports = {
...rootMain,
core: { ...rootMain.core, builder: 'webpack5' },
module.exports = {
core: { builder: 'webpack5' },
};
`;
@@ -26,12 +23,9 @@ describe('testing utilities', () => {
it('should return false if builder is @storybook/webpack5', () => {
const sourceCode = stripIndents`
const rootMain = require('../../../.storybook/main');
module.exports = {
...rootMain,
core: { ...rootMain.core, builder: '@storybook/webpack5' },
};
module.exports = {
core: { builder: '@storybook/webpack5' },
};
`;
const source = ts.createSourceFile(
@@ -46,11 +40,8 @@ describe('testing utilities', () => {
it('should return false if builder exists but does not contain webpack', () => {
const sourceCode = stripIndents`
const rootMain = require('../../../.storybook/main');
module.exports = {
...rootMain,
core: { ...rootMain.core, builder: '@storybook/vite-builder' },
module.exports = {
core: { builder: '@storybook/vite-builder' },
};
`;
@@ -66,11 +57,8 @@ describe('testing utilities', () => {
it('should return true if builder is webpack4', () => {
const sourceCode = stripIndents`
const rootMain = require('../../../.storybook/main');
module.exports = {
...rootMain,
core: { ...rootMain.core, builder: 'webpack4' },
module.exports = {
core: { builder: 'webpack4' },
};
`;
@@ -86,11 +74,8 @@ describe('testing utilities', () => {
it('should return true if builder does not exist because default is webpack', () => {
const sourceCode = stripIndents`
const rootMain = require('../../../.storybook/main');
module.exports = {
...rootMain,
};
module.exports = {
};
`;
const source = ts.createSourceFile(
@@ -1,21 +1,17 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`@nrwl/storybook:configuration basic functionalities should generate a webpackFinal into the main.js and reference a potential global webpackFinal definition 1`] = `
"const rootMain = require('../../../.storybook/main');
"
module.exports = {
...rootMain,
core: { ...rootMain.core, builder: 'webpack5' },
core: { builder: 'webpack5' },
stories: [
...rootMain.stories,
'../**/*.stories.mdx',
'../**/*.stories.@(js|jsx|ts|tsx)' ],
addons: [...rootMain.addons
addons: ['@storybook/addon-essentials'
]
@@ -52,7 +48,7 @@ Object {
"inputs": Array [
"default",
"^production",
"{workspaceRoot}/.storybook/**/*",
"!{projectRoot}/.storybook/**/*",
],
},
"e2e": Object {
@@ -100,27 +96,23 @@ Array [
]
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for Storybook configurations with Vite should create correct main.ts and tsconfig.json for NextJS buildable libs 1`] = `
"import { rootMain } from '../../../.storybook/main';
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for Storybook configurations with Vite should create correct main.js and tsconfig.json for NextJS buildable libs 1`] = `
"const { mergeConfig } = require('vite');
const viteTsConfigPaths = require('vite-tsconfig-paths').default;
import type { StorybookConfig, Options } from '@storybook/core-common';
import { mergeConfig } from 'vite';
import viteTsConfigPaths from 'vite-tsconfig-paths';
const config: StorybookConfig = {
...rootMain,
core: { ...rootMain.core, builder: '@storybook/builder-vite' },
module.exports = {
core: { builder: '@storybook/builder-vite' },
stories: [
...rootMain.stories,
'../src/lib/**/*.stories.mdx',
'../src/lib/**/*.stories.@(js|jsx|ts|tsx)'
],
addons: [...(rootMain.addons || [])
addons: ['@storybook/addon-essentials'
],
async viteFinal(config: any) {
async viteFinal(config, { configType }) {
return mergeConfig(config, {
plugins: [
viteTsConfigPaths({
@@ -129,9 +121,7 @@ const config: StorybookConfig = {
],
});
},
} as StorybookConfig;
module.exports = config;
};
@@ -142,7 +132,127 @@ module.exports = config;
"
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for Storybook configurations with Vite should create correct main.ts and tsconfig.json for NextJS buildable libs 2`] = `
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for Storybook configurations with Vite should create correct main.js and tsconfig.json for NextJS buildable libs 2`] = `
"{
\\"extends\\": \\"../tsconfig.json\\",
\\"compilerOptions\\": {
\\"emitDecoratorMetadata\\": true
, \\"outDir\\": \\"\\"
},
\\"files\\": [
\\"../../../node_modules/@nrwl/react/typings/styled-jsx.d.ts\\",
\\"../../../node_modules/@nrwl/react/typings/cssmodule.d.ts\\",
\\"../../../node_modules/@nrwl/react/typings/image.d.ts\\"
],
\\"exclude\\": [\\"../**/*.spec.ts\\" , \\"../**/*.spec.js\\", \\"../**/*.spec.tsx\\", \\"../**/*.spec.jsx\\"],
\\"include\\": [
\\"../src/**/*.stories.ts\\",
\\"../src/**/*.stories.js\\",
\\"../src/**/*.stories.jsx\\",
\\"../src/**/*.stories.tsx\\",
\\"../src/**/*.stories.mdx\\",
\\"*.js\\"]
}
"
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for Storybook configurations with Vite should create correct main.js and tsconfig.json for React apps using the swc compiler 1`] = `
"const { mergeConfig } = require('vite');
const viteTsConfigPaths = require('vite-tsconfig-paths').default;
module.exports = {
core: { builder: '@storybook/builder-vite' },
stories: [
'../src/app/**/*.stories.mdx',
'../src/app/**/*.stories.@(js|jsx|ts|tsx)'
],
addons: ['@storybook/addon-essentials'
, 'storybook-addon-swc'
],
async viteFinal(config, { configType }) {
return mergeConfig(config, {
plugins: [
viteTsConfigPaths({
root: '../../../',
}),
],
});
},
};
// To customize your Vite configuration you can use the viteFinal field.
// Check https://storybook.js.org/docs/react/builders/vite#configuration
// and https://nx.dev/packages/storybook/documents/custom-builder-configs
"
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for Storybook configurations with Vite should create correct main.js and tsconfig.json for React apps using the swc compiler 2`] = `
"{
\\"extends\\": \\"../tsconfig.json\\",
\\"compilerOptions\\": {
\\"emitDecoratorMetadata\\": true
, \\"outDir\\": \\"\\"
},
\\"files\\": [
\\"../../../node_modules/@nrwl/react/typings/styled-jsx.d.ts\\",
\\"../../../node_modules/@nrwl/react/typings/cssmodule.d.ts\\",
\\"../../../node_modules/@nrwl/react/typings/image.d.ts\\"
],
\\"exclude\\": [\\"../**/*.spec.ts\\" , \\"../**/*.spec.js\\", \\"../**/*.spec.tsx\\", \\"../**/*.spec.jsx\\"],
\\"include\\": [
\\"../src/**/*.stories.ts\\",
\\"../src/**/*.stories.js\\",
\\"../src/**/*.stories.jsx\\",
\\"../src/**/*.stories.tsx\\",
\\"../src/**/*.stories.mdx\\",
\\"*.js\\"]
}
"
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for Storybook configurations with Vite should create correct main.js and tsconfig.json for React buildable libs 1`] = `
"const { mergeConfig } = require('vite');
const viteTsConfigPaths = require('vite-tsconfig-paths').default;
module.exports = {
core: { builder: '@storybook/builder-vite' },
stories: [
'../src/lib/**/*.stories.mdx',
'../src/lib/**/*.stories.@(js|jsx|ts|tsx)'
],
addons: ['@storybook/addon-essentials'
],
async viteFinal(config, { configType }) {
return mergeConfig(config, {
plugins: [
viteTsConfigPaths({
root: '../../../',
}),
],
});
},
};
// To customize your Vite configuration you can use the viteFinal field.
// Check https://storybook.js.org/docs/react/builders/vite#configuration
// and https://nx.dev/packages/storybook/documents/custom-builder-configs
"
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for Storybook configurations with Vite should create correct main.js and tsconfig.json for React buildable libs 2`] = `
"{
\\"extends\\": \\"../tsconfig.json\\",
\\"compilerOptions\\": {
@@ -161,29 +271,25 @@ exports[`@nrwl/storybook:configuration for other types of projects - Next.js and
\\"../src/**/*.stories.jsx\\",
\\"../src/**/*.stories.tsx\\",
\\"../src/**/*.stories.mdx\\",
\\"*.ts\\",
\\"*.js\\"]
}
"
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for Storybook configurations with Vite should create correct main.ts and tsconfig.json for NextJS libs 1`] = `
"import { rootMain } from '../../../.storybook/main';
import type { StorybookConfig, Options } from '@storybook/core-common';
"import type { StorybookConfig } from '@storybook/core-common';
import { mergeConfig } from 'vite';
import viteTsConfigPaths from 'vite-tsconfig-paths';
const config: StorybookConfig = {
...rootMain,
core: { ...rootMain.core, builder: '@storybook/builder-vite' },
core: { builder: '@storybook/builder-vite' },
stories: [
...rootMain.stories,
'../src/lib/**/*.stories.mdx',
'../src/lib/**/*.stories.@(js|jsx|ts|tsx)'
],
addons: [...(rootMain.addons || [])
addons: ['@storybook/addon-essentials'
],
@@ -235,22 +341,19 @@ exports[`@nrwl/storybook:configuration for other types of projects - Next.js and
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for Storybook configurations with Vite should create correct main.ts and tsconfig.json for NextJs apps 1`] = `
"import { rootMain } from '../../../.storybook/main';
import type { StorybookConfig, Options } from '@storybook/core-common';
"import type { StorybookConfig } from '@storybook/core-common';
import path from 'path';
import { mergeConfig } from 'vite';
import viteTsConfigPaths from 'vite-tsconfig-paths';
const config: StorybookConfig = {
...rootMain,
core: { ...rootMain.core, builder: '@storybook/builder-vite' },
core: { builder: '@storybook/builder-vite' },
stories: [
...rootMain.stories,
'../components/**/*.stories.mdx',
'../components/**/*.stories.@(js|jsx|ts|tsx)'
],
addons: [...(rootMain.addons || [])
addons: ['@storybook/addon-essentials'
, 'storybook-addon-swc',
{
@@ -309,22 +412,19 @@ exports[`@nrwl/storybook:configuration for other types of projects - Next.js and
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for Storybook configurations with Vite should create correct main.ts and tsconfig.json for React apps 1`] = `
"import { rootMain } from '../../../.storybook/main';
import type { StorybookConfig, Options } from '@storybook/core-common';
"import type { StorybookConfig } from '@storybook/core-common';
import { mergeConfig } from 'vite';
import viteTsConfigPaths from 'vite-tsconfig-paths';
const config: StorybookConfig = {
...rootMain,
core: { ...rootMain.core, builder: '@storybook/builder-vite' },
core: { builder: '@storybook/builder-vite' },
stories: [
...rootMain.stories,
'../src/app/**/*.stories.mdx',
'../src/app/**/*.stories.@(js|jsx|ts|tsx)'
],
addons: [...(rootMain.addons || [])
addons: ['@storybook/addon-essentials'
],
@@ -375,157 +475,20 @@ exports[`@nrwl/storybook:configuration for other types of projects - Next.js and
"
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for Storybook configurations with Vite should create correct main.ts and tsconfig.json for React apps using the swc compiler 1`] = `
"import { rootMain } from '../../../.storybook/main';
import type { StorybookConfig, Options } from '@storybook/core-common';
import { mergeConfig } from 'vite';
import viteTsConfigPaths from 'vite-tsconfig-paths';
const config: StorybookConfig = {
...rootMain,
core: { ...rootMain.core, builder: '@storybook/builder-vite' },
stories: [
...rootMain.stories,
'../src/app/**/*.stories.mdx',
'../src/app/**/*.stories.@(js|jsx|ts|tsx)'
],
addons: [...(rootMain.addons || [])
, 'storybook-addon-swc'
],
async viteFinal(config: any) {
return mergeConfig(config, {
plugins: [
viteTsConfigPaths({
root: '../../../',
}),
],
});
},
} as StorybookConfig;
module.exports = config;
// To customize your Vite configuration you can use the viteFinal field.
// Check https://storybook.js.org/docs/react/builders/vite#configuration
// and https://nx.dev/packages/storybook/documents/custom-builder-configs
"
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for Storybook configurations with Vite should create correct main.ts and tsconfig.json for React apps using the swc compiler 2`] = `
"{
\\"extends\\": \\"../tsconfig.json\\",
\\"compilerOptions\\": {
\\"emitDecoratorMetadata\\": true
, \\"outDir\\": \\"\\"
},
\\"files\\": [
\\"../../../node_modules/@nrwl/react/typings/styled-jsx.d.ts\\",
\\"../../../node_modules/@nrwl/react/typings/cssmodule.d.ts\\",
\\"../../../node_modules/@nrwl/react/typings/image.d.ts\\"
],
\\"exclude\\": [\\"../**/*.spec.ts\\" , \\"../**/*.spec.js\\", \\"../**/*.spec.tsx\\", \\"../**/*.spec.jsx\\"],
\\"include\\": [
\\"../src/**/*.stories.ts\\",
\\"../src/**/*.stories.js\\",
\\"../src/**/*.stories.jsx\\",
\\"../src/**/*.stories.tsx\\",
\\"../src/**/*.stories.mdx\\",
\\"*.ts\\",
\\"*.js\\"]
}
"
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for Storybook configurations with Vite should create correct main.ts and tsconfig.json for React buildable libs 1`] = `
"import { rootMain } from '../../../.storybook/main';
import type { StorybookConfig, Options } from '@storybook/core-common';
import { mergeConfig } from 'vite';
import viteTsConfigPaths from 'vite-tsconfig-paths';
const config: StorybookConfig = {
...rootMain,
core: { ...rootMain.core, builder: '@storybook/builder-vite' },
stories: [
...rootMain.stories,
'../src/lib/**/*.stories.mdx',
'../src/lib/**/*.stories.@(js|jsx|ts|tsx)'
],
addons: [...(rootMain.addons || [])
],
async viteFinal(config: any) {
return mergeConfig(config, {
plugins: [
viteTsConfigPaths({
root: '../../../',
}),
],
});
},
} as StorybookConfig;
module.exports = config;
// To customize your Vite configuration you can use the viteFinal field.
// Check https://storybook.js.org/docs/react/builders/vite#configuration
// and https://nx.dev/packages/storybook/documents/custom-builder-configs
"
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for Storybook configurations with Vite should create correct main.ts and tsconfig.json for React buildable libs 2`] = `
"{
\\"extends\\": \\"../tsconfig.json\\",
\\"compilerOptions\\": {
\\"emitDecoratorMetadata\\": true
, \\"outDir\\": \\"\\"
},
\\"files\\": [
\\"../../../node_modules/@nrwl/react/typings/styled-jsx.d.ts\\",
\\"../../../node_modules/@nrwl/react/typings/cssmodule.d.ts\\",
\\"../../../node_modules/@nrwl/react/typings/image.d.ts\\"
],
\\"exclude\\": [\\"../**/*.spec.ts\\" , \\"../**/*.spec.js\\", \\"../**/*.spec.tsx\\", \\"../**/*.spec.jsx\\"],
\\"include\\": [
\\"../src/**/*.stories.ts\\",
\\"../src/**/*.stories.js\\",
\\"../src/**/*.stories.jsx\\",
\\"../src/**/*.stories.tsx\\",
\\"../src/**/*.stories.mdx\\",
\\"*.ts\\",
\\"*.js\\"]
}
"
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for TypeScript Storybook configurations should create correct main.ts and tsconfig.json for NextJS buildable libs 1`] = `
"import { rootMain } from '../../../.storybook/main';
import type { StorybookConfig, Options } from '@storybook/core-common';
"import type { StorybookConfig } from '@storybook/core-common';
const config: StorybookConfig = {
...rootMain,
core: { ...rootMain.core, builder: 'webpack5' },
core: { builder: 'webpack5' },
stories: [
...rootMain.stories,
'../src/lib/**/*.stories.mdx',
'../src/lib/**/*.stories.@(js|jsx|ts|tsx)'
],
addons: [...(rootMain.addons || []) , '@nrwl/react/plugins/storybook'
addons: ['@storybook/addon-essentials' , '@nrwl/react/plugins/storybook'
]
@@ -568,22 +531,19 @@ exports[`@nrwl/storybook:configuration for other types of projects - Next.js and
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for TypeScript Storybook configurations should create correct main.ts and tsconfig.json for NextJS libs 1`] = `
"import { rootMain } from '../../../.storybook/main';
import type { StorybookConfig, Options } from '@storybook/core-common';
"import type { StorybookConfig } from '@storybook/core-common';
const config: StorybookConfig = {
...rootMain,
core: { ...rootMain.core, builder: 'webpack5' },
core: { builder: 'webpack5' },
stories: [
...rootMain.stories,
'../src/lib/**/*.stories.mdx',
'../src/lib/**/*.stories.@(js|jsx|ts|tsx)'
],
addons: [...(rootMain.addons || []) , '@nrwl/react/plugins/storybook'
addons: ['@storybook/addon-essentials' , '@nrwl/react/plugins/storybook'
]
@@ -626,22 +586,19 @@ exports[`@nrwl/storybook:configuration for other types of projects - Next.js and
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for TypeScript Storybook configurations should create correct main.ts and tsconfig.json for NextJs apps 1`] = `
"import { rootMain } from '../../../.storybook/main';
import type { StorybookConfig, Options } from '@storybook/core-common';
"import type { StorybookConfig } from '@storybook/core-common';
import path from 'path';
const config: StorybookConfig = {
...rootMain,
core: { ...rootMain.core, builder: 'webpack5' },
core: { builder: 'webpack5' },
stories: [
...rootMain.stories,
'../components/**/*.stories.mdx',
'../components/**/*.stories.@(js|jsx|ts|tsx)'
],
addons: [...(rootMain.addons || []) , '@nrwl/react/plugins/storybook'
addons: ['@storybook/addon-essentials' , '@nrwl/react/plugins/storybook'
, 'storybook-addon-swc',
{
@@ -691,22 +648,19 @@ exports[`@nrwl/storybook:configuration for other types of projects - Next.js and
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for TypeScript Storybook configurations should create correct main.ts and tsconfig.json for React apps 1`] = `
"import { rootMain } from '../../../.storybook/main';
import type { StorybookConfig, Options } from '@storybook/core-common';
"import type { StorybookConfig } from '@storybook/core-common';
const config: StorybookConfig = {
...rootMain,
core: { ...rootMain.core, builder: 'webpack5' },
core: { builder: 'webpack5' },
stories: [
...rootMain.stories,
'../src/app/**/*.stories.mdx',
'../src/app/**/*.stories.@(js|jsx|ts|tsx)'
],
addons: [...(rootMain.addons || []) , '@nrwl/react/plugins/storybook'
addons: ['@storybook/addon-essentials' , '@nrwl/react/plugins/storybook'
]
@@ -804,22 +758,19 @@ exports[`@nrwl/storybook:configuration for other types of projects - Next.js and
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for TypeScript Storybook configurations should create correct main.ts and tsconfig.json for React buildable libs 1`] = `
"import { rootMain } from '../../../.storybook/main';
import type { StorybookConfig, Options } from '@storybook/core-common';
"import type { StorybookConfig } from '@storybook/core-common';
const config: StorybookConfig = {
...rootMain,
core: { ...rootMain.core, builder: 'webpack5' },
core: { builder: 'webpack5' },
stories: [
...rootMain.stories,
'../src/lib/**/*.stories.mdx',
'../src/lib/**/*.stories.@(js|jsx|ts|tsx)'
],
addons: [...(rootMain.addons || []) , '@nrwl/react/plugins/storybook'
addons: ['@storybook/addon-essentials' , '@nrwl/react/plugins/storybook'
]
@@ -862,22 +813,18 @@ exports[`@nrwl/storybook:configuration for other types of projects - Next.js and
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for js Storybook configurations should create correct main.js and tsconfig.json for NextJS buildable libs 1`] = `
"const rootMain = require('../../../.storybook/main');
"
module.exports = {
...rootMain,
core: { ...rootMain.core, builder: 'webpack5' },
core: { builder: 'webpack5' },
stories: [
...rootMain.stories,
'../src/lib/**/*.stories.mdx',
'../src/lib/**/*.stories.@(js|jsx|ts|tsx)'
],
addons: [...rootMain.addons , '@nrwl/react/plugins/storybook'
addons: ['@storybook/addon-essentials' , '@nrwl/react/plugins/storybook'
]
@@ -917,22 +864,18 @@ exports[`@nrwl/storybook:configuration for other types of projects - Next.js and
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for js Storybook configurations should create correct main.js and tsconfig.json for NextJS libs 1`] = `
"const rootMain = require('../../../.storybook/main');
"
module.exports = {
...rootMain,
core: { ...rootMain.core, builder: 'webpack5' },
core: { builder: 'webpack5' },
stories: [
...rootMain.stories,
'../src/lib/**/*.stories.mdx',
'../src/lib/**/*.stories.@(js|jsx|ts|tsx)'
],
addons: [...rootMain.addons , '@nrwl/react/plugins/storybook'
addons: ['@storybook/addon-essentials' , '@nrwl/react/plugins/storybook'
]
@@ -972,22 +915,18 @@ exports[`@nrwl/storybook:configuration for other types of projects - Next.js and
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for js Storybook configurations should create correct main.js and tsconfig.json for NextJs apps 1`] = `
"const rootMain = require('../../../.storybook/main');
"
const path = require('path');
module.exports = {
...rootMain,
core: { ...rootMain.core, builder: 'webpack5' },
core: { builder: 'webpack5' },
stories: [
...rootMain.stories,
'../components/**/*.stories.mdx',
'../components/**/*.stories.@(js|jsx|ts|tsx)'
],
addons: [...rootMain.addons , '@nrwl/react/plugins/storybook'
addons: ['@storybook/addon-essentials' , '@nrwl/react/plugins/storybook'
, 'storybook-addon-swc',
{
@@ -1034,22 +973,18 @@ exports[`@nrwl/storybook:configuration for other types of projects - Next.js and
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for js Storybook configurations should create correct main.js and tsconfig.json for React apps 1`] = `
"const rootMain = require('../../../.storybook/main');
"
module.exports = {
...rootMain,
core: { ...rootMain.core, builder: 'webpack5' },
core: { builder: 'webpack5' },
stories: [
...rootMain.stories,
'../src/app/**/*.stories.mdx',
'../src/app/**/*.stories.@(js|jsx|ts|tsx)'
],
addons: [...rootMain.addons , '@nrwl/react/plugins/storybook'
addons: ['@storybook/addon-essentials' , '@nrwl/react/plugins/storybook'
]
@@ -1089,22 +1024,18 @@ exports[`@nrwl/storybook:configuration for other types of projects - Next.js and
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for js Storybook configurations should create correct main.js and tsconfig.json for React apps using the swc compiler 1`] = `
"const rootMain = require('../../../.storybook/main');
"
module.exports = {
...rootMain,
core: { ...rootMain.core, builder: 'webpack5' },
core: { builder: 'webpack5' },
stories: [
...rootMain.stories,
'../src/app/**/*.stories.mdx',
'../src/app/**/*.stories.@(js|jsx|ts|tsx)'
],
addons: [...rootMain.addons , '@nrwl/react/plugins/storybook'
addons: ['@storybook/addon-essentials' , '@nrwl/react/plugins/storybook'
, 'storybook-addon-swc'
]
@@ -1144,22 +1075,18 @@ exports[`@nrwl/storybook:configuration for other types of projects - Next.js and
`;
exports[`@nrwl/storybook:configuration for other types of projects - Next.js and the swc compiler for js Storybook configurations should create correct main.js and tsconfig.json for React buildable libs 1`] = `
"const rootMain = require('../../../.storybook/main');
"
module.exports = {
...rootMain,
core: { ...rootMain.core, builder: 'webpack5' },
core: { builder: 'webpack5' },
stories: [
...rootMain.stories,
'../src/lib/**/*.stories.mdx',
'../src/lib/**/*.stories.@(js|jsx|ts|tsx)'
],
addons: [...rootMain.addons , '@nrwl/react/plugins/storybook'
addons: ['@storybook/addon-essentials' , '@nrwl/react/plugins/storybook'
]
@@ -16,7 +16,7 @@ import configurationGenerator from './configuration';
import * as workspaceConfiguration from './test-configs/workspace-conifiguration.json';
describe('@nrwl/storybook:configuration', () => {
xdescribe('basic functionalities', () => {
describe('basic functionalities', () => {
let tree: Tree;
beforeEach(async () => {
@@ -99,31 +99,6 @@ describe('@nrwl/storybook:configuration', () => {
).toMatchSnapshot();
});
it('should not update root files after generating them once', async () => {
await configurationGenerator(tree, {
name: 'test-ui-lib',
uiFramework: '@storybook/angular',
});
const newContents = `module.exports = {
stories: [],
addons: ['@storybook/addon-essentials', 'new-addon'],
};
`;
// Setup a new lib
await libraryGenerator(tree, {
name: 'test-ui-lib-2',
});
tree.write('.storybook/main.js', newContents);
await configurationGenerator(tree, {
name: 'test-ui-lib-2',
uiFramework: '@storybook/angular',
});
expect(tree.read('.storybook/main.js', 'utf-8')).toEqual(newContents);
});
it('should update workspace file for react libs', async () => {
await configurationGenerator(tree, {
name: 'test-ui-lib',
@@ -317,14 +292,12 @@ describe('@nrwl/storybook:configuration', () => {
uiFramework: '@storybook/angular',
tsConfiguration: true,
});
expect(tree.exists('libs/test-ui-lib-2/.storybook/main.ts')).toBeTruthy();
expect(tree.exists('libs/test-ui-lib/.storybook/main.ts')).toBeTruthy();
expect(
tree.exists('libs/test-ui-lib-2/.storybook/preview.ts')
tree.exists('libs/test-ui-lib/.storybook/preview.ts')
).toBeTruthy();
expect(tree.exists('libs/test-ui-lib-2/.storybook/main.js')).toBeFalsy();
expect(
tree.exists('libs/test-ui-lib-2/.storybook/preview.js')
).toBeFalsy();
expect(tree.exists('libs/test-ui-lib/.storybook/main.js')).toBeFalsy();
expect(tree.exists('libs/test-ui-lib/.storybook/preview.js')).toBeFalsy();
});
it('should add test-storybook target', async () => {
@@ -350,7 +323,7 @@ describe('@nrwl/storybook:configuration', () => {
});
describe('for other types of projects - Next.js and the swc compiler', () => {
xdescribe('for js Storybook configurations', () => {
describe('for js Storybook configurations', () => {
let tree: Tree;
beforeAll(async () => {
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
@@ -449,110 +422,6 @@ describe('@nrwl/storybook:configuration', () => {
});
describe('for TypeScript Storybook configurations', () => {
let tree: Tree;
beforeAll(async () => {
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
writeConfig(tree, workspaceConfiguration);
writeJson(tree, 'apps/nxapp/tsconfig.json', {});
writeJson(tree, 'apps/reapp/tsconfig.json', {});
writeJson(tree, 'libs/nxlib/tsconfig.json', {});
writeJson(tree, 'libs/nxlib-buildable/tsconfig.json', {});
writeJson(tree, 'libs/relib-buildable/tsconfig.json', {});
writeJson(tree, 'apps/reapp-swc/tsconfig.json', {});
// await configurationGenerator(tree, {
// name: 'nxapp',
// uiFramework: '@storybook/react',
// tsConfiguration: true,
// });
// await configurationGenerator(tree, {
// name: 'reapp',
// uiFramework: '@storybook/react',
// tsConfiguration: true,
// });
// await configurationGenerator(tree, {
// name: 'nxlib',
// uiFramework: '@storybook/react',
// tsConfiguration: true,
// });
// await configurationGenerator(tree, {
// name: 'nxlib-buildable',
// uiFramework: '@storybook/react',
// tsConfiguration: true,
// });
// await configurationGenerator(tree, {
// name: 'relib-buildable',
// uiFramework: '@storybook/react',
// tsConfiguration: true,
// });
await configurationGenerator(tree, {
name: 'reapp-swc',
uiFramework: '@storybook/react',
tsConfiguration: true,
});
});
it(`should create correct main.ts and tsconfig.json for NextJs apps`, async () => {
expect(
tree.read('apps/nxapp/.storybook/main.ts', 'utf-8')
).toMatchSnapshot();
expect(
tree.read('apps/nxapp/.storybook/tsconfig.json', 'utf-8')
).toMatchSnapshot();
});
it(`should create correct main.ts and tsconfig.json for React apps`, async () => {
expect(
tree.read('apps/reapp/.storybook/main.ts', 'utf-8')
).toMatchSnapshot();
expect(
tree.read('apps/reapp/.storybook/tsconfig.json', 'utf-8')
).toMatchSnapshot();
});
it(`should create correct main.ts and tsconfig.json for NextJS libs`, async () => {
expect(
tree.read('libs/nxlib/.storybook/main.ts', 'utf-8')
).toMatchSnapshot();
expect(
tree.read('libs/nxlib/.storybook/tsconfig.json', 'utf-8')
).toMatchSnapshot();
});
it(`should create correct main.ts and tsconfig.json for NextJS buildable libs`, async () => {
expect(
tree.read('libs/nxlib-buildable/.storybook/main.ts', 'utf-8')
).toMatchSnapshot();
expect(
tree.read('libs/nxlib-buildable/.storybook/tsconfig.json', 'utf-8')
).toMatchSnapshot();
});
it(`should create correct main.ts and tsconfig.json for React buildable libs`, async () => {
expect(
tree.read('libs/relib-buildable/.storybook/main.ts', 'utf-8')
).toMatchSnapshot();
expect(
tree.read('libs/relib-buildable/.storybook/tsconfig.json', 'utf-8')
).toMatchSnapshot();
});
it.only(`should create correct main.ts and tsconfig.json for React apps using the swc compiler`, async () => {
expect(
tree.read('apps/reapp-swc/.storybook/main.ts', 'utf-8')
).toMatchSnapshot();
expect(
tree.read('apps/reapp-swc/.storybook/tsconfig.json', 'utf-8')
).toMatchSnapshot();
});
});
describe('for Storybook configurations with Vite', () => {
let tree: Tree;
beforeAll(async () => {
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
@@ -566,33 +435,32 @@ describe('@nrwl/storybook:configuration', () => {
await configurationGenerator(tree, {
name: 'nxapp',
uiFramework: '@storybook/react',
bundler: 'vite',
tsConfiguration: true,
});
await configurationGenerator(tree, {
name: 'reapp',
uiFramework: '@storybook/react',
bundler: 'vite',
tsConfiguration: true,
});
await configurationGenerator(tree, {
name: 'nxlib',
uiFramework: '@storybook/react',
bundler: 'vite',
tsConfiguration: true,
});
await configurationGenerator(tree, {
name: 'nxlib-buildable',
uiFramework: '@storybook/react',
bundler: 'vite',
tsConfiguration: true,
});
await configurationGenerator(tree, {
name: 'relib-buildable',
uiFramework: '@storybook/react',
bundler: 'vite',
tsConfiguration: true,
});
await configurationGenerator(tree, {
name: 'reapp-swc',
uiFramework: '@storybook/react',
bundler: 'vite',
tsConfiguration: true,
});
});
@@ -656,6 +524,113 @@ describe('@nrwl/storybook:configuration', () => {
).toMatchSnapshot();
});
});
describe('for Storybook configurations with Vite', () => {
let tree: Tree;
beforeAll(async () => {
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
writeConfig(tree, workspaceConfiguration);
writeJson(tree, 'apps/nxapp/tsconfig.json', {});
writeJson(tree, 'apps/reapp/tsconfig.json', {});
writeJson(tree, 'libs/nxlib/tsconfig.json', {});
writeJson(tree, 'libs/nxlib-buildable/tsconfig.json', {});
writeJson(tree, 'libs/relib-buildable/tsconfig.json', {});
writeJson(tree, 'apps/reapp-swc/tsconfig.json', {});
await configurationGenerator(tree, {
name: 'nxapp',
uiFramework: '@storybook/react',
bundler: 'vite',
tsConfiguration: true,
});
await configurationGenerator(tree, {
name: 'reapp',
uiFramework: '@storybook/react',
bundler: 'vite',
tsConfiguration: true,
});
await configurationGenerator(tree, {
name: 'nxlib',
uiFramework: '@storybook/react',
bundler: 'vite',
tsConfiguration: true,
});
await configurationGenerator(tree, {
name: 'nxlib-buildable',
uiFramework: '@storybook/react',
bundler: 'vite',
});
await configurationGenerator(tree, {
name: 'relib-buildable',
uiFramework: '@storybook/react',
bundler: 'vite',
});
await configurationGenerator(tree, {
name: 'reapp-swc',
uiFramework: '@storybook/react',
bundler: 'vite',
});
});
it(`should create correct main.ts and tsconfig.json for NextJs apps`, async () => {
expect(
tree.read('apps/nxapp/.storybook/main.ts', 'utf-8')
).toMatchSnapshot();
expect(
tree.read('apps/nxapp/.storybook/tsconfig.json', 'utf-8')
).toMatchSnapshot();
});
it(`should create correct main.ts and tsconfig.json for React apps`, async () => {
expect(
tree.read('apps/reapp/.storybook/main.ts', 'utf-8')
).toMatchSnapshot();
expect(
tree.read('apps/reapp/.storybook/tsconfig.json', 'utf-8')
).toMatchSnapshot();
});
it(`should create correct main.ts and tsconfig.json for NextJS libs`, async () => {
expect(
tree.read('libs/nxlib/.storybook/main.ts', 'utf-8')
).toMatchSnapshot();
expect(
tree.read('libs/nxlib/.storybook/tsconfig.json', 'utf-8')
).toMatchSnapshot();
});
it(`should create correct main.js and tsconfig.json for NextJS buildable libs`, async () => {
expect(
tree.read('libs/nxlib-buildable/.storybook/main.js', 'utf-8')
).toMatchSnapshot();
expect(
tree.read('libs/nxlib-buildable/.storybook/tsconfig.json', 'utf-8')
).toMatchSnapshot();
});
it(`should create correct main.js and tsconfig.json for React buildable libs`, async () => {
expect(
tree.read('libs/relib-buildable/.storybook/main.js', 'utf-8')
).toMatchSnapshot();
expect(
tree.read('libs/relib-buildable/.storybook/tsconfig.json', 'utf-8')
).toMatchSnapshot();
});
it(`should create correct main.js and tsconfig.json for React apps using the swc compiler`, async () => {
expect(
tree.read('apps/reapp-swc/.storybook/main.js', 'utf-8')
).toMatchSnapshot();
expect(
tree.read('apps/reapp-swc/.storybook/tsconfig.json', 'utf-8')
).toMatchSnapshot();
});
});
});
});
@@ -82,7 +82,7 @@ export default async function (tree: Tree) {
logger.info(
`
Read more about our effort to deprecate the root .storybook folder here:
https://nx.dev/packages/storybook/configuring-storybook
https://nx.dev/packages/storybook/documents/configuring-storybook
`
);
@@ -16,8 +16,8 @@ import { join } from 'path';
plugins: [
dts({
entryRoot: 'src',
tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'),
// Faster builds by skipping tests. Set this to false to enable type checking.
skipDiagnostics: true,
}),
react(),
@@ -74,8 +74,8 @@ import { join } from 'path';
plugins: [
dts({
entryRoot: 'src',
tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'),
// Faster builds by skipping tests. Set this to false to enable type checking.
skipDiagnostics: true,
}),
react(),
@@ -197,8 +197,8 @@ import { defineConfig } from 'vite';
}),
],
dts({
entryRoot: 'src',
tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'),
// Faster builds by skipping tests. Set this to false to enable type checking.
skipDiagnostics: true,
}),
],
@@ -29,8 +29,8 @@ import { join } from 'path';
}
},plugins: [
dts({
entryRoot: 'src',
tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'),
// Faster builds by skipping tests. Set this to false to enable type checking.
skipDiagnostics: true,
}),
react(),
@@ -82,14 +82,13 @@ import { defineConfig } from 'vite';
}),
],
dts({
entryRoot: 'src',
tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'),
// Faster builds by skipping tests. Set this to false to enable type checking.
skipDiagnostics: true,
}),
],
test: {
...{
globals: true,
cache: {
dir: '../../node_modules/.vitest',
@@ -97,8 +96,6 @@ import { defineConfig } from 'vite';
environment: 'jsdom',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
},
...{\\"globals\\":true,\\"cache\\":{\\"dir\\":\\"../node_modules/.vitest\\"},\\"environment\\":\\"jsdom\\",\\"include\\":[\\"src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}\\"]}
},
});
"
@@ -137,14 +134,13 @@ import { defineConfig } from 'vite';
}),
],
dts({
entryRoot: 'src',
tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'),
// Faster builds by skipping tests. Set this to false to enable type checking.
skipDiagnostics: true,
}),
],
test: {
...{
globals: true,
cache: {
dir: '../../node_modules/.vitest',
@@ -152,8 +148,6 @@ import { defineConfig } from 'vite';
environment: 'jsdom',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
},
...{\\"globals\\":true,\\"cache\\":{\\"dir\\":\\"../node_modules/.vitest\\"},\\"environment\\":\\"jsdom\\",\\"include\\":[\\"src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}\\"]}
},
});
"
@@ -199,8 +193,8 @@ import { defineConfig } from 'vite';
}),
],
dts({
entryRoot: 'src',
tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'),
// Faster builds by skipping tests. Set this to false to enable type checking.
skipDiagnostics: true,
}),
],
@@ -247,14 +241,13 @@ import { defineConfig } from 'vite';
}),
],
dts({
entryRoot: 'src',
tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'),
// Faster builds by skipping tests. Set this to false to enable type checking.
skipDiagnostics: true,
}),
],
test: {
...{
globals: true,
cache: {
dir: '../../node_modules/.vitest',
@@ -262,8 +255,6 @@ import { defineConfig } from 'vite';
environment: 'jsdom',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
},
...{\\"globals\\":true,\\"cache\\":{\\"dir\\":\\"../node_modules/.vitest\\"},\\"environment\\":\\"jsdom\\",\\"include\\":[\\"src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}\\"]}
},
build: {
...{
@@ -279,18 +270,19 @@ import { defineConfig } from 'vite';
exports[`ensureViteConfigIsCorrect should not do anything if cannot understand syntax of vite config 1`] = `"console.log('Unknown syntax')"`;
exports[`ensureViteConfigIsCorrect should not do anything if project has everything setup already 1`] = `
"import dts from 'vite-plugin-dts';
import { join } from 'path';
import { defineConfig } from 'vite';
"
/// <reference types=\\"vitest\\" />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import viteTsConfigPaths from 'vite-tsconfig-paths';
import dts from 'vite-plugin-dts';
import { join } from 'path';
export default defineConfig({
plugins: [
...[
dts({
entryRoot: 'src',
tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'),
// Faster builds by skipping tests. Set this to false to enable type checking.
skipDiagnostics: true,
}),
react(),
@@ -298,17 +290,10 @@ import { defineConfig } from 'vite';
root: '../../../',
}),
],
dts({
tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'),
// Faster builds by skipping tests. Set this to false to enable type checking.
skipDiagnostics: true,
}),
],
// Configuration for building your library.
// See: https://vitejs.dev/guide/build.html#library-mode
build: {
...{
lib: {
// Could also be a dictionary or array of multiple entry points.
entry: 'src/index.ts',
@@ -323,11 +308,8 @@ import { defineConfig } from 'vite';
external: ['react', 'react-dom', 'react/jsx-runtime'],
},
},
...{\\"lib\\":{\\"entry\\":\\"src/index.ts\\",\\"name\\":\\"my-app\\",\\"fileName\\":\\"index\\",\\"formats\\":[\\"es\\",\\"cjs\\"]},\\"rollupOptions\\":{\\"external\\":[\\"'react', 'react-dom', 'react/jsx-runtime'\\"]}}
},
test: {
...{
globals: true,
cache: {
dir: '../../../node_modules/.vitest',
@@ -335,8 +317,6 @@ import { defineConfig } from 'vite';
environment: 'jsdom',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
},
...{\\"globals\\":true,\\"cache\\":{\\"dir\\":\\"../node_modules/.vitest\\"},\\"environment\\":\\"jsdom\\",\\"include\\":[\\"src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}\\"]}
},
});
"
`;
@@ -357,8 +337,8 @@ import { defineConfig } from 'vite';
}),
],
dts({
entryRoot: 'src',
tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'),
// Faster builds by skipping tests. Set this to false to enable type checking.
skipDiagnostics: true,
}),
],
+1 -1
View File
@@ -491,8 +491,8 @@ export function createOrEditViteConfig(
? ''
: options.includeLib
? `dts({
entryRoot: 'src',
tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'),
// Faster builds by skipping tests. Set this to false to enable type checking.
skipDiagnostics: true,
}),`
: '';
@@ -153,12 +153,14 @@ export const hasEverything = `
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import viteTsConfigPaths from 'vite-tsconfig-paths';
import dts from 'vite-plugin-dts';
import { join } from 'path';
export default defineConfig({
plugins: [
dts({
entryRoot: 'src',
tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'),
// Faster builds by skipping tests. Set this to false to enable type checking.
skipDiagnostics: true,
}),
react(),
@@ -245,8 +247,8 @@ export const testOptionObject = {
};
export const dtsPlugin = `dts({
entryRoot: 'src',
tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'),
// Faster builds by skipping tests. Set this to false to enable type checking.
skipDiagnostics: true,
}),`;
export const dtsImportLine = `import dts from 'vite-plugin-dts';\nimport { join } from 'path';`;
@@ -39,6 +39,7 @@ describe('ensureViteConfigIsCorrect', () => {
pluginOption,
testOption,
testOptionObject,
'',
{ build: false, test: true, serve: false }
);
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
@@ -63,6 +64,7 @@ describe('ensureViteConfigIsCorrect', () => {
pluginOption,
testOption,
testOptionObject,
'',
{ build: false, test: true, serve: false }
);
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
@@ -87,6 +89,7 @@ describe('ensureViteConfigIsCorrect', () => {
pluginOption,
testOption,
testOptionObject,
'',
{ build: false, test: false, serve: false }
);
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
@@ -111,6 +114,7 @@ describe('ensureViteConfigIsCorrect', () => {
pluginOption,
testOption,
testOptionObject,
'',
{ build: false, test: false, serve: false }
);
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
@@ -135,6 +139,7 @@ describe('ensureViteConfigIsCorrect', () => {
pluginOption,
testOption,
testOptionObject,
'',
{ build: false, test: false, serve: false }
);
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
@@ -159,6 +164,7 @@ describe('ensureViteConfigIsCorrect', () => {
pluginOption,
testOption,
testOptionObject,
'',
{ build: false, test: false, serve: false }
);
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
@@ -177,6 +183,7 @@ describe('ensureViteConfigIsCorrect', () => {
pluginOption,
testOption,
testOptionObject,
'',
{ build: true, test: true, serve: true }
);
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
@@ -195,6 +202,7 @@ describe('ensureViteConfigIsCorrect', () => {
pluginOption,
testOption,
testOptionObject,
'',
{ build: false, test: true, serve: true }
);
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
@@ -213,6 +221,7 @@ describe('ensureViteConfigIsCorrect', () => {
pluginOption,
testOption,
testOptionObject,
'',
{ build: false, test: false, serve: true }
);
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
-1
View File
@@ -42,7 +42,6 @@
"dotenv": "~10.0.0",
"file-loader": "^6.2.0",
"fork-ts-checker-webpack-plugin": "7.2.13",
"fs-extra": "^11.1.0",
"ignore": "^5.0.4",
"less": "3.12.2",
"less-loader": "^11.1.0",
@@ -2,7 +2,7 @@ import { ExecutorContext, logger } from '@nrwl/devkit';
import type { Configuration as WebpackConfiguration } from 'webpack';
import type { Configuration as WebpackDevServerConfiguration } from 'webpack-dev-server';
import * as path from 'path';
import { readFileSync } from 'fs-extra';
import { readFileSync } from 'fs';
import { getWebpackConfig } from '../../webpack/lib/get-webpack-config';
import { WebDevServerOptions } from '../schema';
+2 -2
View File
@@ -1,5 +1,5 @@
import * as path from 'path';
import { existsSync, removeSync } from 'fs-extra';
import { existsSync, rmSync } from 'fs';
import { directoryExists } from 'nx/src/utils/fileutils';
export function findUp(
@@ -63,5 +63,5 @@ export function deleteOutputDir(root: string, outputPath: string) {
throw new Error('Output path MUST not be project root directory!');
}
removeSync(resolvedOutputPath);
rmSync(resolvedOutputPath, { recursive: true, force: true });
}
@@ -32,8 +32,8 @@ variables:
extends: .base-pipeline
script:
- <%= packageManagerPrefix %> nx-cloud start-ci-run --stop-agents-after="build"
- <%= packageManagerPrefix %> nx-cloud record -- yarn nx format:check --base=$NX_BASE --head=$NX_HEAD
- <%= packageManagerPrefix %> nx affected --base=$NX_BASE --head=$NX_HEAD --target=lint --parallel=3 & yarn nx affected --base=$NX_BASE --head=$NX_HEAD --target=test --parallel=3 --ci --code-coverage & yarn nx affected --base=$NX_BASE --head=$NX_HEAD --target=e2e --parallel=3 --ci --code-coverage & yarn nx affected --base=$NX_BASE --head=$NX_HEAD --target=build --parallel=3
- <%= packageManagerPrefix %> nx-cloud record -- <%= packageManagerPrefix %> nx format:check --base=$NX_BASE --head=$NX_HEAD
- <%= packageManagerPrefix %> nx affected --base=$NX_BASE --head=$NX_HEAD --target=lint --parallel=3 & <%= packageManagerPrefix %> nx affected --base=$NX_BASE --head=$NX_HEAD --target=test --parallel=3 --ci --code-coverage & <%= packageManagerPrefix %> nx affected --base=$NX_BASE --head=$NX_HEAD --target=e2e --parallel=3 --ci --code-coverage & <%= packageManagerPrefix %> nx affected --base=$NX_BASE --head=$NX_HEAD --target=build --parallel=3
# Create as many agents as you want
nx-dte-agent1:
@@ -1,13 +1,12 @@
import { getProjects, Tree } from '@nrwl/devkit';
import {
addProjectConfiguration,
ProjectConfiguration,
readJson,
readProjectConfiguration,
Tree,
} from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import type { NormalizedSchema } from '../schema';
import { moveProjectConfiguration } from './move-project-configuration';
import { createProjectConfigurationInNewDestination } from './create-project-configuration-in-new-destination';
describe('moveProjectConfiguration', () => {
let tree: Tree;
@@ -156,11 +155,8 @@ describe('moveProjectConfiguration', () => {
it('should rename the project', async () => {
setupWorkspace();
moveProjectConfiguration(tree, schema, projectConfig);
createProjectConfigurationInNewDestination(tree, schema, projectConfig);
expect(() => {
readProjectConfiguration(tree, 'my-source');
}).toThrow();
expect(
readProjectConfiguration(tree, 'subfolder-my-destination')
).toBeDefined();
@@ -169,7 +165,7 @@ describe('moveProjectConfiguration', () => {
it('should update paths in only the intended project', async () => {
setupWorkspace();
moveProjectConfiguration(tree, schema, projectConfig);
createProjectConfigurationInNewDestination(tree, schema, projectConfig);
const actualProject = readProjectConfiguration(
tree,
@@ -186,7 +182,7 @@ describe('moveProjectConfiguration', () => {
it('should update tags and implicitDependencies', () => {
setupWorkspace();
moveProjectConfiguration(tree, schema, projectConfig);
createProjectConfigurationInNewDestination(tree, schema, projectConfig);
const actualProject = readProjectConfiguration(
tree,
@@ -194,8 +190,6 @@ describe('moveProjectConfiguration', () => {
);
expect(actualProject.tags).toEqual(['type:ui']);
expect(actualProject.implicitDependencies).toEqual(['my-other-lib']);
const projects = Object.fromEntries(getProjects(tree));
expect(projects['my-source']).not.toBeDefined();
});
it('should support moving a standalone project', () => {
@@ -222,11 +216,8 @@ describe('moveProjectConfiguration', () => {
updateImportPath: true,
};
moveProjectConfiguration(tree, moveSchema, projectConfig);
createProjectConfigurationInNewDestination(tree, moveSchema, projectConfig);
expect(() => {
readProjectConfiguration(tree, projectName);
}).toThrow();
expect(readProjectConfiguration(tree, newProjectName)).toBeDefined();
});
});
@@ -1,12 +1,11 @@
import {
addProjectConfiguration,
ProjectConfiguration,
removeProjectConfiguration,
Tree,
} from '@nrwl/devkit';
import { NormalizedSchema } from '../schema';
export function moveProjectConfiguration(
export function createProjectConfigurationInNewDestination(
tree: Tree,
schema: NormalizedSchema,
projectConfig: ProjectConfiguration
@@ -15,18 +14,14 @@ export function moveProjectConfiguration(
projectConfig.name = schema.newProjectName;
}
// replace old root path with new one
const projectString = JSON.stringify(projectConfig);
const newProjectString = projectString.replace(
new RegExp(projectConfig.root, 'g'),
schema.relativeToRootDestination
);
// rename
const newProject: ProjectConfiguration = JSON.parse(newProjectString);
// Delete the original project
removeProjectConfiguration(tree, schema.projectName);
// Create a new project with the root replaced
addProjectConfiguration(tree, schema.newProjectName, newProject);
}
@@ -4,9 +4,9 @@ import {
Tree,
} from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { moveProject } from '@nrwl/workspace/src/generators/move/lib/move-project';
import { libraryGenerator } from '../../library/library';
import { NormalizedSchema } from '../schema';
import { moveProjectFiles } from './move-project-files';
describe('moveProject', () => {
let tree: Tree;
@@ -28,7 +28,7 @@ describe('moveProject', () => {
relativeToRootDestination: 'libs/my-destination',
};
moveProject(tree, schema, projectConfig);
moveProjectFiles(tree, schema, projectConfig);
const destinationChildren = tree.children('libs/my-destination');
expect(destinationChildren.length).toBeGreaterThan(0);
@@ -7,7 +7,7 @@ import { NormalizedSchema } from '../schema';
*
* @param schema The options provided to the schematic
*/
export function moveProject(
export function moveProjectFiles(
tree: Tree,
schema: NormalizedSchema,
project: ProjectConfiguration
@@ -2,12 +2,12 @@ import {
convertNxGenerator,
formatFiles,
readProjectConfiguration,
removeProjectConfiguration,
Tree,
} from '@nrwl/devkit';
import { checkDestination } from './lib/check-destination';
import { moveProject } from './lib/move-project';
import { moveProjectConfiguration } from './lib/move-project-configuration';
import { createProjectConfigurationInNewDestination } from './lib/create-project-configuration-in-new-destination';
import { moveProjectFiles } from './lib/move-project-files';
import { normalizeSchema } from './lib/normalize-schema';
import { updateBuildTargets } from './lib/update-build-targets';
import { updateCypressConfig } from './lib/update-cypress-config';
@@ -27,8 +27,9 @@ export async function moveGenerator(tree: Tree, rawSchema: Schema) {
checkDestination(tree, rawSchema, projectConfig);
const schema = normalizeSchema(tree, rawSchema, projectConfig);
moveProjectConfiguration(tree, schema, projectConfig);
moveProject(tree, schema, projectConfig); // we MUST move the project first, if we don't we get a "This should never happen" error 🤦‍♀️
removeProjectConfiguration(tree, schema.projectName);
moveProjectFiles(tree, schema, projectConfig);
createProjectConfigurationInNewDestination(tree, schema, projectConfig);
updateImports(tree, schema, projectConfig);
updateProjectRootFiles(tree, schema, projectConfig);
updateCypressConfig(tree, schema, projectConfig);
@@ -6,10 +6,7 @@ Object {
"@nrwl/angular": "0.0.1",
},
"devDependencies": Object {
"@angular-devkit/core": "~15.1.0",
"@angular-devkit/schematics": "~15.1.0",
"@nrwl/workspace": "0.0.1",
"@schematics/angular": "~15.1.0",
"nx": "0.0.1",
"prettier": "^2.6.2",
"typescript": "~4.8.2",
@@ -93,14 +93,7 @@ function getPresetDependencies(preset: string, version?: string) {
case Preset.AngularMonorepo:
case Preset.AngularStandalone:
return {
dependencies: { '@nrwl/angular': nxVersion },
dev: {
'@angular-devkit/core': angularCliVersion,
'@angular-devkit/schematics': angularCliVersion,
'@schematics/angular': angularCliVersion,
},
};
return { dependencies: { '@nrwl/angular': nxVersion }, dev: {} };
case Preset.Express:
return { dependencies: {}, dev: { '@nrwl/express': nxVersion } };
+8 -14
View File
@@ -5,28 +5,18 @@
* Use of this source code is governed by an MIT- style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {
apply,
chain,
import type {
DirEntry,
forEach,
mergeWith,
noop,
Rule,
SchematicContext,
Source,
Tree,
} from '@angular-devkit/schematics';
import * as ts from 'typescript';
import {
parseJson,
ProjectConfiguration,
serializeJson,
FileData,
} from '@nrwl/devkit';
import { parseJson, serializeJson } from '@nrwl/devkit';
import { getWorkspacePath } from './cli-config-utils';
import { extname, join, normalize, Path } from '@angular-devkit/core';
import type { NxJsonConfiguration, ProjectsConfigurations } from '@nrwl/devkit';
import type { Path } from '@angular-devkit/core';
import type { NxJsonConfiguration } from '@nrwl/devkit';
import { addInstallTask } from './rules/add-install-task';
import { findNodes } from 'nx/src/utils/typescript';
import { getSourceNodes } from '../utilities/typescript/get-source-nodes';
@@ -364,6 +354,7 @@ export function allFilesInDirInHost(
recursive: boolean;
} = { recursive: true }
): Path[] {
const { join } = require('@angular-devkit/core');
const dir = host.getDir(path);
const res: Path[] = [];
dir.subfiles.forEach((p) => {
@@ -490,6 +481,7 @@ export function addDepsToPackageJson(
devDeps: any,
addInstall = true
): Rule {
const { chain, noop } = require('@angular-devkit/schematics');
return (host: Tree, context: SchematicContext) => {
const currentPackageJson = readJsonInTree(host, 'package.json');
@@ -525,6 +517,7 @@ export function updatePackageJsonDependencies(
devDeps: any,
addInstall = true
): Rule {
const { chain } = require('@angular-devkit/schematics');
return chain([
updateJsonInTree('package.json', (json, context: SchematicContext) => {
json.dependencies = {
@@ -723,6 +716,7 @@ function renameFile(tree: Tree, from: string, to: string) {
* Applies a template merge but skips for already existing entries
*/
export function applyWithSkipExisting(source: Source, rules: Rule[]): Rule {
const { mergeWith, apply, forEach } = require('@angular-devkit/schematics');
return (tree: Tree, _context: SchematicContext) => {
const rule = mergeWith(
apply(source, [
@@ -1,4 +1,4 @@
import { Tree } from '@angular-devkit/schematics';
import type { Tree } from '@angular-devkit/schematics';
import { readJsonInTree } from './ast-utils';
+2 -2
View File
@@ -1,6 +1,6 @@
import { Tree } from '@angular-devkit/schematics';
import type { Tree } from '@angular-devkit/schematics';
import { getProjectConfig } from './ast-utils';
import { join, Path } from '@angular-devkit/core';
import { join } from '@angular-devkit/core';
export enum ProjectType {
Application = 'application',
@@ -1,10 +1,12 @@
import { Rule } from '@angular-devkit/schematics';
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
import type { Rule } from '@angular-devkit/schematics';
let installAdded = false;
export function addInstallTask(
options: { skipInstall: boolean } = { skipInstall: false }
): Rule {
const {
NodePackageInstallTask,
} = require('@angular-devkit/schematics/tasks');
return (_, context) => {
if (!options.skipInstall && !installAdded) {
context.addTask(new NodePackageInstallTask());
@@ -1,4 +1,4 @@
import { Rule, Tree } from '@angular-devkit/schematics';
import type { Rule, Tree } from '@angular-devkit/schematics';
/**
* Remove a file from the Virtual Schematic Tree
@@ -1,4 +1,4 @@
import { Rule, Tree } from '@angular-devkit/schematics';
import type { Rule, Tree } from '@angular-devkit/schematics';
import { createOrUpdate, getProjectConfig } from '../ast-utils';
import { offsetFromRoot } from '@nrwl/devkit';
@@ -1,5 +1,5 @@
import { JsonObject } from '@angular-devkit/core';
import { Rule } from '@angular-devkit/schematics';
import type { JsonObject } from '@angular-devkit/core';
import type { Rule } from '@angular-devkit/schematics';
import { updateWorkspace } from '../workspace';
/**
@@ -1,4 +1,4 @@
import { Tree } from '@angular-devkit/schematics';
import type { Tree } from '@angular-devkit/schematics';
import {
_test_addWorkspaceFile,
WorkspaceFormat,
+1 -1
View File
@@ -1,6 +1,6 @@
import { join } from 'path';
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
import { Rule, Tree } from '@angular-devkit/schematics';
import type { Rule, Tree } from '@angular-devkit/schematics';
import { updateWorkspace } from './workspace';
import { TestingArchitectHost } from '@angular-devkit/architect/testing';
import { schema } from '@angular-devkit/core';
+1 -1
View File
@@ -1,4 +1,4 @@
import {
import type {
Rule,
SchematicContext,
TaskConfiguration,
+1 -1
View File
@@ -1,4 +1,4 @@
import { Tree, Rule } from '@angular-devkit/schematics';
import type { Tree, Rule } from '@angular-devkit/schematics';
import { JsonArray, JsonObject, workspaces } from '@angular-devkit/core';
import {
ProjectDefinition,