feat(nest): implement nest lib schematic (#2540)
This commit is contained in:
parent
ff6b434548
commit
a39587a350
@ -20,6 +20,7 @@ module.exports = {
|
|||||||
{ name: 'core', description: 'anything Nx core specific' },
|
{ name: 'core', description: 'anything Nx core specific' },
|
||||||
{ name: 'docs', description: 'anything related to docs infrastructure' },
|
{ name: 'docs', description: 'anything related to docs infrastructure' },
|
||||||
{ name: 'nextjs', description: 'anything Next specific' },
|
{ name: 'nextjs', description: 'anything Next specific' },
|
||||||
|
{ name: 'nest', description: 'anything Nest specific' },
|
||||||
{ name: 'node', description: 'anything Node specific' },
|
{ name: 'node', description: 'anything Node specific' },
|
||||||
{ name: 'nx-plugin', description: 'anything Nx Plugin specific' },
|
{ name: 'nx-plugin', description: 'anything Nx Plugin specific' },
|
||||||
{ name: 'react', description: 'anything React specific' },
|
{ name: 'react', description: 'anything React specific' },
|
||||||
|
|||||||
@ -181,6 +181,7 @@ The scope must be one of the following:
|
|||||||
- core - anything Nx core specific
|
- core - anything Nx core specific
|
||||||
- docs - anything related to docs infrastructure
|
- docs - anything related to docs infrastructure
|
||||||
- nextjs - anything Next specific
|
- nextjs - anything Next specific
|
||||||
|
- nest - anything Nest specific
|
||||||
- node - anything Node specific
|
- node - anything Node specific
|
||||||
- linter - anything Linter specific
|
- linter - anything Linter specific
|
||||||
- react - anything React specific
|
- react - anything React specific
|
||||||
|
|||||||
145
docs/angular/api-nest/schematics/library.md
Normal file
145
docs/angular/api-nest/schematics/library.md
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
# library
|
||||||
|
|
||||||
|
Create a new nest library
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ng generate library ...
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ng g lib ... # same
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, Nx will search for `library` in the default collection provisioned in `angular.json`.
|
||||||
|
|
||||||
|
You can specify the collection explicitly as follows:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ng g @nrwl/nest:library ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Show what will be generated without writing to disk:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ng g library ... --dry-run
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
Generate libs/myapp/mylib:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ng g lib mylib --directory=myapp
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
### controller
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Type: `boolean`
|
||||||
|
|
||||||
|
Include a controller with the library
|
||||||
|
|
||||||
|
### directory
|
||||||
|
|
||||||
|
Alias(es): d
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
A directory where the app is placed
|
||||||
|
|
||||||
|
### global
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Type: `boolean`
|
||||||
|
|
||||||
|
Add the Global decorator to the generated module.
|
||||||
|
|
||||||
|
### linter
|
||||||
|
|
||||||
|
Default: `tslint`
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Possible values: `eslint`, `tslint`
|
||||||
|
|
||||||
|
The tool to use for running lint checks.
|
||||||
|
|
||||||
|
### name
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Library name
|
||||||
|
|
||||||
|
### publishable
|
||||||
|
|
||||||
|
Type: `boolean`
|
||||||
|
|
||||||
|
Create a publishable library. A "build" architect will be added for this project the workspace configuration.
|
||||||
|
|
||||||
|
### service
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Type: `boolean`
|
||||||
|
|
||||||
|
Include a service with the library.
|
||||||
|
|
||||||
|
### skipFormat
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Type: `boolean`
|
||||||
|
|
||||||
|
Skip formatting files
|
||||||
|
|
||||||
|
### skipTsConfig
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Type: `boolean`
|
||||||
|
|
||||||
|
Do not update tsconfig.json for development experience.
|
||||||
|
|
||||||
|
### tags
|
||||||
|
|
||||||
|
Alias(es): t
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Add tags to the library (used for linting)
|
||||||
|
|
||||||
|
### target
|
||||||
|
|
||||||
|
Default: `es6`
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Possible values: `es5`, `es6`, `esnext`, `es2015`, `es2016`, `es2017`, `es2018`, `es2019`, `es2020`
|
||||||
|
|
||||||
|
The es target, Nest suggest using es6 or higher.
|
||||||
|
|
||||||
|
### testEnvironment
|
||||||
|
|
||||||
|
Default: `node`
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Possible values: `jsdom`, `node`
|
||||||
|
|
||||||
|
The test environment for jest, for node applications this should stay as node unless doing DOM testing.
|
||||||
|
|
||||||
|
### unitTestRunner
|
||||||
|
|
||||||
|
Default: `jest`
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Possible values: `jest`, `none`
|
||||||
|
|
||||||
|
Test runner to use for unit tests
|
||||||
@ -90,6 +90,16 @@ Type: `string`
|
|||||||
|
|
||||||
Add tags to the library (used for linting)
|
Add tags to the library (used for linting)
|
||||||
|
|
||||||
|
### testEnvironment
|
||||||
|
|
||||||
|
Default: `jsdom`
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Possible values: `jsdom`, `node`
|
||||||
|
|
||||||
|
The test environment to use if unitTestRunner is set to jest
|
||||||
|
|
||||||
### unitTestRunner
|
### unitTestRunner
|
||||||
|
|
||||||
Default: `jest`
|
Default: `jest`
|
||||||
|
|||||||
@ -80,6 +80,16 @@ Type: `string`
|
|||||||
|
|
||||||
Add tags to the library (used for linting)
|
Add tags to the library (used for linting)
|
||||||
|
|
||||||
|
### testEnvironment
|
||||||
|
|
||||||
|
Default: `jsdom`
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Possible values: `jsdom`, `node`
|
||||||
|
|
||||||
|
The test environment to use if unitTestRunner is set to jest
|
||||||
|
|
||||||
### unitTestRunner
|
### unitTestRunner
|
||||||
|
|
||||||
Default: `jest`
|
Default: `jest`
|
||||||
|
|||||||
145
docs/react/api-nest/schematics/library.md
Normal file
145
docs/react/api-nest/schematics/library.md
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
# library
|
||||||
|
|
||||||
|
Create a new nest library
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nx generate library ...
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nx g lib ... # same
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, Nx will search for `library` in the default collection provisioned in `workspace.json`.
|
||||||
|
|
||||||
|
You can specify the collection explicitly as follows:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nx g @nrwl/nest:library ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Show what will be generated without writing to disk:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nx g library ... --dry-run
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
Generate libs/myapp/mylib:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nx g lib mylib --directory=myapp
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
### controller
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Type: `boolean`
|
||||||
|
|
||||||
|
Include a controller with the library
|
||||||
|
|
||||||
|
### directory
|
||||||
|
|
||||||
|
Alias(es): d
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
A directory where the app is placed
|
||||||
|
|
||||||
|
### global
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Type: `boolean`
|
||||||
|
|
||||||
|
Add the Global decorator to the generated module.
|
||||||
|
|
||||||
|
### linter
|
||||||
|
|
||||||
|
Default: `tslint`
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Possible values: `eslint`, `tslint`
|
||||||
|
|
||||||
|
The tool to use for running lint checks.
|
||||||
|
|
||||||
|
### name
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Library name
|
||||||
|
|
||||||
|
### publishable
|
||||||
|
|
||||||
|
Type: `boolean`
|
||||||
|
|
||||||
|
Create a publishable library. A "build" architect will be added for this project the workspace configuration.
|
||||||
|
|
||||||
|
### service
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Type: `boolean`
|
||||||
|
|
||||||
|
Include a service with the library.
|
||||||
|
|
||||||
|
### skipFormat
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Type: `boolean`
|
||||||
|
|
||||||
|
Skip formatting files
|
||||||
|
|
||||||
|
### skipTsConfig
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Type: `boolean`
|
||||||
|
|
||||||
|
Do not update tsconfig.json for development experience.
|
||||||
|
|
||||||
|
### tags
|
||||||
|
|
||||||
|
Alias(es): t
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Add tags to the library (used for linting)
|
||||||
|
|
||||||
|
### target
|
||||||
|
|
||||||
|
Default: `es6`
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Possible values: `es5`, `es6`, `esnext`, `es2015`, `es2016`, `es2017`, `es2018`, `es2019`, `es2020`
|
||||||
|
|
||||||
|
The es target, Nest suggest using es6 or higher.
|
||||||
|
|
||||||
|
### testEnvironment
|
||||||
|
|
||||||
|
Default: `node`
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Possible values: `jsdom`, `node`
|
||||||
|
|
||||||
|
The test environment for jest, for node applications this should stay as node unless doing DOM testing.
|
||||||
|
|
||||||
|
### unitTestRunner
|
||||||
|
|
||||||
|
Default: `jest`
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Possible values: `jest`, `none`
|
||||||
|
|
||||||
|
Test runner to use for unit tests
|
||||||
@ -90,6 +90,16 @@ Type: `string`
|
|||||||
|
|
||||||
Add tags to the library (used for linting)
|
Add tags to the library (used for linting)
|
||||||
|
|
||||||
|
### testEnvironment
|
||||||
|
|
||||||
|
Default: `jsdom`
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Possible values: `jsdom`, `node`
|
||||||
|
|
||||||
|
The test environment to use if unitTestRunner is set to jest
|
||||||
|
|
||||||
### unitTestRunner
|
### unitTestRunner
|
||||||
|
|
||||||
Default: `jest`
|
Default: `jest`
|
||||||
|
|||||||
@ -80,6 +80,16 @@ Type: `string`
|
|||||||
|
|
||||||
Add tags to the library (used for linting)
|
Add tags to the library (used for linting)
|
||||||
|
|
||||||
|
### testEnvironment
|
||||||
|
|
||||||
|
Default: `jsdom`
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Possible values: `jsdom`, `node`
|
||||||
|
|
||||||
|
The test environment to use if unitTestRunner is set to jest
|
||||||
|
|
||||||
### unitTestRunner
|
### unitTestRunner
|
||||||
|
|
||||||
Default: `jest`
|
Default: `jest`
|
||||||
|
|||||||
145
docs/web/api-nest/schematics/library.md
Normal file
145
docs/web/api-nest/schematics/library.md
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
# library
|
||||||
|
|
||||||
|
Create a new nest library
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nx generate library ...
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nx g lib ... # same
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, Nx will search for `library` in the default collection provisioned in `workspace.json`.
|
||||||
|
|
||||||
|
You can specify the collection explicitly as follows:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nx g @nrwl/nest:library ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Show what will be generated without writing to disk:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nx g library ... --dry-run
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
Generate libs/myapp/mylib:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nx g lib mylib --directory=myapp
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
### controller
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Type: `boolean`
|
||||||
|
|
||||||
|
Include a controller with the library
|
||||||
|
|
||||||
|
### directory
|
||||||
|
|
||||||
|
Alias(es): d
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
A directory where the app is placed
|
||||||
|
|
||||||
|
### global
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Type: `boolean`
|
||||||
|
|
||||||
|
Add the Global decorator to the generated module.
|
||||||
|
|
||||||
|
### linter
|
||||||
|
|
||||||
|
Default: `tslint`
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Possible values: `eslint`, `tslint`
|
||||||
|
|
||||||
|
The tool to use for running lint checks.
|
||||||
|
|
||||||
|
### name
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Library name
|
||||||
|
|
||||||
|
### publishable
|
||||||
|
|
||||||
|
Type: `boolean`
|
||||||
|
|
||||||
|
Create a publishable library. A "build" architect will be added for this project the workspace configuration.
|
||||||
|
|
||||||
|
### service
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Type: `boolean`
|
||||||
|
|
||||||
|
Include a service with the library.
|
||||||
|
|
||||||
|
### skipFormat
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Type: `boolean`
|
||||||
|
|
||||||
|
Skip formatting files
|
||||||
|
|
||||||
|
### skipTsConfig
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Type: `boolean`
|
||||||
|
|
||||||
|
Do not update tsconfig.json for development experience.
|
||||||
|
|
||||||
|
### tags
|
||||||
|
|
||||||
|
Alias(es): t
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Add tags to the library (used for linting)
|
||||||
|
|
||||||
|
### target
|
||||||
|
|
||||||
|
Default: `es6`
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Possible values: `es5`, `es6`, `esnext`, `es2015`, `es2016`, `es2017`, `es2018`, `es2019`, `es2020`
|
||||||
|
|
||||||
|
The es target, Nest suggest using es6 or higher.
|
||||||
|
|
||||||
|
### testEnvironment
|
||||||
|
|
||||||
|
Default: `node`
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Possible values: `jsdom`, `node`
|
||||||
|
|
||||||
|
The test environment for jest, for node applications this should stay as node unless doing DOM testing.
|
||||||
|
|
||||||
|
### unitTestRunner
|
||||||
|
|
||||||
|
Default: `jest`
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Possible values: `jest`, `none`
|
||||||
|
|
||||||
|
Test runner to use for unit tests
|
||||||
@ -90,6 +90,16 @@ Type: `string`
|
|||||||
|
|
||||||
Add tags to the library (used for linting)
|
Add tags to the library (used for linting)
|
||||||
|
|
||||||
|
### testEnvironment
|
||||||
|
|
||||||
|
Default: `jsdom`
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Possible values: `jsdom`, `node`
|
||||||
|
|
||||||
|
The test environment to use if unitTestRunner is set to jest
|
||||||
|
|
||||||
### unitTestRunner
|
### unitTestRunner
|
||||||
|
|
||||||
Default: `jest`
|
Default: `jest`
|
||||||
|
|||||||
@ -80,6 +80,16 @@ Type: `string`
|
|||||||
|
|
||||||
Add tags to the library (used for linting)
|
Add tags to the library (used for linting)
|
||||||
|
|
||||||
|
### testEnvironment
|
||||||
|
|
||||||
|
Default: `jsdom`
|
||||||
|
|
||||||
|
Type: `string`
|
||||||
|
|
||||||
|
Possible values: `jsdom`, `node`
|
||||||
|
|
||||||
|
The test environment to use if unitTestRunner is set to jest
|
||||||
|
|
||||||
### unitTestRunner
|
### unitTestRunner
|
||||||
|
|
||||||
Default: `jest`
|
Default: `jest`
|
||||||
|
|||||||
@ -21,6 +21,8 @@ import {
|
|||||||
setMaxWorkers,
|
setMaxWorkers,
|
||||||
newProject
|
newProject
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
import { stripIndents } from '@angular-devkit/core/src/utils/literals';
|
||||||
|
import { readFile } from './utils';
|
||||||
|
|
||||||
function getData(): Promise<any> {
|
function getData(): Promise<any> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
@ -226,6 +228,73 @@ forEachCli(currentCLIName => {
|
|||||||
});
|
});
|
||||||
}, 120000);
|
}, 120000);
|
||||||
|
|
||||||
|
describe('nest libraries', function() {
|
||||||
|
it('should be able to generate a nest library', async () => {
|
||||||
|
ensureProject();
|
||||||
|
const nestlib = uniq('nestlib');
|
||||||
|
|
||||||
|
runCLI(`generate @nrwl/nest:lib ${nestlib}`);
|
||||||
|
|
||||||
|
const jestConfigContent = readFile(`libs/${nestlib}/jest.config.js`);
|
||||||
|
|
||||||
|
expect(stripIndents`${jestConfigContent}`).toEqual(
|
||||||
|
stripIndents`module.exports = {
|
||||||
|
name: '${nestlib}',
|
||||||
|
preset: '../../jest.config.js',
|
||||||
|
testEnvironment: 'node',
|
||||||
|
transform: {
|
||||||
|
'^.+\\.[tj]sx?$': 'ts-jest'
|
||||||
|
},
|
||||||
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||||
|
coverageDirectory: '../../coverage/libs/${nestlib}'
|
||||||
|
};
|
||||||
|
`
|
||||||
|
);
|
||||||
|
|
||||||
|
const lintResults = runCLI(`lint ${nestlib}`);
|
||||||
|
expect(lintResults).toContain('All files pass linting.');
|
||||||
|
}, 60000);
|
||||||
|
|
||||||
|
it('should be able to generate a nest library w/ service', async () => {
|
||||||
|
ensureProject();
|
||||||
|
const nestlib = uniq('nestlib');
|
||||||
|
|
||||||
|
runCLI(`generate @nrwl/nest:lib ${nestlib} --service`);
|
||||||
|
|
||||||
|
const lintResults = runCLI(`lint ${nestlib}`);
|
||||||
|
expect(lintResults).toContain('All files pass linting.');
|
||||||
|
|
||||||
|
const jestResult = await runCLIAsync(`test ${nestlib}`);
|
||||||
|
expect(jestResult.stderr).toContain('Test Suites: 1 passed, 1 total');
|
||||||
|
}, 60000);
|
||||||
|
|
||||||
|
it('should be able to generate a nest library w/ controller', async () => {
|
||||||
|
ensureProject();
|
||||||
|
const nestlib = uniq('nestlib');
|
||||||
|
|
||||||
|
runCLI(`generate @nrwl/nest:lib ${nestlib} --controller`);
|
||||||
|
|
||||||
|
const lintResults = runCLI(`lint ${nestlib}`);
|
||||||
|
expect(lintResults).toContain('All files pass linting.');
|
||||||
|
|
||||||
|
const jestResult = await runCLIAsync(`test ${nestlib}`);
|
||||||
|
expect(jestResult.stderr).toContain('Test Suites: 1 passed, 1 total');
|
||||||
|
}, 60000);
|
||||||
|
|
||||||
|
it('should be able to generate a nest library w/ controller and service', async () => {
|
||||||
|
ensureProject();
|
||||||
|
const nestlib = uniq('nestlib');
|
||||||
|
|
||||||
|
runCLI(`generate @nrwl/nest:lib ${nestlib} --controller --service`);
|
||||||
|
|
||||||
|
const lintResults = runCLI(`lint ${nestlib}`);
|
||||||
|
expect(lintResults).toContain('All files pass linting.');
|
||||||
|
|
||||||
|
const jestResult = await runCLIAsync(`test ${nestlib}`);
|
||||||
|
expect(jestResult.stderr).toContain('Test Suites: 2 passed, 2 total');
|
||||||
|
}, 60000);
|
||||||
|
});
|
||||||
|
|
||||||
it('should be able to generate an empty application', async () => {
|
it('should be able to generate an empty application', async () => {
|
||||||
ensureProject();
|
ensureProject();
|
||||||
const nodeapp = uniq('nodeapp');
|
const nodeapp = uniq('nodeapp');
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
name: '<%= project %>',
|
name: '<%= project %>',
|
||||||
preset: '<%= offsetFromRoot %>jest.config.js',<% if (supportTsx) { %>
|
preset: '<%= offsetFromRoot %>jest.config.js',<% if(testEnvironment) { %>
|
||||||
|
testEnvironment: '<%= testEnvironment %>',<% } %><% if (supportTsx) { %>
|
||||||
transform: {
|
transform: {
|
||||||
'^.+\\.[tj]sx?$': 'ts-jest'
|
'^.+\\.[tj]sx?$': 'ts-jest'
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,23 +1,22 @@
|
|||||||
import {
|
import {
|
||||||
Rule,
|
|
||||||
Tree,
|
|
||||||
mergeWith,
|
|
||||||
chain,
|
|
||||||
url,
|
|
||||||
apply,
|
apply,
|
||||||
SchematicContext,
|
chain,
|
||||||
|
filter,
|
||||||
|
mergeWith,
|
||||||
move,
|
move,
|
||||||
template,
|
|
||||||
noop,
|
noop,
|
||||||
filter
|
Rule,
|
||||||
|
SchematicContext,
|
||||||
|
template,
|
||||||
|
Tree,
|
||||||
|
url
|
||||||
} from '@angular-devkit/schematics';
|
} from '@angular-devkit/schematics';
|
||||||
import {
|
import {
|
||||||
readJsonInTree,
|
getProjectConfig,
|
||||||
|
offsetFromRoot,
|
||||||
updateJsonInTree,
|
updateJsonInTree,
|
||||||
updateWorkspaceInTree
|
updateWorkspaceInTree
|
||||||
} from '@nrwl/workspace';
|
} from '@nrwl/workspace';
|
||||||
import { getProjectConfig, addDepsToPackageJson } from '@nrwl/workspace';
|
|
||||||
import { offsetFromRoot } from '@nrwl/workspace';
|
|
||||||
import { join, normalize } from '@angular-devkit/core';
|
import { join, normalize } from '@angular-devkit/core';
|
||||||
import init from '../init/init';
|
import init from '../init/init';
|
||||||
|
|
||||||
@ -27,6 +26,7 @@ export interface JestProjectSchema {
|
|||||||
skipSetupFile: boolean;
|
skipSetupFile: boolean;
|
||||||
setupFile: 'angular' | 'web-components' | 'none';
|
setupFile: 'angular' | 'web-components' | 'none';
|
||||||
skipSerializers: boolean;
|
skipSerializers: boolean;
|
||||||
|
testEnvironment: 'node' | 'jsdom' | '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateFiles(options: JestProjectSchema): Rule {
|
function generateFiles(options: JestProjectSchema): Rule {
|
||||||
@ -114,6 +114,10 @@ function check(options: JestProjectSchema): Rule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function normalizeOptions(options: JestProjectSchema): JestProjectSchema {
|
function normalizeOptions(options: JestProjectSchema): JestProjectSchema {
|
||||||
|
if (options.testEnvironment === 'jsdom') {
|
||||||
|
options.testEnvironment = '';
|
||||||
|
}
|
||||||
|
|
||||||
if (!options.skipSetupFile) {
|
if (!options.skipSetupFile) {
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,6 +32,12 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Setup tsx support",
|
"description": "Setup tsx support",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"testEnvironment": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["jsdom", "node"],
|
||||||
|
"description": "The test environment for jest",
|
||||||
|
"default": "jsdom"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": []
|
"required": []
|
||||||
|
|||||||
@ -16,6 +16,13 @@
|
|||||||
"schema": "./src/schematics/application/schema.json",
|
"schema": "./src/schematics/application/schema.json",
|
||||||
"aliases": ["app"],
|
"aliases": ["app"],
|
||||||
"description": "Create a nest application"
|
"description": "Create a nest application"
|
||||||
|
},
|
||||||
|
|
||||||
|
"library": {
|
||||||
|
"factory": "./src/schematics/library/library",
|
||||||
|
"schema": "./src/schematics/library/schema.json",
|
||||||
|
"aliases": ["lib"],
|
||||||
|
"description": "Create a new nest library"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,26 @@
|
|||||||
|
import { Test } from '@nestjs/testing';
|
||||||
|
import { <%= className %>Controller } from './<%= fileName %>.controller';
|
||||||
|
<% if(service) { %>import { <%= className %>Service } from './<%= fileName %>.service';<% } %>
|
||||||
|
|
||||||
|
describe('<%= className %>Controller', () => {
|
||||||
|
|
||||||
|
let controller: <%= className %>Controller;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module = await Test.createTestingModule({
|
||||||
|
providers: [
|
||||||
|
<% if(service) { %><%= className %>Service<% } %>
|
||||||
|
],
|
||||||
|
controllers: [
|
||||||
|
<%= className %>Controller
|
||||||
|
]
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
controller = module.get(<%= className %>Controller);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(controller).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
})
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
import { Controller } from '@nestjs/common';
|
||||||
|
<% if(service) { %>import { <%= className %>Service } from './<%= fileName %>.service';<% } %>
|
||||||
|
|
||||||
|
@Controller('<%= fileName %>')
|
||||||
|
export class <%= className %>Controller {
|
||||||
|
constructor(<% if(service) { %>private <%= propertyName %>Service: <%= className %>Service<% } %>) {}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
import { Module<% if(global) { %>, Global<% } %> } from '@nestjs/common';
|
||||||
|
<% if(service) { %>import { <%= className %>Service } from './<%= fileName %>.service';<% } %>
|
||||||
|
<% if(controller) { %>import { <%= className %>Controller } from './<%= fileName %>.controller';<% } %>
|
||||||
|
|
||||||
|
<% if(global) { %>@Global()<% } %>
|
||||||
|
@Module({
|
||||||
|
controllers: [
|
||||||
|
<% if(controller) { %><%= className %>Controller<% } %>
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
<% if(service) { %><%= className %>Service<% } %>
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
<% if(service) { %><%= className %>Service<% } %>
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class <%= className %>Module {
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
import { Test } from '@nestjs/testing';
|
||||||
|
import { <%= className %>Service } from './<%= fileName %>.service';
|
||||||
|
|
||||||
|
describe('<%= className %>Service', () => {
|
||||||
|
|
||||||
|
let service: <%= className %>Service;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module = await Test.createTestingModule({
|
||||||
|
providers: [
|
||||||
|
<%= className %>Service
|
||||||
|
]
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
service = module.get(<%= className %>Service);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
})
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class <%= className %>Service {
|
||||||
|
constructor() {}
|
||||||
|
}
|
||||||
409
packages/nest/src/schematics/library/library.spec.ts
Normal file
409
packages/nest/src/schematics/library/library.spec.ts
Normal file
@ -0,0 +1,409 @@
|
|||||||
|
import { Tree } from '@angular-devkit/schematics';
|
||||||
|
import { NxJson, readJsonInTree } from '@nrwl/workspace';
|
||||||
|
import { createEmptyWorkspace, getFileContent } from '@nrwl/workspace/testing';
|
||||||
|
import { runSchematic } from '../../utils/testing';
|
||||||
|
import { stripIndents } from '@angular-devkit/core/src/utils/literals';
|
||||||
|
|
||||||
|
describe('lib', () => {
|
||||||
|
let appTree: Tree;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
appTree = Tree.empty();
|
||||||
|
appTree = createEmptyWorkspace(appTree);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('not nested', () => {
|
||||||
|
it('should update workspace.json', async () => {
|
||||||
|
const tree = await runSchematic('lib', { name: 'myLib' }, appTree);
|
||||||
|
const workspaceJson = readJsonInTree(tree, '/workspace.json');
|
||||||
|
expect(workspaceJson.projects['my-lib'].root).toEqual('libs/my-lib');
|
||||||
|
expect(workspaceJson.projects['my-lib'].architect.build).toBeUndefined();
|
||||||
|
expect(workspaceJson.projects['my-lib'].architect.lint).toEqual({
|
||||||
|
builder: '@angular-devkit/build-angular:tslint',
|
||||||
|
options: {
|
||||||
|
exclude: ['**/node_modules/**', '!libs/my-lib/**'],
|
||||||
|
tsConfig: [
|
||||||
|
'libs/my-lib/tsconfig.lib.json',
|
||||||
|
'libs/my-lib/tsconfig.spec.json'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(workspaceJson.projects['my-lib'].architect.test).toEqual({
|
||||||
|
builder: '@nrwl/jest:jest',
|
||||||
|
options: {
|
||||||
|
jestConfig: 'libs/my-lib/jest.config.js',
|
||||||
|
tsConfig: 'libs/my-lib/tsconfig.spec.json',
|
||||||
|
passWithNoTests: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should include a controller', async () => {
|
||||||
|
const tree = await runSchematic(
|
||||||
|
'lib',
|
||||||
|
{ name: 'myLib', controller: true },
|
||||||
|
appTree
|
||||||
|
);
|
||||||
|
const service = getFileContent(
|
||||||
|
tree,
|
||||||
|
'libs/my-lib/src/lib/my-lib.controller.ts'
|
||||||
|
);
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should include a service', async () => {
|
||||||
|
const tree = await runSchematic(
|
||||||
|
'lib',
|
||||||
|
{ name: 'myLib', service: true },
|
||||||
|
appTree
|
||||||
|
);
|
||||||
|
const service = getFileContent(
|
||||||
|
tree,
|
||||||
|
'libs/my-lib/src/lib/my-lib.service.ts'
|
||||||
|
);
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add the @Global decorator', async () => {
|
||||||
|
const tree = await runSchematic(
|
||||||
|
'lib',
|
||||||
|
{ name: 'myLib', global: true },
|
||||||
|
appTree
|
||||||
|
);
|
||||||
|
const module = getFileContent(
|
||||||
|
tree,
|
||||||
|
'libs/my-lib/src/lib/my-lib.module.ts'
|
||||||
|
);
|
||||||
|
expect(stripIndents`${module}`).toEqual(
|
||||||
|
stripIndents`import { Module, Global } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Global()
|
||||||
|
@Module({
|
||||||
|
controllers: [],
|
||||||
|
providers: [],
|
||||||
|
exports: []
|
||||||
|
})
|
||||||
|
export class MyLibModule {}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should provide the controller and service', async () => {
|
||||||
|
const tree = await runSchematic(
|
||||||
|
'lib',
|
||||||
|
{ name: 'myLib', service: true, controller: true },
|
||||||
|
appTree
|
||||||
|
);
|
||||||
|
const module = getFileContent(
|
||||||
|
tree,
|
||||||
|
'libs/my-lib/src/lib/my-lib.module.ts'
|
||||||
|
);
|
||||||
|
expect(stripIndents`${module}`).toEqual(
|
||||||
|
stripIndents`import { Module } from '@nestjs/common';
|
||||||
|
import { MyLibService } from './my-lib.service';
|
||||||
|
import { MyLibController } from './my-lib.controller';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
controllers: [MyLibController],
|
||||||
|
providers: [MyLibService],
|
||||||
|
exports: [MyLibService]
|
||||||
|
})
|
||||||
|
export class MyLibModule {}`
|
||||||
|
);
|
||||||
|
|
||||||
|
const controller = getFileContent(
|
||||||
|
tree,
|
||||||
|
'libs/my-lib/src/lib/my-lib.controller.ts'
|
||||||
|
);
|
||||||
|
expect(stripIndents`${controller}`).toEqual(
|
||||||
|
stripIndents`import { Controller } from '@nestjs/common';
|
||||||
|
import { MyLibService } from './my-lib.service';
|
||||||
|
|
||||||
|
@Controller('my-lib')
|
||||||
|
export class MyLibController {
|
||||||
|
constructor(private myLibService: MyLibService) {}
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
|
||||||
|
const barrel = getFileContent(tree, 'libs/my-lib/src/index.ts');
|
||||||
|
expect(stripIndents`${barrel}`).toEqual(
|
||||||
|
stripIndents`export * from './lib/my-lib.module';
|
||||||
|
export * from './lib/my-lib.service';
|
||||||
|
export * from './lib/my-lib.controller';`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update nx.json', async () => {
|
||||||
|
const tree = await runSchematic(
|
||||||
|
'lib',
|
||||||
|
{ name: 'myLib', tags: 'one,two' },
|
||||||
|
appTree
|
||||||
|
);
|
||||||
|
const nxJson = readJsonInTree<NxJson>(tree, '/nx.json');
|
||||||
|
expect(nxJson).toEqual({
|
||||||
|
npmScope: 'proj',
|
||||||
|
projects: {
|
||||||
|
'my-lib': {
|
||||||
|
tags: ['one', 'two']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update root tsconfig.json', async () => {
|
||||||
|
const tree = await runSchematic('lib', { name: 'myLib' }, appTree);
|
||||||
|
const tsconfigJson = readJsonInTree(tree, '/tsconfig.json');
|
||||||
|
expect(tsconfigJson.compilerOptions.paths['@proj/my-lib']).toEqual([
|
||||||
|
'libs/my-lib/src/index.ts'
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create a local tsconfig.json', async () => {
|
||||||
|
const tree = await runSchematic('lib', { name: 'myLib' }, appTree);
|
||||||
|
const tsconfigJson = readJsonInTree(tree, 'libs/my-lib/tsconfig.json');
|
||||||
|
expect(tsconfigJson).toEqual({
|
||||||
|
extends: '../../tsconfig.json',
|
||||||
|
compilerOptions: {
|
||||||
|
types: ['node', 'jest'],
|
||||||
|
target: 'es6'
|
||||||
|
},
|
||||||
|
include: ['**/*.ts']
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should extend the local tsconfig.json with tsconfig.spec.json', async () => {
|
||||||
|
const tree = await runSchematic('lib', { name: 'myLib' }, appTree);
|
||||||
|
const tsconfigJson = readJsonInTree(
|
||||||
|
tree,
|
||||||
|
'libs/my-lib/tsconfig.spec.json'
|
||||||
|
);
|
||||||
|
expect(tsconfigJson.extends).toEqual('./tsconfig.json');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should extend the local tsconfig.json with tsconfig.lib.json', async () => {
|
||||||
|
const tree = await runSchematic('lib', { name: 'myLib' }, appTree);
|
||||||
|
const tsconfigJson = readJsonInTree(
|
||||||
|
tree,
|
||||||
|
'libs/my-lib/tsconfig.lib.json'
|
||||||
|
);
|
||||||
|
expect(tsconfigJson.extends).toEqual('./tsconfig.json');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate files', async () => {
|
||||||
|
const tree = await runSchematic('lib', { name: 'myLib' }, appTree);
|
||||||
|
expect(tree.exists(`libs/my-lib/jest.config.js`)).toBeTruthy();
|
||||||
|
expect(tree.exists('libs/my-lib/src/index.ts')).toBeTruthy();
|
||||||
|
expect(tree.exists(`libs/my-lib/src/lib/my-lib.spec.ts`)).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('nested', () => {
|
||||||
|
it('should update nx.json', async () => {
|
||||||
|
const tree = await runSchematic(
|
||||||
|
'lib',
|
||||||
|
{
|
||||||
|
name: 'myLib',
|
||||||
|
directory: 'myDir',
|
||||||
|
tags: 'one'
|
||||||
|
},
|
||||||
|
appTree
|
||||||
|
);
|
||||||
|
const nxJson = readJsonInTree<NxJson>(tree, '/nx.json');
|
||||||
|
expect(nxJson).toEqual({
|
||||||
|
npmScope: 'proj',
|
||||||
|
projects: {
|
||||||
|
'my-dir-my-lib': {
|
||||||
|
tags: ['one']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const tree2 = await runSchematic(
|
||||||
|
'lib',
|
||||||
|
{
|
||||||
|
name: 'myLib2',
|
||||||
|
directory: 'myDir',
|
||||||
|
tags: 'one,two'
|
||||||
|
},
|
||||||
|
tree
|
||||||
|
);
|
||||||
|
const nxJson2 = readJsonInTree<NxJson>(tree2, '/nx.json');
|
||||||
|
expect(nxJson2).toEqual({
|
||||||
|
npmScope: 'proj',
|
||||||
|
projects: {
|
||||||
|
'my-dir-my-lib': {
|
||||||
|
tags: ['one']
|
||||||
|
},
|
||||||
|
'my-dir-my-lib2': {
|
||||||
|
tags: ['one', 'two']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate files', async () => {
|
||||||
|
const tree = await runSchematic(
|
||||||
|
'lib',
|
||||||
|
{ name: 'myLib', directory: 'myDir' },
|
||||||
|
appTree
|
||||||
|
);
|
||||||
|
expect(tree.exists(`libs/my-dir/my-lib/jest.config.js`)).toBeTruthy();
|
||||||
|
expect(tree.exists('libs/my-dir/my-lib/src/index.ts')).toBeTruthy();
|
||||||
|
expect(
|
||||||
|
tree.exists(`libs/my-dir/my-lib/src/lib/my-lib.spec.ts`)
|
||||||
|
).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update workspace.json', async () => {
|
||||||
|
const tree = await runSchematic(
|
||||||
|
'lib',
|
||||||
|
{ name: 'myLib', directory: 'myDir' },
|
||||||
|
appTree
|
||||||
|
);
|
||||||
|
const workspaceJson = readJsonInTree(tree, '/workspace.json');
|
||||||
|
|
||||||
|
expect(workspaceJson.projects['my-dir-my-lib'].root).toEqual(
|
||||||
|
'libs/my-dir/my-lib'
|
||||||
|
);
|
||||||
|
expect(workspaceJson.projects['my-dir-my-lib'].architect.lint).toEqual({
|
||||||
|
builder: '@angular-devkit/build-angular:tslint',
|
||||||
|
options: {
|
||||||
|
exclude: ['**/node_modules/**', '!libs/my-dir/my-lib/**'],
|
||||||
|
tsConfig: [
|
||||||
|
'libs/my-dir/my-lib/tsconfig.lib.json',
|
||||||
|
'libs/my-dir/my-lib/tsconfig.spec.json'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update tsconfig.json', async () => {
|
||||||
|
const tree = await runSchematic(
|
||||||
|
'lib',
|
||||||
|
{ name: 'myLib', directory: 'myDir' },
|
||||||
|
appTree
|
||||||
|
);
|
||||||
|
const tsconfigJson = readJsonInTree(tree, '/tsconfig.json');
|
||||||
|
expect(tsconfigJson.compilerOptions.paths['@proj/my-dir/my-lib']).toEqual(
|
||||||
|
['libs/my-dir/my-lib/src/index.ts']
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
tsconfigJson.compilerOptions.paths['my-dir-my-lib/*']
|
||||||
|
).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create a local tsconfig.json', async () => {
|
||||||
|
const tree = await runSchematic(
|
||||||
|
'lib',
|
||||||
|
{ name: 'myLib', directory: 'myDir' },
|
||||||
|
appTree
|
||||||
|
);
|
||||||
|
|
||||||
|
const tsconfigJson = readJsonInTree(
|
||||||
|
tree,
|
||||||
|
'libs/my-dir/my-lib/tsconfig.json'
|
||||||
|
);
|
||||||
|
expect(tsconfigJson).toEqual({
|
||||||
|
extends: '../../../tsconfig.json',
|
||||||
|
compilerOptions: {
|
||||||
|
types: ['node', 'jest'],
|
||||||
|
target: 'es6'
|
||||||
|
},
|
||||||
|
include: ['**/*.ts']
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('--unit-test-runner none', () => {
|
||||||
|
it('should not generate test configuration', async () => {
|
||||||
|
const resultTree = await runSchematic(
|
||||||
|
'lib',
|
||||||
|
{ name: 'myLib', unitTestRunner: 'none' },
|
||||||
|
appTree
|
||||||
|
);
|
||||||
|
expect(resultTree.exists('libs/my-lib/tsconfig.spec.json')).toBeFalsy();
|
||||||
|
expect(resultTree.exists('libs/my-lib/jest.config.js')).toBeFalsy();
|
||||||
|
expect(resultTree.exists('libs/my-lib/lib/my-lib.spec.ts')).toBeFalsy();
|
||||||
|
const workspaceJson = readJsonInTree(resultTree, 'workspace.json');
|
||||||
|
expect(workspaceJson.projects['my-lib'].architect.test).toBeUndefined();
|
||||||
|
const tsconfigJson = readJsonInTree(
|
||||||
|
resultTree,
|
||||||
|
'libs/my-lib/tsconfig.json'
|
||||||
|
);
|
||||||
|
expect(tsconfigJson).toEqual({
|
||||||
|
extends: '../../tsconfig.json',
|
||||||
|
compilerOptions: {
|
||||||
|
types: ['node'],
|
||||||
|
target: 'es6'
|
||||||
|
},
|
||||||
|
include: ['**/*.ts']
|
||||||
|
});
|
||||||
|
expect(
|
||||||
|
workspaceJson.projects['my-lib'].architect.lint.options.tsConfig
|
||||||
|
).toEqual(['libs/my-lib/tsconfig.lib.json']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('publishable package', () => {
|
||||||
|
it('should update package.json', async () => {
|
||||||
|
const publishableTree = await runSchematic(
|
||||||
|
'lib',
|
||||||
|
{ name: 'mylib', publishable: true },
|
||||||
|
appTree
|
||||||
|
);
|
||||||
|
|
||||||
|
let packageJsonContent = readJsonInTree(
|
||||||
|
publishableTree,
|
||||||
|
'libs/mylib/package.json'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(packageJsonContent.name).toEqual('@proj/mylib');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('compiler options target', () => {
|
||||||
|
it('should set target to es6 in tsconfig.json by default', async () => {
|
||||||
|
const tree = await runSchematic(
|
||||||
|
'lib',
|
||||||
|
{ name: 'myLib', directory: 'myDir' },
|
||||||
|
appTree
|
||||||
|
);
|
||||||
|
|
||||||
|
const tsconfigJson = readJsonInTree(
|
||||||
|
tree,
|
||||||
|
'libs/my-dir/my-lib/tsconfig.json'
|
||||||
|
);
|
||||||
|
expect(tsconfigJson.compilerOptions.target).toEqual('es6');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set target to es2020 in tsconfig.json', async () => {
|
||||||
|
const tree = await runSchematic(
|
||||||
|
'lib',
|
||||||
|
{ name: 'myLib', directory: 'myDir', target: 'es2020' },
|
||||||
|
appTree
|
||||||
|
);
|
||||||
|
|
||||||
|
const tsconfigJson = readJsonInTree(
|
||||||
|
tree,
|
||||||
|
'libs/my-dir/my-lib/tsconfig.json'
|
||||||
|
);
|
||||||
|
expect(tsconfigJson.compilerOptions.target).toEqual('es2020');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set target jest testEnvironment to node', async () => {
|
||||||
|
const tree = await runSchematic('lib', { name: 'myLib' }, appTree);
|
||||||
|
|
||||||
|
const jestConfig = getFileContent(tree, 'libs/my-lib/jest.config.js');
|
||||||
|
expect(stripIndents`${jestConfig}`)
|
||||||
|
.toEqual(stripIndents`module.exports = {
|
||||||
|
name: 'my-lib',
|
||||||
|
preset: '../../jest.config.js',
|
||||||
|
testEnvironment: 'node',
|
||||||
|
transform: {
|
||||||
|
'^.+\\.[tj]sx?$': 'ts-jest'
|
||||||
|
},
|
||||||
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||||
|
coverageDirectory: '../../coverage/libs/my-lib'
|
||||||
|
};`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
192
packages/nest/src/schematics/library/library.ts
Normal file
192
packages/nest/src/schematics/library/library.ts
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
import { normalize, Path } from '@angular-devkit/core';
|
||||||
|
import {
|
||||||
|
apply,
|
||||||
|
chain,
|
||||||
|
externalSchematic,
|
||||||
|
filter,
|
||||||
|
MergeStrategy,
|
||||||
|
mergeWith,
|
||||||
|
move,
|
||||||
|
noop,
|
||||||
|
Rule,
|
||||||
|
SchematicContext,
|
||||||
|
template,
|
||||||
|
Tree,
|
||||||
|
url
|
||||||
|
} from '@angular-devkit/schematics';
|
||||||
|
import {
|
||||||
|
addGlobal,
|
||||||
|
deleteFile,
|
||||||
|
formatFiles,
|
||||||
|
getNpmScope,
|
||||||
|
getProjectConfig,
|
||||||
|
insert,
|
||||||
|
names,
|
||||||
|
offsetFromRoot,
|
||||||
|
toFileName,
|
||||||
|
updateJsonInTree,
|
||||||
|
updateWorkspaceInTree
|
||||||
|
} from '@nrwl/workspace';
|
||||||
|
import { Schema } from './schema';
|
||||||
|
import * as ts from 'typescript';
|
||||||
|
import { RemoveChange } from '@nrwl/workspace/src/utils/ast-utils';
|
||||||
|
|
||||||
|
export interface NormalizedSchema extends Schema {
|
||||||
|
name: string;
|
||||||
|
prefix: string;
|
||||||
|
fileName: string;
|
||||||
|
projectRoot: Path;
|
||||||
|
projectDirectory: string;
|
||||||
|
parsedTags: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function(schema: NormalizedSchema): Rule {
|
||||||
|
return (host: Tree, context: SchematicContext) => {
|
||||||
|
const options = normalizeOptions(host, schema);
|
||||||
|
|
||||||
|
return chain([
|
||||||
|
externalSchematic('@nrwl/node', 'lib', schema),
|
||||||
|
createFiles(options),
|
||||||
|
addExportsToBarrelFile(options),
|
||||||
|
updateTsConfig(options),
|
||||||
|
addProject(options),
|
||||||
|
formatFiles(options),
|
||||||
|
deleteFile(`/${options.projectRoot}/src/lib/${options.fileName}.spec.ts`)
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeOptions(host: Tree, options: Schema): NormalizedSchema {
|
||||||
|
const defaultPrefix = getNpmScope(host);
|
||||||
|
const name = toFileName(options.name);
|
||||||
|
const projectDirectory = options.directory
|
||||||
|
? `${toFileName(options.directory)}/${name}`
|
||||||
|
: name;
|
||||||
|
|
||||||
|
const projectName = projectDirectory.replace(new RegExp('/', 'g'), '-');
|
||||||
|
const fileName = projectName;
|
||||||
|
const projectRoot = normalize(`libs/${projectDirectory}`);
|
||||||
|
|
||||||
|
const parsedTags = options.tags
|
||||||
|
? options.tags.split(',').map(s => s.trim())
|
||||||
|
: [];
|
||||||
|
|
||||||
|
const normalized: NormalizedSchema = {
|
||||||
|
...options,
|
||||||
|
prefix: defaultPrefix, // we could also allow customizing this
|
||||||
|
fileName,
|
||||||
|
name: projectName,
|
||||||
|
projectRoot,
|
||||||
|
projectDirectory,
|
||||||
|
parsedTags
|
||||||
|
};
|
||||||
|
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addExportsToBarrelFile(options: NormalizedSchema): Rule {
|
||||||
|
return (host: Tree) => {
|
||||||
|
const indexFilePath = `${options.projectRoot}/src/index.ts`;
|
||||||
|
const buffer = host.read(indexFilePath);
|
||||||
|
if (!!buffer) {
|
||||||
|
const indexSource = buffer!.toString('utf-8');
|
||||||
|
const indexSourceFile = ts.createSourceFile(
|
||||||
|
indexFilePath,
|
||||||
|
indexSource,
|
||||||
|
ts.ScriptTarget.Latest,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
insert(host, indexFilePath, [
|
||||||
|
new RemoveChange(
|
||||||
|
indexFilePath,
|
||||||
|
0,
|
||||||
|
`export * from './lib/${options.fileName}';`
|
||||||
|
),
|
||||||
|
...addGlobal(
|
||||||
|
indexSourceFile,
|
||||||
|
indexFilePath,
|
||||||
|
`export * from './lib/${options.fileName}.module';`
|
||||||
|
),
|
||||||
|
...(options.service
|
||||||
|
? addGlobal(
|
||||||
|
indexSourceFile,
|
||||||
|
indexFilePath,
|
||||||
|
`export * from './lib/${options.fileName}.service';`
|
||||||
|
)
|
||||||
|
: []),
|
||||||
|
...(options.controller
|
||||||
|
? addGlobal(
|
||||||
|
indexSourceFile,
|
||||||
|
indexFilePath,
|
||||||
|
`export * from './lib/${options.fileName}.controller';`
|
||||||
|
)
|
||||||
|
: [])
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function createFiles(options: NormalizedSchema): Rule {
|
||||||
|
return mergeWith(
|
||||||
|
apply(url(`./files/lib`), [
|
||||||
|
template({
|
||||||
|
...options,
|
||||||
|
...names(options.name),
|
||||||
|
tmpl: '',
|
||||||
|
offsetFromRoot: offsetFromRoot(options.projectRoot)
|
||||||
|
}),
|
||||||
|
move(options.projectRoot),
|
||||||
|
options.unitTestRunner === 'none'
|
||||||
|
? filter(file => !file.endsWith('spec.ts'))
|
||||||
|
: noop(),
|
||||||
|
options.publishable
|
||||||
|
? noop()
|
||||||
|
: filter(file => !file.endsWith('package.json')),
|
||||||
|
options.service ? noop() : filter(file => !file.endsWith('.service.ts')),
|
||||||
|
options.controller
|
||||||
|
? noop()
|
||||||
|
: filter(file => !file.endsWith('.controller.ts')),
|
||||||
|
!options.controller || options.unitTestRunner === 'none'
|
||||||
|
? filter(file => !file.endsWith('.controller.spec.ts'))
|
||||||
|
: noop(),
|
||||||
|
!options.service || options.unitTestRunner === 'none'
|
||||||
|
? filter(file => !file.endsWith('.service.spec.ts'))
|
||||||
|
: noop()
|
||||||
|
]),
|
||||||
|
MergeStrategy.Overwrite
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTsConfig(options: NormalizedSchema): Rule {
|
||||||
|
return (host: Tree, context: SchematicContext) => {
|
||||||
|
const projectConfig = getProjectConfig(host, options.name);
|
||||||
|
return updateJsonInTree(`${projectConfig.root}/tsconfig.json`, json => {
|
||||||
|
json.compilerOptions.target = options.target;
|
||||||
|
return json;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function addProject(options: NormalizedSchema): Rule {
|
||||||
|
if (!options.publishable) {
|
||||||
|
return noop();
|
||||||
|
}
|
||||||
|
|
||||||
|
return updateWorkspaceInTree(json => {
|
||||||
|
const architect = json.projects[options.name].architect;
|
||||||
|
if (architect) {
|
||||||
|
architect.build = {
|
||||||
|
builder: '@nrwl/node:package',
|
||||||
|
options: {
|
||||||
|
outputPath: `dist/libs/${options.projectDirectory}`,
|
||||||
|
tsConfig: `${options.projectRoot}/tsconfig.lib.json`,
|
||||||
|
packageJson: `${options.projectRoot}/package.json`,
|
||||||
|
main: `${options.projectRoot}/src/index.ts`,
|
||||||
|
assets: [`${options.projectRoot}/*.md`]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return json;
|
||||||
|
});
|
||||||
|
}
|
||||||
26
packages/nest/src/schematics/library/schema.d.ts
vendored
Normal file
26
packages/nest/src/schematics/library/schema.d.ts
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { Linter } from '@nrwl/workspace';
|
||||||
|
|
||||||
|
export interface Schema {
|
||||||
|
name: string;
|
||||||
|
directory?: string;
|
||||||
|
skipTsConfig: boolean;
|
||||||
|
skipFormat: boolean;
|
||||||
|
tags?: string;
|
||||||
|
unitTestRunner: 'jest' | 'none';
|
||||||
|
linter: Linter;
|
||||||
|
publishable?: boolean;
|
||||||
|
global?: boolean;
|
||||||
|
service?: boolean;
|
||||||
|
controller?: boolean;
|
||||||
|
target?:
|
||||||
|
| 'es5'
|
||||||
|
| 'es6'
|
||||||
|
| 'esnext'
|
||||||
|
| 'es2015'
|
||||||
|
| 'es2016'
|
||||||
|
| 'es2017'
|
||||||
|
| 'es2018'
|
||||||
|
| 'es2019'
|
||||||
|
| 'es2020';
|
||||||
|
testEnvironment: 'jsdom' | 'node';
|
||||||
|
}
|
||||||
97
packages/nest/src/schematics/library/schema.json
Normal file
97
packages/nest/src/schematics/library/schema.json
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/schema",
|
||||||
|
"id": "NxNestLibrary",
|
||||||
|
"title": "Create a Nest Library for Nx",
|
||||||
|
"type": "object",
|
||||||
|
"examples": [
|
||||||
|
{
|
||||||
|
"command": "g lib mylib --directory=myapp",
|
||||||
|
"description": "Generate libs/myapp/mylib"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Library name",
|
||||||
|
"$default": {
|
||||||
|
"$source": "argv",
|
||||||
|
"index": 0
|
||||||
|
},
|
||||||
|
"x-prompt": "What name would you like to use for the library?"
|
||||||
|
},
|
||||||
|
"directory": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A directory where the app is placed",
|
||||||
|
"alias": "d"
|
||||||
|
},
|
||||||
|
"linter": {
|
||||||
|
"description": "The tool to use for running lint checks.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["eslint", "tslint"],
|
||||||
|
"default": "tslint"
|
||||||
|
},
|
||||||
|
"unitTestRunner": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["jest", "none"],
|
||||||
|
"description": "Test runner to use for unit tests",
|
||||||
|
"default": "jest"
|
||||||
|
},
|
||||||
|
"tags": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Add tags to the library (used for linting)",
|
||||||
|
"alias": "t"
|
||||||
|
},
|
||||||
|
"skipFormat": {
|
||||||
|
"description": "Skip formatting files",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"skipTsConfig": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"description": "Do not update tsconfig.json for development experience."
|
||||||
|
},
|
||||||
|
"publishable": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Create a publishable library. A \"build\" architect will be added for this project the workspace configuration."
|
||||||
|
},
|
||||||
|
"global": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Add the Global decorator to the generated module.",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"service": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Include a service with the library.",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"controller": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Include a controller with the library",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"testEnvironment": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["jsdom", "node"],
|
||||||
|
"description": "The test environment for jest, for node applications this should stay as node unless doing DOM testing.",
|
||||||
|
"default": "node"
|
||||||
|
},
|
||||||
|
"target": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The es target, Nest suggest using es6 or higher.",
|
||||||
|
"default": "es6",
|
||||||
|
"enum": [
|
||||||
|
"es5",
|
||||||
|
"es6",
|
||||||
|
"esnext",
|
||||||
|
"es2015",
|
||||||
|
"es2016",
|
||||||
|
"es2017",
|
||||||
|
"es2018",
|
||||||
|
"es2019",
|
||||||
|
"es2020"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["name"]
|
||||||
|
}
|
||||||
@ -9,4 +9,5 @@ export interface Schema {
|
|||||||
unitTestRunner: 'jest' | 'none';
|
unitTestRunner: 'jest' | 'none';
|
||||||
linter: Linter;
|
linter: Linter;
|
||||||
publishable?: boolean;
|
publishable?: boolean;
|
||||||
|
testEnvironment: 'jsdom' | 'node';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,6 +54,12 @@
|
|||||||
"publishable": {
|
"publishable": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Create a publishable library. A \"build\" architect will be added for this project the workspace configuration."
|
"description": "Create a publishable library. A \"build\" architect will be added for this project the workspace configuration."
|
||||||
|
},
|
||||||
|
"testEnvironment": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["jsdom", "node"],
|
||||||
|
"description": "The test environment to use if unitTestRunner is set to jest",
|
||||||
|
"default": "jsdom"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["name"]
|
"required": ["name"]
|
||||||
|
|||||||
@ -100,7 +100,8 @@ export default function(schema: Schema): Rule {
|
|||||||
project: options.name,
|
project: options.name,
|
||||||
setupFile: 'none',
|
setupFile: 'none',
|
||||||
supportTsx: true,
|
supportTsx: true,
|
||||||
skipSerializers: true
|
skipSerializers: true,
|
||||||
|
testEnvironment: options.testEnvironment
|
||||||
})
|
})
|
||||||
: noop(),
|
: noop(),
|
||||||
formatFiles(options)
|
formatFiles(options)
|
||||||
|
|||||||
@ -9,4 +9,5 @@ export interface Schema {
|
|||||||
simpleModuleName: boolean;
|
simpleModuleName: boolean;
|
||||||
unitTestRunner: 'jest' | 'none';
|
unitTestRunner: 'jest' | 'none';
|
||||||
linter: Linter;
|
linter: Linter;
|
||||||
|
testEnvironment: 'jsdom' | 'node';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,6 +48,12 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": false,
|
||||||
"description": "Do not update tsconfig.json for development experience."
|
"description": "Do not update tsconfig.json for development experience."
|
||||||
|
},
|
||||||
|
"testEnvironment": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["jsdom", "node"],
|
||||||
|
"description": "The test environment to use if unitTestRunner is set to jest",
|
||||||
|
"default": "jsdom"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["name"]
|
"required": ["name"]
|
||||||
|
|||||||
@ -253,7 +253,10 @@ function setDefaultLinter(linter: string) {
|
|||||||
plugin: { linter }
|
plugin: { linter }
|
||||||
};
|
};
|
||||||
json.schematics['@nrwl/nest'] = { application: { linter } };
|
json.schematics['@nrwl/nest'] = { application: { linter } };
|
||||||
json.schematics['@nrwl/express'] = { application: { linter } };
|
json.schematics['@nrwl/express'] = {
|
||||||
|
application: { linter },
|
||||||
|
library: { linter }
|
||||||
|
};
|
||||||
return json;
|
return json;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@ const gitMessage = require('child_process')
|
|||||||
.toString()
|
.toString()
|
||||||
.trim();
|
.trim();
|
||||||
|
|
||||||
const matchCommit = /(chore|feat|fix|cleanup|docs)\((angular|bazel|core|docs|nextjs|linter|node|nx-plugin|react|storybook|testing|repo|misc)\):\s(([a-z0-9:\-\s])+)/g.test(
|
const matchCommit = /(chore|feat|fix|cleanup|docs)\((angular|bazel|core|docs|nextjs|nest|linter|node|nx-plugin|react|storybook|testing|repo|misc)\):\s(([a-z0-9:\-\s])+)/g.test(
|
||||||
gitMessage
|
gitMessage
|
||||||
);
|
);
|
||||||
const matchRevert = /Revert/gi.test(gitMessage);
|
const matchRevert = /Revert/gi.test(gitMessage);
|
||||||
@ -27,7 +27,7 @@ if (exitCode === 0) {
|
|||||||
console.log('\n');
|
console.log('\n');
|
||||||
console.log('possible types: chore|build|feat|fix|cleanup|docs');
|
console.log('possible types: chore|build|feat|fix|cleanup|docs');
|
||||||
console.log(
|
console.log(
|
||||||
'possible scopes: angular|bazel|core|docs|nextjs|linter|node|react|storybook|testing|repo|misc (if unsure use "core")'
|
'possible scopes: angular|bazel|core|docs|nextjs|nest|linter|linter|node|react|storybook|testing|repo|misc (if unsure use "core")'
|
||||||
);
|
);
|
||||||
console.log(
|
console.log(
|
||||||
'\nEXAMPLE: \n' +
|
'\nEXAMPLE: \n' +
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user