Victor Savkin c25628a4f6
feat(misc): add linter flag to create-nx-workspace (#3826)
* feat(misc): add linter flag to create-nx-workspace

* fix(core): prompt linter when preset is angular or angular-nest

Co-authored-by: Jason Jean <jasonjean1993@gmail.com>
2020-09-30 12:11:37 -04:00

220 lines
6.6 KiB
TypeScript

import { join, normalize } from '@angular-devkit/core';
import {
apply,
chain,
MergeStrategy,
mergeWith,
move,
noop,
Rule,
SchematicContext,
template,
Tree,
url,
} from '@angular-devkit/schematics';
import {
getWorkspacePath,
Linter,
offsetFromRoot,
replaceAppNameWithPath,
updateJsonInTree,
} from '@nrwl/workspace';
import * as path from 'path';
import { NormalizedSchema } from './normalized-schema';
import { updateNgPackage } from './update-ng-package';
// TODO - refactor this into separate rules with better names
export function updateProject(options: NormalizedSchema): Rule {
return chain([
(host: Tree, _context: SchematicContext): Tree => {
const libRoot = `${options.projectRoot}/src/lib/`;
const serviceSpecPath = path.join(
libRoot,
`${options.name}.service.spec.ts`
);
const componentSpecPath = path.join(
libRoot,
`${options.name}.component.spec.ts`
);
host.delete(path.join(libRoot, `${options.name}.service.ts`));
if (host.exists(serviceSpecPath)) {
host.delete(serviceSpecPath);
}
host.delete(path.join(libRoot, `${options.name}.component.ts`));
if (host.exists(componentSpecPath)) {
host.delete(path.join(libRoot, `${options.name}.component.spec.ts`));
}
if (!options.publishable && !options.buildable) {
host.delete(path.join(options.projectRoot, 'ng-package.json'));
host.delete(path.join(options.projectRoot, 'package.json'));
host.delete(path.join(options.projectRoot, 'tsconfig.lib.prod.json'));
}
host.delete(path.join(options.projectRoot, 'karma.conf.js'));
host.delete(path.join(options.projectRoot, 'src/test.ts'));
host.delete(path.join(options.projectRoot, 'tsconfig.spec.json'));
host.delete(path.join(libRoot, `${options.name}.module.ts`));
host.create(
path.join(libRoot, `${options.fileName}.module.ts`),
`
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
@NgModule({
imports: [
CommonModule
]
})
export class ${options.moduleName} { }
`
);
if (options.unitTestRunner !== 'none' && options.addModuleSpec) {
host.create(
path.join(libRoot, `${options.fileName}.module.spec.ts`),
`
import { async, TestBed } from '@angular/core/testing';
import { ${options.moduleName} } from './${options.fileName}.module';
describe('${options.moduleName}', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [ ${options.moduleName} ]
})
.compileComponents();
}));
// TODO: Add real tests here.
//
// NB: This particular test does not do anything useful.
// It does NOT check for correct instantiation of the module.
it('should have a module definition', () => {
expect(${options.moduleName}).toBeDefined();
});
});
`
);
}
host.overwrite(
`${options.projectRoot}/src/index.ts`,
`
export * from './lib/${options.fileName}.module';
`
);
return host;
},
mergeWith(
apply(url('./files/lib'), [
template({
...options,
offsetFromRoot: offsetFromRoot(options.projectRoot),
}),
move(options.projectRoot),
]),
MergeStrategy.Overwrite
),
(host: Tree) => {
return updateJsonInTree(getWorkspacePath(host), (json) => {
const project = json.projects[options.name];
const fixedProject = replaceAppNameWithPath(
project,
options.name,
options.projectRoot
);
fixedProject.schematics = fixedProject.schematics || {};
if (options.style !== 'css') {
fixedProject.schematics = {
...fixedProject.schematics,
'@schematics/angular:component': {
style: options.style,
},
};
}
if (!options.publishable && !options.buildable) {
delete fixedProject.architect.build;
} else {
// adjust the builder path to our custom one
fixedProject.architect.build.builder = '@nrwl/angular:package';
}
delete fixedProject.architect.test;
if (options.linter === Linter.TsLint) {
fixedProject.architect.lint.options.tsConfig = fixedProject.architect.lint.options.tsConfig.filter(
(path) =>
path !==
join(normalize(options.projectRoot), 'tsconfig.spec.json')
);
fixedProject.architect.lint.options.exclude.push(
'!' + join(normalize(options.projectRoot), '**/*')
);
}
if (options.linter === Linter.EsLint) {
fixedProject.architect.lint.builder = '@nrwl/linter:eslint';
fixedProject.architect.lint.options.lintFilePatterns = [
`${options.projectRoot}/src/**/*.ts`,
];
delete fixedProject.architect.lint.options.tsConfig;
delete fixedProject.architect.lint.options.exclude;
host.delete(`${options.projectRoot}/tslint.json`);
}
json.projects[options.name] = fixedProject;
return json;
});
},
updateJsonInTree(`${options.projectRoot}/tsconfig.lib.json`, (json) => {
if (options.unitTestRunner === 'jest') {
json.exclude = ['src/test-setup.ts', '**/*.spec.ts'];
} else if (options.unitTestRunner === 'none') {
json.exclude = [];
} else {
json.exclude = json.exclude || [];
}
return {
...json,
extends: `./tsconfig.json`,
compilerOptions: {
...json.compilerOptions,
outDir: `${offsetFromRoot(options.projectRoot)}dist/out-tsc`,
},
};
}),
options.linter === Linter.TsLint
? updateJsonInTree(`${options.projectRoot}/tslint.json`, (json) => {
return {
...json,
extends: `${offsetFromRoot(options.projectRoot)}tslint.json`,
linterOptions: {
exclude: ['!**/*'],
},
};
})
: noop(),
updateJsonInTree(`/nx.json`, (json) => {
return {
...json,
projects: {
...json.projects,
[options.name]: { tags: options.parsedTags },
},
};
}),
(host: Tree) => {
return updateNgPackage(host, options);
},
]);
}