@nrwl/schematics
Version:
163 lines (162 loc) • 7.08 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const schematics_1 = require("@angular-devkit/schematics");
const core_1 = require("@angular-devkit/core");
const path_1 = require("path");
const workspace_1 = require("@nrwl/workspace");
const workspace_2 = require("@nrwl/workspace");
const workspace_3 = require("@nrwl/workspace");
const literals_1 = require("@angular-devkit/core/src/utils/literals");
function getBuilders(project) {
return Array.from(new Set(Object.values(project.architect).map(target => target.builder)));
}
const builderTypes = {
'@angular-devkit/build-angular:karma': ['jasmine'],
'@angular-devkit/build-angular:protractor': ['jasmine', 'jasminewd2'],
'@nrwl/builders:jest': ['jest', 'node'],
'@nrwl/builers:cypress': ['cypress']
};
function getTypes(host, project, context) {
let types = [];
const tsConfigPaths = getTsConfigs(project, host);
const tsConfigs = tsConfigPaths.map(tsconfigPath => workspace_1.readJsonInTree(host, tsconfigPath));
const tsConfigsWithNoTypes = tsConfigPaths.filter(tsconfigPath => {
const tsconfig = workspace_1.readJsonInTree(host, tsconfigPath);
return !tsconfig.compilerOptions.types;
});
if (tsConfigsWithNoTypes.length > 0) {
context.logger.warn(literals_1.stripIndents `The following tsconfigs had no types defined: ${tsConfigsWithNoTypes.join(',')}`);
return undefined;
}
types = types.concat(...tsConfigs.map(tsconfig => tsconfig.compilerOptions.types || []));
types = types.concat(...getBuilders(project)
.filter(builder => builder in builderTypes)
.map(builder => builderTypes[builder]));
return types.filter((type, i, arr) => arr.indexOf(type) === i); // dedupe the array;
}
function createTsConfig(project) {
return (host, context) => {
const tsConfigPath = core_1.join(core_1.normalize(project.root), 'tsconfig.json');
if (host.exists(tsConfigPath)) {
return schematics_1.noop();
}
host.create(tsConfigPath, '{}');
const types = getTypes(host, project, context);
if (types === undefined) {
context.logger.warn(literals_1.stripIndents `No types array was added to ${tsConfigPath} meaning the editor might encounter conflicts for types.}`);
}
return workspace_1.updateJsonInTree(tsConfigPath, () => {
return {
extends: `${workspace_3.offsetFromRoot(project.root)}tsconfig.json`,
compilerOptions: {
types
}
};
});
};
}
function getTsConfigs(project, host, context) {
return Array.from(new Set(Object.values(project.architect)
.reduce((arr, target) => {
return [
...arr,
...(target.options ? [target.options] : []),
...Object.values(target.configurations || {})
];
}, [])
.reduce((arr, options) => {
if (!options.tsConfig) {
return arr;
}
if (!Array.isArray(options.tsConfig)) {
return arr.includes(options.tsConfig)
? arr
: [...arr, options.tsConfig];
}
return [
...arr,
...options.tsConfig.filter(tsconfig => !arr.includes(tsconfig))
];
}, [])
.filter(tsconfig => {
if (!host.exists(tsconfig)) {
if (context) {
context.logger.warn(`${tsconfig} does not exist but is set as a "tsConfig" in /angular.json`);
}
return false;
}
return true;
})
.map(tsconfig => {
return core_1.normalize(tsconfig);
})));
}
function updateTsConfig(project, tsconfig) {
return workspace_1.updateJsonInTree(tsconfig, json => {
json.extends =
core_1.dirname(tsconfig) === core_1.normalize(project.root)
? './tsconfig.json'
: path_1.relative(core_1.dirname(tsconfig), core_1.join(project.root, 'tsconfig.json'));
return json;
});
}
function updateTsConfigs(project) {
return (host, context) => {
return schematics_1.chain(getTsConfigs(project, host, context).map(tsconfig => updateTsConfig(project, tsconfig)));
};
}
function fixCypressConfigs(host, context) {
const workspaceJson = workspace_1.readJsonInTree(host, 'angular.json');
return schematics_1.chain(Object.entries(workspaceJson.projects)
.filter(([key, project]) => project.architect.e2e &&
project.architect.e2e.builder === '@nrwl/builders:cypress' &&
project.architect.lint &&
!host.exists(project.architect.lint.options.tsConfig) &&
host.exists(core_1.join(project.root, 'tsconfig.e2e.json')))
.map(([key, project]) => fixCypressConfig(project, key)));
}
function fixCypressConfig(project, projectKey) {
return workspace_1.updateWorkspaceInTree(workspaceJson => {
workspaceJson.projects[projectKey].architect.lint.options.tsConfig = core_1.join(project.root, 'tsconfig.e2e.json');
return workspaceJson;
});
}
function updateProjects(host) {
const { projects } = workspace_1.readJsonInTree(host, workspace_2.getWorkspacePath(host));
return schematics_1.chain(Object.entries(projects).map(([key, project]) => {
return schematics_1.chain([createTsConfig(project), updateTsConfigs(project)]);
}));
}
function displayInformation(host, context) {
context.logger
.info(literals_1.stripIndents `With this update, we are changing the structure of the tsconfig files.
A tsconfig.json has been added to all project roots which is used by editors to provide intellisense.
The tsconfig.(app|lib|spec|e2e).json files now all extend off of the tsconfig.json in the project root.
To find out more, visit our wiki: https://github.com/nrwl/nx/wiki/Workspace-Organization#tsconfigs`);
}
function switchToEs2015(host, context) {
return workspace_1.updateJsonInTree('tsconfig.json', json => {
json.compilerOptions = json.compilerOptions || {};
json.compilerOptions.module = 'es2015';
context.logger.info('Typescript has been set to compile with es2015 modules');
return json;
});
}
const updateAngularCLI = workspace_3.addUpdateTask('@angular/cli', '7.1.0');
function default_1() {
return schematics_1.chain([
workspace_1.updateJsonInTree('package.json', json => {
json.dependencies = json.dependencies || {};
json.dependencies = Object.assign({}, json.dependencies, { '@ngrx/effects': '6.1.2', '@ngrx/router-store': '6.1.2', '@ngrx/store': '6.1.2' });
json.devDependencies = json.devDependencies || {};
json.devDependencies = Object.assign({}, json.devDependencies, { '@ngrx/schematics': '6.1.2', '@ngrx/store-devtools': '6.1.2' });
return json;
}),
fixCypressConfigs,
switchToEs2015,
updateProjects,
displayInformation,
updateAngularCLI
]);
}
exports.default = default_1;