feat(linter): add explicit file extension to config files (#3847)
* feat(linter): add explicit file extension to config files * feat(linter): update references to .eslintrc for new projects * fix(linter): fix quotes in global eslint config
This commit is contained in:
parent
b45734b1d2
commit
e339ece224
@ -44,7 +44,7 @@ happynrwl/
|
|||||||
│ │ ├── jest.conf.js
|
│ │ ├── jest.conf.js
|
||||||
│ │ ├── tsconfig.json
|
│ │ ├── tsconfig.json
|
||||||
│ │ ├── tsconfig.spec.json
|
│ │ ├── tsconfig.spec.json
|
||||||
│ │ └── .eslintrc
|
│ │ └── .eslintrc.json
|
||||||
│ └── tuskdesk-e2e/
|
│ └── tuskdesk-e2e/
|
||||||
│ │ ├── src/
|
│ │ ├── src/
|
||||||
│ │ │ ├── integrations/
|
│ │ │ ├── integrations/
|
||||||
@ -54,14 +54,14 @@ happynrwl/
|
|||||||
│ │ │ └── support/
|
│ │ │ └── support/
|
||||||
│ │ ├── cypress.json
|
│ │ ├── cypress.json
|
||||||
│ │ ├── tsconfig.e2e.json
|
│ │ ├── tsconfig.e2e.json
|
||||||
│ │ └── .eslintrc
|
│ │ └── .eslintrc.json
|
||||||
├── libs/
|
├── libs/
|
||||||
├── workspace.json
|
├── workspace.json
|
||||||
├── nx.json
|
├── nx.json
|
||||||
├── package.json
|
├── package.json
|
||||||
├── tools/
|
├── tools/
|
||||||
├── tsconfig.json
|
├── tsconfig.json
|
||||||
└── .eslintrc
|
└── .eslintrc.json
|
||||||
```
|
```
|
||||||
|
|
||||||
Run:
|
Run:
|
||||||
|
|||||||
@ -167,7 +167,7 @@ Read more about workspace schematics in the Workspace Schematics guide.
|
|||||||
|
|
||||||
### Workspace Lint Checks
|
### Workspace Lint Checks
|
||||||
|
|
||||||
Custom lint checks is another great way to enforce best practices. We can create custom lint checks in the `tools/lint` directory and then register them in `tslint.json`or `.eslintrc`.
|
Custom lint checks is another great way to enforce best practices. We can create custom lint checks in the `tools/lint` directory and then register them in `tslint.json`or `.eslintrc.json`.
|
||||||
|
|
||||||
## Developer Workflow
|
## Developer Workflow
|
||||||
|
|
||||||
|
|||||||
@ -51,7 +51,7 @@ First, use `nx.json` to annotate your projects with tags. In this example, we wi
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Next open the top-level `.eslintrc` or `tslint.json` to add the constraints.
|
Next open the top-level `.eslintrc.json` or `tslint.json` to add the constraints.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|||||||
@ -38,7 +38,7 @@ myorg/
|
|||||||
│ │ ├── jest.conf.js
|
│ │ ├── jest.conf.js
|
||||||
│ │ ├── tsconfig.json
|
│ │ ├── tsconfig.json
|
||||||
│ │ ├── tsconfig.spec.json
|
│ │ ├── tsconfig.spec.json
|
||||||
│ │ └── .eslintrc
|
│ │ └── .eslintrc.json
|
||||||
│ └── myapp-e2e/
|
│ └── myapp-e2e/
|
||||||
│ │ ├── src/
|
│ │ ├── src/
|
||||||
│ │ │ ├── integrations/
|
│ │ │ ├── integrations/
|
||||||
@ -48,14 +48,14 @@ myorg/
|
|||||||
│ │ │ └── support/
|
│ │ │ └── support/
|
||||||
│ │ ├── cypress.json
|
│ │ ├── cypress.json
|
||||||
│ │ ├── tsconfig.e2e.json
|
│ │ ├── tsconfig.e2e.json
|
||||||
│ │ └── .eslintrc
|
│ │ └── .eslintrc.json
|
||||||
├── libs/
|
├── libs/
|
||||||
├── workspace.json
|
├── workspace.json
|
||||||
├── nx.json
|
├── nx.json
|
||||||
├── package.json
|
├── package.json
|
||||||
├── tools/
|
├── tools/
|
||||||
├── tsconfig.json
|
├── tsconfig.json
|
||||||
└── .eslintrc
|
└── .eslintrc.json
|
||||||
```
|
```
|
||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|||||||
@ -18,9 +18,9 @@ forEachCli('nx', () => {
|
|||||||
|
|
||||||
runCLI(`generate @nrwl/react:app ${myapp}`);
|
runCLI(`generate @nrwl/react:app ${myapp}`);
|
||||||
|
|
||||||
const eslintrc = readJson('.eslintrc');
|
const eslintrc = readJson('.eslintrc.json');
|
||||||
eslintrc.rules['no-console'] = 'error';
|
eslintrc.rules['no-console'] = 'error';
|
||||||
updateFile('.eslintrc', JSON.stringify(eslintrc, null, 2));
|
updateFile('.eslintrc.json', JSON.stringify(eslintrc, null, 2));
|
||||||
|
|
||||||
updateFile(`apps/${myapp}/src/main.ts`, `console.log("should fail");`);
|
updateFile(`apps/${myapp}/src/main.ts`, `console.log("should fail");`);
|
||||||
|
|
||||||
@ -34,9 +34,9 @@ forEachCli('nx', () => {
|
|||||||
|
|
||||||
runCLI(`generate @nrwl/react:app ${myapp}`);
|
runCLI(`generate @nrwl/react:app ${myapp}`);
|
||||||
|
|
||||||
const eslintrc = readJson('.eslintrc');
|
const eslintrc = readJson('.eslintrc.json');
|
||||||
eslintrc.rules['no-console'] = 'error';
|
eslintrc.rules['no-console'] = 'error';
|
||||||
updateFile('.eslintrc', JSON.stringify(eslintrc, null, 2));
|
updateFile('.eslintrc.json', JSON.stringify(eslintrc, null, 2));
|
||||||
|
|
||||||
updateFile(`apps/${myapp}/src/main.ts`, `console.log("should fail");`);
|
updateFile(`apps/${myapp}/src/main.ts`, `console.log("should fail");`);
|
||||||
|
|
||||||
@ -49,9 +49,9 @@ forEachCli('nx', () => {
|
|||||||
|
|
||||||
runCLI(`generate @nrwl/react:app ${myapp}`);
|
runCLI(`generate @nrwl/react:app ${myapp}`);
|
||||||
|
|
||||||
const eslintrc = readJson('.eslintrc');
|
const eslintrc = readJson('.eslintrc.json');
|
||||||
eslintrc.rules['no-console'] = undefined;
|
eslintrc.rules['no-console'] = undefined;
|
||||||
updateFile('.eslintrc', JSON.stringify(eslintrc, null, 2));
|
updateFile('.eslintrc.json', JSON.stringify(eslintrc, null, 2));
|
||||||
|
|
||||||
updateFile(`apps/${myapp}/src/main.ts`, `console.log("should fail");`);
|
updateFile(`apps/${myapp}/src/main.ts`, `console.log("should fail");`);
|
||||||
|
|
||||||
@ -81,9 +81,9 @@ forEachCli('nx', () => {
|
|||||||
};
|
};
|
||||||
updateFile('workspace.json', JSON.stringify(workspaceJson, null, 2));
|
updateFile('workspace.json', JSON.stringify(workspaceJson, null, 2));
|
||||||
|
|
||||||
const eslintrc = readJson('.eslintrc');
|
const eslintrc = readJson('.eslintrc.json');
|
||||||
eslintrc.rules['no-console'] = undefined;
|
eslintrc.rules['no-console'] = undefined;
|
||||||
updateFile('.eslintrc', JSON.stringify(eslintrc, null, 2));
|
updateFile('.eslintrc.json', JSON.stringify(eslintrc, null, 2));
|
||||||
|
|
||||||
updateFile(`apps/${myapp}/src/main.ts`, `console.log("should fail");`);
|
updateFile(`apps/${myapp}/src/main.ts`, `console.log("should fail");`);
|
||||||
|
|
||||||
@ -129,9 +129,9 @@ forEachCli('nx', () => {
|
|||||||
|
|
||||||
runCLI(`generate @nrwl/react:app ${myapp}`);
|
runCLI(`generate @nrwl/react:app ${myapp}`);
|
||||||
|
|
||||||
const eslintrc = readJson('.eslintrc');
|
const eslintrc = readJson('.eslintrc.json');
|
||||||
eslintrc.rules['no-console'] = 'error';
|
eslintrc.rules['no-console'] = 'error';
|
||||||
updateFile('.eslintrc', JSON.stringify(eslintrc, null, 2));
|
updateFile('.eslintrc.json', JSON.stringify(eslintrc, null, 2));
|
||||||
updateFile(`apps/${myapp}/src/main.ts`, `console.log("should fail");`);
|
updateFile(`apps/${myapp}/src/main.ts`, `console.log("should fail");`);
|
||||||
|
|
||||||
const outputFile = 'a/b/c/lint-output.json';
|
const outputFile = 'a/b/c/lint-output.json';
|
||||||
@ -167,9 +167,12 @@ forEachCli('nx', () => {
|
|||||||
|
|
||||||
runCLI(`generate @nrwl/react:app ${myapp}`);
|
runCLI(`generate @nrwl/react:app ${myapp}`);
|
||||||
|
|
||||||
const eslintrc = readJson(`apps/${myapp}/.eslintrc`);
|
const eslintrc = readJson(`apps/${myapp}/.eslintrc.json`);
|
||||||
eslintrc.rules['no-console'] = 'warn';
|
eslintrc.rules['no-console'] = 'warn';
|
||||||
updateFile(`apps/${myapp}/.eslintrc`, JSON.stringify(eslintrc, null, 2));
|
updateFile(
|
||||||
|
`apps/${myapp}/.eslintrc.json`,
|
||||||
|
JSON.stringify(eslintrc, null, 2)
|
||||||
|
);
|
||||||
updateFile(
|
updateFile(
|
||||||
`apps/${myapp}/src/main.ts`,
|
`apps/${myapp}/src/main.ts`,
|
||||||
`console.log('once'); console.log('twice');`
|
`console.log('once'); console.log('twice');`
|
||||||
|
|||||||
@ -246,7 +246,7 @@ describe('schematic:cypress-project', () => {
|
|||||||
const packageJson = readJsonInTree(tree, 'package.json');
|
const packageJson = readJsonInTree(tree, 'package.json');
|
||||||
const eslintrcJson = readJsonInTree(
|
const eslintrcJson = readJsonInTree(
|
||||||
tree,
|
tree,
|
||||||
'apps/my-app-e2e/.eslintrc'
|
'apps/my-app-e2e/.eslintrc.json'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
|
|||||||
@ -9,6 +9,11 @@
|
|||||||
"version": "10.3.0-beta.0",
|
"version": "10.3.0-beta.0",
|
||||||
"description": "Migrate to the new ESLint builder and ESLint config style",
|
"description": "Migrate to the new ESLint builder and ESLint config style",
|
||||||
"factory": "./src/migrations/update-10-3-0/update-eslint-builder-and-config"
|
"factory": "./src/migrations/update-10-3-0/update-eslint-builder-and-config"
|
||||||
|
},
|
||||||
|
"add-json-ext-to-eslintrc": {
|
||||||
|
"version": "10.3.0-beta.2",
|
||||||
|
"description": "Add explicit .json file extension to .eslintrc files, not using an extension is deprecated",
|
||||||
|
"factory": "./src/migrations/update-10-3-0/add-json-ext-to-eslintrc"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packageJsonUpdates": {
|
"packageJsonUpdates": {
|
||||||
|
|||||||
@ -39,7 +39,7 @@ function createValidRunBuilderOptions(
|
|||||||
): Schema {
|
): Schema {
|
||||||
return {
|
return {
|
||||||
lintFilePatterns: [],
|
lintFilePatterns: [],
|
||||||
eslintConfig: './.eslintrc',
|
eslintConfig: './.eslintrc.json',
|
||||||
fix: true,
|
fix: true,
|
||||||
cache: true,
|
cache: true,
|
||||||
cacheLocation: 'cacheLocation1',
|
cacheLocation: 'cacheLocation1',
|
||||||
@ -118,7 +118,7 @@ describe('Linter Builder', () => {
|
|||||||
await runBuilder(
|
await runBuilder(
|
||||||
createValidRunBuilderOptions({
|
createValidRunBuilderOptions({
|
||||||
lintFilePatterns: [],
|
lintFilePatterns: [],
|
||||||
eslintConfig: './.eslintrc',
|
eslintConfig: './.eslintrc.json',
|
||||||
fix: true,
|
fix: true,
|
||||||
cache: true,
|
cache: true,
|
||||||
cacheLocation: 'cacheLocation1',
|
cacheLocation: 'cacheLocation1',
|
||||||
@ -131,9 +131,9 @@ describe('Linter Builder', () => {
|
|||||||
quiet: false,
|
quiet: false,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(lint).toHaveBeenCalledWith('/root/.eslintrc', {
|
expect(lint).toHaveBeenCalledWith('/root/.eslintrc.json', {
|
||||||
lintFilePatterns: [],
|
lintFilePatterns: [],
|
||||||
eslintConfig: './.eslintrc',
|
eslintConfig: './.eslintrc.json',
|
||||||
fix: true,
|
fix: true,
|
||||||
cache: true,
|
cache: true,
|
||||||
cacheLocation: 'cacheLocation1',
|
cacheLocation: 'cacheLocation1',
|
||||||
@ -164,7 +164,7 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
await runBuilder(
|
await runBuilder(
|
||||||
createValidRunBuilderOptions({
|
createValidRunBuilderOptions({
|
||||||
eslintConfig: './.eslintrc',
|
eslintConfig: './.eslintrc.json',
|
||||||
lintFilePatterns: ['includedFile1'],
|
lintFilePatterns: ['includedFile1'],
|
||||||
format: 'json',
|
format: 'json',
|
||||||
})
|
})
|
||||||
@ -172,7 +172,7 @@ describe('Linter Builder', () => {
|
|||||||
expect(mockLoadFormatter).toHaveBeenCalledWith('json');
|
expect(mockLoadFormatter).toHaveBeenCalledWith('json');
|
||||||
await runBuilder(
|
await runBuilder(
|
||||||
createValidRunBuilderOptions({
|
createValidRunBuilderOptions({
|
||||||
eslintConfig: './.eslintrc',
|
eslintConfig: './.eslintrc.json',
|
||||||
lintFilePatterns: ['includedFile1'],
|
lintFilePatterns: ['includedFile1'],
|
||||||
format: 'html',
|
format: 'html',
|
||||||
})
|
})
|
||||||
@ -184,7 +184,7 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
await runBuilder(
|
await runBuilder(
|
||||||
createValidRunBuilderOptions({
|
createValidRunBuilderOptions({
|
||||||
eslintConfig: './.eslintrc',
|
eslintConfig: './.eslintrc.json',
|
||||||
lintFilePatterns: ['includedFile1'],
|
lintFilePatterns: ['includedFile1'],
|
||||||
format: 'json',
|
format: 'json',
|
||||||
fix: false,
|
fix: false,
|
||||||
@ -212,7 +212,7 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
await runBuilder(
|
await runBuilder(
|
||||||
createValidRunBuilderOptions({
|
createValidRunBuilderOptions({
|
||||||
eslintConfig: './.eslintrc',
|
eslintConfig: './.eslintrc.json',
|
||||||
lintFilePatterns: ['includedFile1'],
|
lintFilePatterns: ['includedFile1'],
|
||||||
format: 'json',
|
format: 'json',
|
||||||
silent: false,
|
silent: false,
|
||||||
@ -255,7 +255,7 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
await runBuilder(
|
await runBuilder(
|
||||||
createValidRunBuilderOptions({
|
createValidRunBuilderOptions({
|
||||||
eslintConfig: './.eslintrc',
|
eslintConfig: './.eslintrc.json',
|
||||||
lintFilePatterns: ['includedFile1'],
|
lintFilePatterns: ['includedFile1'],
|
||||||
format: 'json',
|
format: 'json',
|
||||||
silent: false,
|
silent: false,
|
||||||
@ -303,7 +303,7 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
await runBuilder(
|
await runBuilder(
|
||||||
createValidRunBuilderOptions({
|
createValidRunBuilderOptions({
|
||||||
eslintConfig: './.eslintrc',
|
eslintConfig: './.eslintrc.json',
|
||||||
lintFilePatterns: ['includedFile1'],
|
lintFilePatterns: ['includedFile1'],
|
||||||
format: 'json',
|
format: 'json',
|
||||||
silent: true,
|
silent: true,
|
||||||
@ -347,7 +347,7 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
const output = await runBuilder(
|
const output = await runBuilder(
|
||||||
createValidRunBuilderOptions({
|
createValidRunBuilderOptions({
|
||||||
eslintConfig: './.eslintrc',
|
eslintConfig: './.eslintrc.json',
|
||||||
lintFilePatterns: ['includedFile1'],
|
lintFilePatterns: ['includedFile1'],
|
||||||
format: 'json',
|
format: 'json',
|
||||||
silent: true,
|
silent: true,
|
||||||
@ -375,7 +375,7 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
const output = await runBuilder(
|
const output = await runBuilder(
|
||||||
createValidRunBuilderOptions({
|
createValidRunBuilderOptions({
|
||||||
eslintConfig: './.eslintrc',
|
eslintConfig: './.eslintrc.json',
|
||||||
lintFilePatterns: ['includedFile1'],
|
lintFilePatterns: ['includedFile1'],
|
||||||
format: 'json',
|
format: 'json',
|
||||||
silent: true,
|
silent: true,
|
||||||
@ -403,7 +403,7 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
const output = await runBuilder(
|
const output = await runBuilder(
|
||||||
createValidRunBuilderOptions({
|
createValidRunBuilderOptions({
|
||||||
eslintConfig: './.eslintrc',
|
eslintConfig: './.eslintrc.json',
|
||||||
lintFilePatterns: ['includedFile1'],
|
lintFilePatterns: ['includedFile1'],
|
||||||
format: 'json',
|
format: 'json',
|
||||||
silent: true,
|
silent: true,
|
||||||
@ -422,7 +422,7 @@ describe('Linter Builder', () => {
|
|||||||
const { createDirectory } = require('@nrwl/workspace');
|
const { createDirectory } = require('@nrwl/workspace');
|
||||||
await runBuilder(
|
await runBuilder(
|
||||||
createValidRunBuilderOptions({
|
createValidRunBuilderOptions({
|
||||||
eslintConfig: './.eslintrc',
|
eslintConfig: './.eslintrc.json',
|
||||||
lintFilePatterns: ['includedFile1'],
|
lintFilePatterns: ['includedFile1'],
|
||||||
format: 'json',
|
format: 'json',
|
||||||
silent: true,
|
silent: true,
|
||||||
@ -442,7 +442,7 @@ describe('Linter Builder', () => {
|
|||||||
jest.spyOn(fs, 'writeFileSync').mockImplementation();
|
jest.spyOn(fs, 'writeFileSync').mockImplementation();
|
||||||
await runBuilder(
|
await runBuilder(
|
||||||
createValidRunBuilderOptions({
|
createValidRunBuilderOptions({
|
||||||
eslintConfig: './.eslintrc',
|
eslintConfig: './.eslintrc.json',
|
||||||
lintFilePatterns: ['includedFile1'],
|
lintFilePatterns: ['includedFile1'],
|
||||||
format: 'json',
|
format: 'json',
|
||||||
silent: true,
|
silent: true,
|
||||||
|
|||||||
@ -40,7 +40,7 @@ async function run(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* We want users to have the option of not specifying the config path, and let
|
* We want users to have the option of not specifying the config path, and let
|
||||||
* eslint automatically resolve the `.eslintrc` files in each folder.
|
* eslint automatically resolve the `.eslintrc.json` files in each folder.
|
||||||
*/
|
*/
|
||||||
const eslintConfigPath = options.eslintConfig
|
const eslintConfigPath = options.eslintConfig
|
||||||
? path.resolve(systemRoot, options.eslintConfig)
|
? path.resolve(systemRoot, options.eslintConfig)
|
||||||
|
|||||||
@ -18,14 +18,14 @@ describe('eslint-utils', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should create the ESLint instance with the proper parameters', async () => {
|
it('should create the ESLint instance with the proper parameters', async () => {
|
||||||
await lint('./.eslintrc', <any>{
|
await lint('./.eslintrc.json', <any>{
|
||||||
fix: true,
|
fix: true,
|
||||||
cache: true,
|
cache: true,
|
||||||
cacheLocation: '/root/cache',
|
cacheLocation: '/root/cache',
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
|
|
||||||
expect(ESLint).toHaveBeenCalledWith({
|
expect(ESLint).toHaveBeenCalledWith({
|
||||||
overrideConfigFile: './.eslintrc',
|
overrideConfigFile: './.eslintrc.json',
|
||||||
fix: true,
|
fix: true,
|
||||||
cache: true,
|
cache: true,
|
||||||
cacheLocation: '/root/cache',
|
cacheLocation: '/root/cache',
|
||||||
|
|||||||
@ -75,7 +75,7 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
const result = runBuilder({
|
const result = runBuilder({
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
files: [],
|
files: [],
|
||||||
});
|
});
|
||||||
await expect(result).rejects.toThrow(
|
await expect(result).rejects.toThrow(
|
||||||
@ -88,7 +88,7 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
const result = runBuilder({
|
const result = runBuilder({
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
files: [],
|
files: [],
|
||||||
});
|
});
|
||||||
await expect(result).resolves.not.toThrow();
|
await expect(result).resolves.not.toThrow();
|
||||||
@ -97,7 +97,7 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
const result = runBuilder({
|
const result = runBuilder({
|
||||||
linter: 'tslint',
|
linter: 'tslint',
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
files: [],
|
files: [],
|
||||||
});
|
});
|
||||||
await expect(result).rejects.toThrow(
|
await expect(result).rejects.toThrow(
|
||||||
@ -112,7 +112,7 @@ describe('Linter Builder', () => {
|
|||||||
const { createProgram } = require('./utility/ts-utils');
|
const { createProgram } = require('./utility/ts-utils');
|
||||||
await runBuilder({
|
await runBuilder({
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
tsConfig: './tsconfig.json',
|
tsConfig: './tsconfig.json',
|
||||||
});
|
});
|
||||||
expect(createProgram).toHaveBeenCalledTimes(1);
|
expect(createProgram).toHaveBeenCalledTimes(1);
|
||||||
@ -120,7 +120,7 @@ describe('Linter Builder', () => {
|
|||||||
expect(lint).toHaveBeenCalledTimes(1);
|
expect(lint).toHaveBeenCalledTimes(1);
|
||||||
expect(lint).toHaveBeenCalledWith(
|
expect(lint).toHaveBeenCalledWith(
|
||||||
'/root',
|
'/root',
|
||||||
'/root/.eslintrc',
|
'/root/.eslintrc.json',
|
||||||
expect.anything(),
|
expect.anything(),
|
||||||
expect.any(Set),
|
expect.any(Set),
|
||||||
'/root/tsconfig.json-program',
|
'/root/tsconfig.json-program',
|
||||||
@ -133,7 +133,7 @@ describe('Linter Builder', () => {
|
|||||||
const { createProgram } = require('./utility/ts-utils');
|
const { createProgram } = require('./utility/ts-utils');
|
||||||
await runBuilder({
|
await runBuilder({
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
tsConfig: ['./tsconfig.json', './tsconfig2.json'],
|
tsConfig: ['./tsconfig.json', './tsconfig2.json'],
|
||||||
});
|
});
|
||||||
expect(createProgram).toHaveBeenCalledTimes(2);
|
expect(createProgram).toHaveBeenCalledTimes(2);
|
||||||
@ -143,7 +143,7 @@ describe('Linter Builder', () => {
|
|||||||
expect(lint).toHaveBeenNthCalledWith(
|
expect(lint).toHaveBeenNthCalledWith(
|
||||||
1,
|
1,
|
||||||
'/root',
|
'/root',
|
||||||
'/root/.eslintrc',
|
'/root/.eslintrc.json',
|
||||||
expect.anything(),
|
expect.anything(),
|
||||||
expect.any(Set),
|
expect.any(Set),
|
||||||
'/root/tsconfig.json-program',
|
'/root/tsconfig.json-program',
|
||||||
@ -152,7 +152,7 @@ describe('Linter Builder', () => {
|
|||||||
expect(lint).toHaveBeenNthCalledWith(
|
expect(lint).toHaveBeenNthCalledWith(
|
||||||
2,
|
2,
|
||||||
'/root',
|
'/root',
|
||||||
'/root/.eslintrc',
|
'/root/.eslintrc.json',
|
||||||
expect.anything(),
|
expect.anything(),
|
||||||
expect.any(Set),
|
expect.any(Set),
|
||||||
'/root/tsconfig2.json-program',
|
'/root/tsconfig2.json-program',
|
||||||
@ -165,14 +165,14 @@ describe('Linter Builder', () => {
|
|||||||
const { createProgram } = require('./utility/ts-utils');
|
const { createProgram } = require('./utility/ts-utils');
|
||||||
await runBuilder({
|
await runBuilder({
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
files: [],
|
files: [],
|
||||||
});
|
});
|
||||||
expect(createProgram).not.toHaveBeenCalled();
|
expect(createProgram).not.toHaveBeenCalled();
|
||||||
expect(lint).toHaveBeenCalledTimes(1);
|
expect(lint).toHaveBeenCalledTimes(1);
|
||||||
expect(lint).toHaveBeenCalledWith(
|
expect(lint).toHaveBeenCalledWith(
|
||||||
'/root',
|
'/root',
|
||||||
'/root/.eslintrc',
|
'/root/.eslintrc.json',
|
||||||
expect.anything(),
|
expect.anything(),
|
||||||
expect.any(Set)
|
expect.any(Set)
|
||||||
);
|
);
|
||||||
@ -184,7 +184,7 @@ describe('Linter Builder', () => {
|
|||||||
const { lint } = require('./utility/eslint-utils');
|
const { lint } = require('./utility/eslint-utils');
|
||||||
await runBuilder({
|
await runBuilder({
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
files: ['includedFile1'],
|
files: ['includedFile1'],
|
||||||
exclude: ['excludedFile1'],
|
exclude: ['excludedFile1'],
|
||||||
fix: true,
|
fix: true,
|
||||||
@ -195,7 +195,7 @@ describe('Linter Builder', () => {
|
|||||||
expect.anything(),
|
expect.anything(),
|
||||||
expect.anything(),
|
expect.anything(),
|
||||||
{
|
{
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
files: ['includedFile1'],
|
files: ['includedFile1'],
|
||||||
exclude: ['excludedFile1'],
|
exclude: ['excludedFile1'],
|
||||||
fix: true,
|
fix: true,
|
||||||
@ -219,7 +219,7 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
const result = runBuilder({
|
const result = runBuilder({
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
files: ['includedFile1'],
|
files: ['includedFile1'],
|
||||||
});
|
});
|
||||||
await expect(result).rejects.toThrow(
|
await expect(result).rejects.toThrow(
|
||||||
@ -230,14 +230,14 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
await runBuilder({
|
await runBuilder({
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
files: ['includedFile1'],
|
files: ['includedFile1'],
|
||||||
format: 'json',
|
format: 'json',
|
||||||
});
|
});
|
||||||
expect(mockGetFormatter).toHaveBeenCalledWith('json');
|
expect(mockGetFormatter).toHaveBeenCalledWith('json');
|
||||||
await runBuilder({
|
await runBuilder({
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
files: ['includedFile1'],
|
files: ['includedFile1'],
|
||||||
format: 'html',
|
format: 'html',
|
||||||
});
|
});
|
||||||
@ -247,7 +247,7 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
await runBuilder({
|
await runBuilder({
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
files: ['includedFile1'],
|
files: ['includedFile1'],
|
||||||
format: 'json',
|
format: 'json',
|
||||||
fix: false,
|
fix: false,
|
||||||
@ -274,7 +274,7 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
await runBuilder({
|
await runBuilder({
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
files: ['includedFile1'],
|
files: ['includedFile1'],
|
||||||
format: 'json',
|
format: 'json',
|
||||||
silent: false,
|
silent: false,
|
||||||
@ -315,7 +315,7 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
const output = await runBuilder({
|
const output = await runBuilder({
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
files: ['includedFile1'],
|
files: ['includedFile1'],
|
||||||
format: 'json',
|
format: 'json',
|
||||||
silent: false,
|
silent: false,
|
||||||
@ -353,7 +353,7 @@ describe('Linter Builder', () => {
|
|||||||
const { createDirectory } = require('@nrwl/workspace');
|
const { createDirectory } = require('@nrwl/workspace');
|
||||||
await runBuilder({
|
await runBuilder({
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
files: ['includedFile1'],
|
files: ['includedFile1'],
|
||||||
outputFile: 'a/b/c/outputFile1',
|
outputFile: 'a/b/c/outputFile1',
|
||||||
});
|
});
|
||||||
@ -368,7 +368,7 @@ describe('Linter Builder', () => {
|
|||||||
jest.spyOn(fs, 'writeFileSync').mockImplementation();
|
jest.spyOn(fs, 'writeFileSync').mockImplementation();
|
||||||
await runBuilder({
|
await runBuilder({
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
files: ['includedFile1'],
|
files: ['includedFile1'],
|
||||||
});
|
});
|
||||||
expect(fs.writeFileSync).not.toHaveBeenCalled();
|
expect(fs.writeFileSync).not.toHaveBeenCalled();
|
||||||
@ -391,7 +391,7 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
const output = await runBuilder({
|
const output = await runBuilder({
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
files: ['includedFile1'],
|
files: ['includedFile1'],
|
||||||
format: 'json',
|
format: 'json',
|
||||||
silent: true,
|
silent: true,
|
||||||
@ -434,7 +434,7 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
const output = await runBuilder({
|
const output = await runBuilder({
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
files: ['includedFile1'],
|
files: ['includedFile1'],
|
||||||
format: 'json',
|
format: 'json',
|
||||||
silent: true,
|
silent: true,
|
||||||
@ -459,7 +459,7 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
const output = await runBuilder({
|
const output = await runBuilder({
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
files: ['includedFile1'],
|
files: ['includedFile1'],
|
||||||
format: 'json',
|
format: 'json',
|
||||||
silent: true,
|
silent: true,
|
||||||
@ -485,7 +485,7 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
const output = await runBuilder({
|
const output = await runBuilder({
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
files: ['includedFile1'],
|
files: ['includedFile1'],
|
||||||
format: 'json',
|
format: 'json',
|
||||||
silent: true,
|
silent: true,
|
||||||
@ -511,7 +511,7 @@ describe('Linter Builder', () => {
|
|||||||
setupMocks();
|
setupMocks();
|
||||||
const output = await runBuilder({
|
const output = await runBuilder({
|
||||||
linter: 'eslint',
|
linter: 'eslint',
|
||||||
config: './.eslintrc',
|
config: './.eslintrc.json',
|
||||||
files: ['includedFile1'],
|
files: ['includedFile1'],
|
||||||
format: 'json',
|
format: 'json',
|
||||||
silent: true,
|
silent: true,
|
||||||
|
|||||||
@ -42,7 +42,7 @@ async function run(options: Schema, context: BuilderContext): Promise<any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We want users to have the option of not specifying the config path, and let
|
// We want users to have the option of not specifying the config path, and let
|
||||||
// eslint automatically resolve the `.eslintrc` files in each folder.
|
// eslint automatically resolve the `.eslintrc.json` files in each folder.
|
||||||
const eslintConfigPath = options.config
|
const eslintConfigPath = options.config
|
||||||
? path.resolve(systemRoot, options.config)
|
? path.resolve(systemRoot, options.config)
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|||||||
@ -31,7 +31,7 @@ describe('eslint-util', () => {
|
|||||||
const lintedFiles = new Set();
|
const lintedFiles = new Set();
|
||||||
await lint(
|
await lint(
|
||||||
'/root',
|
'/root',
|
||||||
'./.eslintrc',
|
'./.eslintrc.json',
|
||||||
<any>{ foo: 'bar' },
|
<any>{ foo: 'bar' },
|
||||||
lintedFiles,
|
lintedFiles,
|
||||||
'ts-program'
|
'ts-program'
|
||||||
@ -46,13 +46,13 @@ describe('eslint-util', () => {
|
|||||||
const lintedFiles = new Set();
|
const lintedFiles = new Set();
|
||||||
await lint(
|
await lint(
|
||||||
'/root',
|
'/root',
|
||||||
'./.eslintrc',
|
'./.eslintrc.json',
|
||||||
<any>{ fix: true, cache: true, cacheLocation: '/root/cache' },
|
<any>{ fix: true, cache: true, cacheLocation: '/root/cache' },
|
||||||
lintedFiles,
|
lintedFiles,
|
||||||
'ts-program'
|
'ts-program'
|
||||||
).catch(() => {});
|
).catch(() => {});
|
||||||
expect(CLIEngine).toHaveBeenCalledWith({
|
expect(CLIEngine).toHaveBeenCalledWith({
|
||||||
configFile: './.eslintrc',
|
configFile: './.eslintrc.json',
|
||||||
fix: true,
|
fix: true,
|
||||||
cache: true,
|
cache: true,
|
||||||
cacheLocation: '/root/cache',
|
cacheLocation: '/root/cache',
|
||||||
@ -72,7 +72,7 @@ describe('eslint-util', () => {
|
|||||||
lintedFiles.add('file4');
|
lintedFiles.add('file4');
|
||||||
const reports = await lint(
|
const reports = await lint(
|
||||||
'/root',
|
'/root',
|
||||||
'./.eslintrc',
|
'./.eslintrc.json',
|
||||||
<any>{ foo: 'bar' },
|
<any>{ foo: 'bar' },
|
||||||
lintedFiles
|
lintedFiles
|
||||||
);
|
);
|
||||||
@ -91,7 +91,7 @@ describe('eslint-util', () => {
|
|||||||
const lintedFiles = new Set();
|
const lintedFiles = new Set();
|
||||||
const lintPromise = lint(
|
const lintPromise = lint(
|
||||||
'/root',
|
'/root',
|
||||||
'./.eslintrc',
|
'./.eslintrc.json',
|
||||||
<any>{ tsConfig: 'my-ts-project' },
|
<any>{ tsConfig: 'my-ts-project' },
|
||||||
lintedFiles,
|
lintedFiles,
|
||||||
program,
|
program,
|
||||||
@ -114,7 +114,7 @@ describe('eslint-util', () => {
|
|||||||
const lintedFiles = new Set();
|
const lintedFiles = new Set();
|
||||||
const lintPromise = lint(
|
const lintPromise = lint(
|
||||||
'/root',
|
'/root',
|
||||||
'./.eslintrc',
|
'./.eslintrc.json',
|
||||||
<any>{ tsConfig: 'my-ts-project' },
|
<any>{ tsConfig: 'my-ts-project' },
|
||||||
lintedFiles,
|
lintedFiles,
|
||||||
program,
|
program,
|
||||||
|
|||||||
@ -0,0 +1,115 @@
|
|||||||
|
import { Tree } from '@angular-devkit/schematics';
|
||||||
|
import {
|
||||||
|
readJsonInTree,
|
||||||
|
readWorkspace,
|
||||||
|
updateJsonInTree,
|
||||||
|
updateWorkspace,
|
||||||
|
} from '@nrwl/workspace';
|
||||||
|
import { callRule, createEmptyWorkspace } from '@nrwl/workspace/testing';
|
||||||
|
import { runMigration } from '../../utils/testing';
|
||||||
|
|
||||||
|
describe('Add explicit .json file extension to .eslintrc files', () => {
|
||||||
|
let tree: Tree;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
tree = Tree.empty();
|
||||||
|
tree = createEmptyWorkspace(tree);
|
||||||
|
tree = await callRule(
|
||||||
|
updateJsonInTree('.eslintrc', () => ({})),
|
||||||
|
tree
|
||||||
|
);
|
||||||
|
tree = await callRule(
|
||||||
|
updateWorkspace((workspace) => {
|
||||||
|
// Old linter builder with ESLint, with explicit config file reference
|
||||||
|
// that needs to be updated
|
||||||
|
workspace.projects.add({
|
||||||
|
name: 'testProject',
|
||||||
|
root: 'apps/testProject',
|
||||||
|
sourceRoot: 'apps/testProject/src',
|
||||||
|
projectType: 'application',
|
||||||
|
targets: {
|
||||||
|
lint: {
|
||||||
|
builder: '@nrwl/linter:lint',
|
||||||
|
options: {
|
||||||
|
linter: 'eslint',
|
||||||
|
config: '.eslintrc',
|
||||||
|
tsConfig: [
|
||||||
|
'apps/testProject/tsconfig.app.json',
|
||||||
|
'apps/testProject/tsconfig.spec.json',
|
||||||
|
],
|
||||||
|
exclude: ['**/node_modules/**', '!apps/testProject/**/*'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// New eslint builder, with explicit config file reference
|
||||||
|
// that needs to be updated
|
||||||
|
workspace.projects.add({
|
||||||
|
name: 'testProject2',
|
||||||
|
root: 'apps/testProject2',
|
||||||
|
sourceRoot: 'apps/testProject2/src',
|
||||||
|
projectType: 'application',
|
||||||
|
targets: {
|
||||||
|
lint: {
|
||||||
|
builder: '@nrwl/linter:eslint',
|
||||||
|
options: {
|
||||||
|
eslintConfig: '.eslintrc',
|
||||||
|
lintFilePatterns: ['apps/testProject2/**/*.ts'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
tree
|
||||||
|
);
|
||||||
|
tree = await callRule(
|
||||||
|
updateJsonInTree('apps/testProject/.eslintrc', () => ({})),
|
||||||
|
tree
|
||||||
|
);
|
||||||
|
tree = await callRule(
|
||||||
|
updateJsonInTree('apps/testProject2/.eslintrc', () => ({})),
|
||||||
|
tree
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should rename .eslintrc files to .eslintrc.json and update any workspace.json references', async () => {
|
||||||
|
const result = await runMigration('add-json-ext-to-eslintrc', {}, tree);
|
||||||
|
|
||||||
|
const workspace = readWorkspace(tree);
|
||||||
|
|
||||||
|
// ---------------------------------------- Root
|
||||||
|
expect(() =>
|
||||||
|
readJsonInTree(result, '.eslintrc')
|
||||||
|
).toThrowErrorMatchingInlineSnapshot(`"Cannot find .eslintrc"`);
|
||||||
|
expect(readJsonInTree(result, '.eslintrc.json')).toMatchInlineSnapshot(
|
||||||
|
`Object {}`
|
||||||
|
);
|
||||||
|
|
||||||
|
// ---------------------------------------- testProject
|
||||||
|
expect(() =>
|
||||||
|
readJsonInTree(result, 'apps/testProject/.eslintrc')
|
||||||
|
).toThrowErrorMatchingInlineSnapshot(
|
||||||
|
`"Cannot find apps/testProject/.eslintrc"`
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
readJsonInTree(result, 'apps/testProject/.eslintrc.json')
|
||||||
|
).toMatchInlineSnapshot(`Object {}`);
|
||||||
|
expect(
|
||||||
|
workspace.projects['testProject'].architect.lint.options.config
|
||||||
|
).toEqual('.eslintrc.json');
|
||||||
|
|
||||||
|
// ---------------------------------------- testProject2
|
||||||
|
expect(() =>
|
||||||
|
readJsonInTree(result, 'apps/testProject2/.eslintrc')
|
||||||
|
).toThrowErrorMatchingInlineSnapshot(
|
||||||
|
`"Cannot find apps/testProject2/.eslintrc"`
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
readJsonInTree(result, 'apps/testProject2/.eslintrc.json')
|
||||||
|
).toMatchInlineSnapshot(`Object {}`);
|
||||||
|
expect(
|
||||||
|
workspace.projects['testProject2'].architect.lint.options.eslintConfig
|
||||||
|
).toEqual('.eslintrc.json');
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
import { basename } from '@angular-devkit/core';
|
||||||
|
import { chain, Tree } from '@angular-devkit/schematics';
|
||||||
|
import {
|
||||||
|
formatFiles,
|
||||||
|
readJsonInTree,
|
||||||
|
serializeJson,
|
||||||
|
updateWorkspace,
|
||||||
|
visitNotIgnoredFiles,
|
||||||
|
} from '@nrwl/workspace';
|
||||||
|
|
||||||
|
function updateESLintConfigReferencesInWorkspace() {
|
||||||
|
return updateWorkspace((workspace) => {
|
||||||
|
workspace.projects.forEach((project) => {
|
||||||
|
const lintTarget = project.targets.get('lint');
|
||||||
|
if (
|
||||||
|
lintTarget?.builder !== '@nrwl/linter:eslint' &&
|
||||||
|
(lintTarget?.builder !== '@nrwl/linter:lint' ||
|
||||||
|
lintTarget?.options?.linter === 'tslint')
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lintTarget.builder === '@nrwl/linter:eslint') {
|
||||||
|
if (!lintTarget.options.eslintConfig) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lintTarget.options.eslintConfig = `${lintTarget.options.eslintConfig}.json`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lintTarget.builder === '@nrwl/linter:lint') {
|
||||||
|
if (!lintTarget.options.config) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lintTarget.options.config = `${lintTarget.options.config}.json`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function renameESLintConfigFiles() {
|
||||||
|
return visitNotIgnoredFiles((file, host, context) => {
|
||||||
|
if (basename(file) !== '.eslintrc') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Using .eslintrc without an explicit file extension is deprecated
|
||||||
|
const newFilePath = `${file}.json`;
|
||||||
|
context.logger.info(`Renaming ${file} to ${newFilePath}`);
|
||||||
|
try {
|
||||||
|
return host.rename(file, newFilePath);
|
||||||
|
} catch (e) {
|
||||||
|
context.logger.error(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function () {
|
||||||
|
return chain([
|
||||||
|
renameESLintConfigFiles,
|
||||||
|
updateESLintConfigReferencesInWorkspace,
|
||||||
|
formatFiles(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
@ -197,14 +197,14 @@ describe('app', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('--linter=eslint', () => {
|
describe('--linter=eslint', () => {
|
||||||
it('should add .eslintrc and dependencies', async () => {
|
it('should add .eslintrc.json and dependencies', async () => {
|
||||||
const tree = await runSchematic(
|
const tree = await runSchematic(
|
||||||
'app',
|
'app',
|
||||||
{ name: 'myApp', linter: 'eslint' },
|
{ name: 'myApp', linter: 'eslint' },
|
||||||
appTree
|
appTree
|
||||||
);
|
);
|
||||||
|
|
||||||
const eslintJson = readJsonInTree(tree, '/apps/my-app/.eslintrc');
|
const eslintJson = readJsonInTree(tree, '/apps/my-app/.eslintrc.json');
|
||||||
const packageJson = readJsonInTree(tree, '/package.json');
|
const packageJson = readJsonInTree(tree, '/package.json');
|
||||||
|
|
||||||
expect(eslintJson.plugins).toEqual(
|
expect(eslintJson.plugins).toEqual(
|
||||||
|
|||||||
@ -112,9 +112,11 @@ describe('app', () => {
|
|||||||
expect(tsconfigApp.extends).toEqual('./tsconfig.json');
|
expect(tsconfigApp.extends).toEqual('./tsconfig.json');
|
||||||
|
|
||||||
const eslintrc = JSON.parse(
|
const eslintrc = JSON.parse(
|
||||||
stripJsonComments(getFileContent(tree, 'apps/my-node-app/.eslintrc'))
|
stripJsonComments(
|
||||||
|
getFileContent(tree, 'apps/my-node-app/.eslintrc.json')
|
||||||
|
)
|
||||||
);
|
);
|
||||||
expect(eslintrc.extends).toEqual('../../.eslintrc');
|
expect(eslintrc.extends).toEqual('../../.eslintrc.json');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -192,9 +194,9 @@ describe('app', () => {
|
|||||||
expectedValue: ['node'],
|
expectedValue: ['node'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'apps/my-dir/my-node-app/.eslintrc',
|
path: 'apps/my-dir/my-node-app/.eslintrc.json',
|
||||||
lookupFn: (json) => json.extends,
|
lookupFn: (json) => json.extends,
|
||||||
expectedValue: '../../../.eslintrc',
|
expectedValue: '../../../.eslintrc.json',
|
||||||
},
|
},
|
||||||
].forEach(hasJsonValue);
|
].forEach(hasJsonValue);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -71,9 +71,9 @@ describe('app', () => {
|
|||||||
expect(tsconfigApp.extends).toEqual('./tsconfig.json');
|
expect(tsconfigApp.extends).toEqual('./tsconfig.json');
|
||||||
|
|
||||||
const eslintJson = JSON.parse(
|
const eslintJson = JSON.parse(
|
||||||
stripJsonComments(tree.readContent('apps/my-app/.eslintrc'))
|
stripJsonComments(tree.readContent('apps/my-app/.eslintrc.json'))
|
||||||
);
|
);
|
||||||
expect(eslintJson.extends).toEqual(['../../.eslintrc']);
|
expect(eslintJson.extends).toEqual(['../../.eslintrc.json']);
|
||||||
|
|
||||||
expect(tree.exists('apps/my-app-e2e/cypress.json')).toBeTruthy();
|
expect(tree.exists('apps/my-app-e2e/cypress.json')).toBeTruthy();
|
||||||
const tsconfigE2E = JSON.parse(
|
const tsconfigE2E = JSON.parse(
|
||||||
@ -155,9 +155,9 @@ describe('app', () => {
|
|||||||
expectedValue: '../../../dist/out-tsc',
|
expectedValue: '../../../dist/out-tsc',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'apps/my-dir/my-app/.eslintrc',
|
path: 'apps/my-dir/my-app/.eslintrc.json',
|
||||||
lookupFn: (json) => json.extends,
|
lookupFn: (json) => json.extends,
|
||||||
expectedValue: ['../../../.eslintrc'],
|
expectedValue: ['../../../.eslintrc.json'],
|
||||||
},
|
},
|
||||||
].forEach(hasJsonValue);
|
].forEach(hasJsonValue);
|
||||||
});
|
});
|
||||||
@ -358,14 +358,14 @@ describe('app', () => {
|
|||||||
expect(appContent).not.toMatch(/extends Component/);
|
expect(appContent).not.toMatch(/extends Component/);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add .eslintrc and dependencies', async () => {
|
it('should add .eslintrc.json and dependencies', async () => {
|
||||||
const tree = await runSchematic(
|
const tree = await runSchematic(
|
||||||
'app',
|
'app',
|
||||||
{ name: 'myApp', linter: 'eslint' },
|
{ name: 'myApp', linter: 'eslint' },
|
||||||
appTree
|
appTree
|
||||||
);
|
);
|
||||||
|
|
||||||
const eslintJson = readJsonInTree(tree, '/apps/my-app/.eslintrc');
|
const eslintJson = readJsonInTree(tree, '/apps/my-app/.eslintrc.json');
|
||||||
const packageJson = readJsonInTree(tree, '/package.json');
|
const packageJson = readJsonInTree(tree, '/package.json');
|
||||||
|
|
||||||
expect(eslintJson.plugins).toEqual(
|
expect(eslintJson.plugins).toEqual(
|
||||||
|
|||||||
@ -201,7 +201,7 @@ function configureTsSolutionConfig(schema: StorybookConfigureSchema): Rule {
|
|||||||
* which includes *.stories files.
|
* which includes *.stories files.
|
||||||
*
|
*
|
||||||
* For TSLint this is done via the builder config, for ESLint this is
|
* For TSLint this is done via the builder config, for ESLint this is
|
||||||
* done within the .eslintrc file.
|
* done within the .eslintrc.json file.
|
||||||
*/
|
*/
|
||||||
function updateLintConfig(schema: StorybookConfigureSchema): Rule {
|
function updateLintConfig(schema: StorybookConfigureSchema): Rule {
|
||||||
const { name: projectName } = schema;
|
const { name: projectName } = schema;
|
||||||
@ -233,13 +233,16 @@ function updateLintConfig(schema: StorybookConfigureSchema): Rule {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return updateJsonInTree(`${projectConfig.root}/.eslintrc`, (json) => {
|
return updateJsonInTree(
|
||||||
if (Array.isArray(json.parserOptions?.project)) {
|
`${projectConfig.root}/.eslintrc.json`,
|
||||||
json.parserOptions.project.push(
|
(json) => {
|
||||||
`${projectConfig.root}/.storybook/tsconfig.json`
|
if (Array.isArray(json.parserOptions?.project)) {
|
||||||
);
|
json.parserOptions.project.push(
|
||||||
|
`${projectConfig.root}/.storybook/tsconfig.json`
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,9 +70,9 @@ describe('app', () => {
|
|||||||
expect(tsconfigApp.extends).toEqual('./tsconfig.json');
|
expect(tsconfigApp.extends).toEqual('./tsconfig.json');
|
||||||
|
|
||||||
const linter = JSON.parse(
|
const linter = JSON.parse(
|
||||||
stripJsonComments(tree.readContent('apps/my-app/.eslintrc'))
|
stripJsonComments(tree.readContent('apps/my-app/.eslintrc.json'))
|
||||||
);
|
);
|
||||||
expect(linter.extends).toEqual('../../.eslintrc');
|
expect(linter.extends).toEqual('../../.eslintrc.json');
|
||||||
|
|
||||||
expect(tree.exists('apps/my-app-e2e/cypress.json')).toBeTruthy();
|
expect(tree.exists('apps/my-app-e2e/cypress.json')).toBeTruthy();
|
||||||
const tsconfigE2E = JSON.parse(
|
const tsconfigE2E = JSON.parse(
|
||||||
@ -154,9 +154,9 @@ describe('app', () => {
|
|||||||
expectedValue: '../../../dist/out-tsc',
|
expectedValue: '../../../dist/out-tsc',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'apps/my-dir/my-app/.eslintrc',
|
path: 'apps/my-dir/my-app/.eslintrc.json',
|
||||||
lookupFn: (json) => json.extends,
|
lookupFn: (json) => json.extends,
|
||||||
expectedValue: '../../../.eslintrc',
|
expectedValue: '../../../.eslintrc.json',
|
||||||
},
|
},
|
||||||
].forEach(hasJsonValue);
|
].forEach(hasJsonValue);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -71,6 +71,7 @@ export { formatFiles } from './src/utils/rules/format-files';
|
|||||||
export { deleteFile } from './src/utils/rules/deleteFile';
|
export { deleteFile } from './src/utils/rules/deleteFile';
|
||||||
export * from './src/utils/rules/ng-add';
|
export * from './src/utils/rules/ng-add';
|
||||||
export { updateKarmaConf } from './src/utils/rules/update-karma-conf';
|
export { updateKarmaConf } from './src/utils/rules/update-karma-conf';
|
||||||
|
export { visitNotIgnoredFiles } from './src/utils/rules/visit-not-ignored-files';
|
||||||
export { setDefaultCollection } from './src/utils/rules/workspace';
|
export { setDefaultCollection } from './src/utils/rules/workspace';
|
||||||
import * as strings from './src/utils/strings';
|
import * as strings from './src/utils/strings';
|
||||||
export { checkAndCleanWithSemver } from './src/utils/version-utils';
|
export { checkAndCleanWithSemver } from './src/utils/version-utils';
|
||||||
|
|||||||
@ -184,7 +184,7 @@ describe('lib', () => {
|
|||||||
tree.exists('libs/my-dir/my-lib/src/lib/my-dir-my-lib.ts')
|
tree.exists('libs/my-dir/my-lib/src/lib/my-dir-my-lib.ts')
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
expect(tree.exists('libs/my-dir/my-lib/src/index.ts')).toBeTruthy();
|
expect(tree.exists('libs/my-dir/my-lib/src/index.ts')).toBeTruthy();
|
||||||
expect(tree.exists(`libs/my-dir/my-lib/.eslintrc`)).toBeTruthy();
|
expect(tree.exists(`libs/my-dir/my-lib/.eslintrc.json`)).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update workspace.json', async () => {
|
it('should update workspace.json', async () => {
|
||||||
@ -242,15 +242,15 @@ describe('lib', () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a local .eslintrc', async () => {
|
it('should create a local .eslintrc.json', async () => {
|
||||||
const tree = await runSchematic(
|
const tree = await runSchematic(
|
||||||
'lib',
|
'lib',
|
||||||
{ name: 'myLib', directory: 'myDir' },
|
{ name: 'myLib', directory: 'myDir' },
|
||||||
appTree
|
appTree
|
||||||
);
|
);
|
||||||
|
|
||||||
const lint = readJsonInTree(tree, 'libs/my-dir/my-lib/.eslintrc');
|
const lint = readJsonInTree(tree, 'libs/my-dir/my-lib/.eslintrc.json');
|
||||||
expect(lint.extends).toEqual('../../../.eslintrc');
|
expect(lint.extends).toEqual('../../../.eslintrc.json');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -98,9 +98,9 @@ describe('preset', () => {
|
|||||||
expect(
|
expect(
|
||||||
tree.exists('/libs/api-interfaces/src/lib/api-interfaces.ts')
|
tree.exists('/libs/api-interfaces/src/lib/api-interfaces.ts')
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
expect(tree.exists('/apps/proj/.eslintrc')).toBe(true);
|
expect(tree.exists('/apps/proj/.eslintrc.json')).toBe(true);
|
||||||
expect(tree.exists('/apps/api/.eslintrc')).toBe(true);
|
expect(tree.exists('/apps/api/.eslintrc.json')).toBe(true);
|
||||||
expect(tree.exists('/libs/api-interfaces/.eslintrc')).toBe(true);
|
expect(tree.exists('/libs/api-interfaces/.eslintrc.json')).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work with unnormalized names', async () => {
|
it('should work with unnormalized names', async () => {
|
||||||
|
|||||||
@ -92,9 +92,9 @@ export function addLintFiles(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (linter === 'eslint') {
|
if (linter === 'eslint') {
|
||||||
if (!host.exists('/.eslintrc')) {
|
if (!host.exists('/.eslintrc.json')) {
|
||||||
chainedCommands.push((host: Tree) => {
|
chainedCommands.push((host: Tree) => {
|
||||||
host.create('/.eslintrc', globalESLint);
|
host.create('/.eslintrc.json', globalESLint);
|
||||||
|
|
||||||
return addDepsToPackageJson(
|
return addDepsToPackageJson(
|
||||||
{
|
{
|
||||||
@ -119,7 +119,7 @@ export function addLintFiles(
|
|||||||
if (!options.onlyGlobal) {
|
if (!options.onlyGlobal) {
|
||||||
chainedCommands.push((host: Tree) => {
|
chainedCommands.push((host: Tree) => {
|
||||||
let configJson;
|
let configJson;
|
||||||
const rootConfig = `${offsetFromRoot(projectRoot)}.eslintrc`;
|
const rootConfig = `${offsetFromRoot(projectRoot)}.eslintrc.json`;
|
||||||
|
|
||||||
// Include all project files to be linted (since they are turned off in the root eslintrc file).
|
// Include all project files to be linted (since they are turned off in the root eslintrc file).
|
||||||
const ignorePatterns = ['!**/*'];
|
const ignorePatterns = ['!**/*'];
|
||||||
@ -155,7 +155,7 @@ export function addLintFiles(
|
|||||||
}
|
}
|
||||||
|
|
||||||
host.create(
|
host.create(
|
||||||
join(projectRoot as any, `.eslintrc`),
|
join(projectRoot as any, `.eslintrc.json`),
|
||||||
JSON.stringify(configJson)
|
JSON.stringify(configJson)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -246,11 +246,11 @@ const globalESLint = `
|
|||||||
"ignorePatterns": ["**/*"],
|
"ignorePatterns": ["**/*"],
|
||||||
"plugins": ["@typescript-eslint", "@nrwl/nx"],
|
"plugins": ["@typescript-eslint", "@nrwl/nx"],
|
||||||
"extends": [
|
"extends": [
|
||||||
'eslint:recommended',
|
"eslint:recommended",
|
||||||
'plugin:@typescript-eslint/eslint-recommended',
|
"plugin:@typescript-eslint/eslint-recommended",
|
||||||
'plugin:@typescript-eslint/recommended',
|
"plugin:@typescript-eslint/recommended",
|
||||||
'prettier',
|
"prettier",
|
||||||
'prettier/@typescript-eslint'
|
"prettier/@typescript-eslint"
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"@typescript-eslint/explicit-member-accessibility": "off",
|
"@typescript-eslint/explicit-member-accessibility": "off",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user