220 lines
7.2 KiB
TypeScript
220 lines
7.2 KiB
TypeScript
import {
|
|
apply,
|
|
branchAndMerge,
|
|
chain,
|
|
externalSchematic,
|
|
mergeWith,
|
|
move,
|
|
Rule,
|
|
template,
|
|
Tree,
|
|
url,
|
|
schematic
|
|
} from '@angular-devkit/schematics';
|
|
import { Schema } from './schema';
|
|
import * as path from 'path';
|
|
import { angularCliVersion, ngrxVersion, nxVersion, prettierVersion, schematicsVersion } from '../utility/lib-versions';
|
|
import * as fs from 'fs';
|
|
import { join } from 'path';
|
|
import { serializeJson, updateJsonFile } from '../utility/fileutils';
|
|
import { toFileName } from '@nrwl/schematics';
|
|
|
|
function updatePackageJson() {
|
|
return (host: Tree) => {
|
|
if (!host.exists('package.json')) {
|
|
throw new Error('Cannot find package.json');
|
|
}
|
|
const packageJson = JSON.parse(host.read('package.json')!.toString('utf-8'));
|
|
if (!packageJson.devDependencies) {
|
|
packageJson.devDependencies = {};
|
|
}
|
|
if (!packageJson.dependencies) {
|
|
packageJson.dependencies = {};
|
|
}
|
|
if (!packageJson.scripts) {
|
|
packageJson.scripts = {};
|
|
}
|
|
if (!packageJson.dependencies['@nrwl/nx']) {
|
|
packageJson.dependencies['@nrwl/nx'] = nxVersion;
|
|
}
|
|
if (!packageJson.dependencies['@ngrx/store']) {
|
|
packageJson.dependencies['@ngrx/store'] = ngrxVersion;
|
|
}
|
|
if (!packageJson.dependencies['@ngrx/router-store']) {
|
|
packageJson.dependencies['@ngrx/router-store'] = ngrxVersion;
|
|
}
|
|
if (!packageJson.dependencies['@ngrx/effects']) {
|
|
packageJson.dependencies['@ngrx/effects'] = ngrxVersion;
|
|
}
|
|
if (!packageJson.dependencies['@ngrx/store-devtools']) {
|
|
packageJson.dependencies['@ngrx/store-devtools'] = ngrxVersion;
|
|
}
|
|
if (!packageJson.devDependencies['@nrwl/schematics']) {
|
|
packageJson.devDependencies['@nrwl/schematics'] = schematicsVersion;
|
|
}
|
|
if (!packageJson.dependencies['@angular/cli']) {
|
|
packageJson.dependencies['@angular/cli'] = angularCliVersion;
|
|
}
|
|
if (!packageJson.devDependencies['prettier']) {
|
|
packageJson.devDependencies['prettier'] = prettierVersion;
|
|
}
|
|
packageJson.scripts['format'] = `prettier --single-quote --print-width 120 --write '{apps,libs}/**/*.ts'`;
|
|
host.overwrite('package.json', serializeJson(packageJson));
|
|
return host;
|
|
};
|
|
}
|
|
|
|
function updateAngularCLIJson(options: Schema) {
|
|
return (host: Tree) => {
|
|
if (!host.exists('.angular-cli.json')) {
|
|
throw new Error('Cannot find .angular-cli.json');
|
|
}
|
|
const angularCliJson = JSON.parse(host.read('.angular-cli.json')!.toString('utf-8'));
|
|
angularCliJson.project.npmScope = npmScope(options);
|
|
|
|
if (angularCliJson.apps.length !== 1) {
|
|
throw new Error('Can only convert projects with one app');
|
|
}
|
|
|
|
angularCliJson.lint = [
|
|
{ project: './tsconfig.app.json' },
|
|
{ project: './tsconfig.spec.json' },
|
|
{ project: './tsconfig.e2e.json' }
|
|
];
|
|
|
|
const app = angularCliJson.apps[0];
|
|
app.root = path.join('apps', options.name, app.root);
|
|
app.outDir = path.join('dist', 'apps', options.name);
|
|
app.test = '../../../test.js';
|
|
app.tsconfig = '../../../tsconfig.app.json';
|
|
app.testTsconfig = '../../../tsconfig.spec.json';
|
|
app.scripts = app.scripts.map(p => path.join('../../', p));
|
|
if (!angularCliJson.defaults) {
|
|
angularCliJson.defaults = {};
|
|
}
|
|
if (!angularCliJson.defaults.schematics) {
|
|
angularCliJson.defaults.schematics = {};
|
|
}
|
|
angularCliJson.defaults.schematics['collection'] = '@nrwl/schematics';
|
|
angularCliJson.defaults.schematics['postGenerate'] = 'npm run format';
|
|
angularCliJson.defaults.schematics['newProject'] = ['app', 'lib'];
|
|
|
|
host.overwrite('.angular-cli.json', serializeJson(angularCliJson));
|
|
|
|
return host;
|
|
};
|
|
}
|
|
|
|
function updateTsConfigsJson(options: Schema) {
|
|
return (host: Tree) => {
|
|
updateJsonFile('tsconfig.json', json => setUpCompilerOptions(json, npmScope(options)));
|
|
|
|
updateJsonFile('tsconfig.app.json', json => {
|
|
json['extends'] = './tsconfig.json';
|
|
if (!json.exclude) json.exclude = [];
|
|
json.exclude = dedup(json.exclude.concat(['**/*.spec.ts', '**/*.e2e-spec.ts', 'node_modules', 'tmp']));
|
|
setUpCompilerOptions(json, npmScope(options));
|
|
});
|
|
|
|
updateJsonFile('tsconfig.spec.json', json => {
|
|
json['extends'] = './tsconfig.json';
|
|
if (!json.exclude) json.exclude = [];
|
|
json.files = ['test.js'];
|
|
json.exclude = dedup(json.exclude.concat(['node_modules', 'tmp']));
|
|
setUpCompilerOptions(json, npmScope(options));
|
|
});
|
|
|
|
updateJsonFile('tsconfig.e2e.json', json => {
|
|
json['extends'] = './tsconfig.json';
|
|
if (!json.exclude) json.exclude = [];
|
|
json.exclude = dedup(json.exclude.concat(['**/*.spec.ts', 'node_modules', 'tmp']));
|
|
setUpCompilerOptions(json, npmScope(options));
|
|
});
|
|
|
|
return host;
|
|
};
|
|
}
|
|
|
|
function updateTsLintJson(options: Schema) {
|
|
return (host: Tree) => {
|
|
updateJsonFile('tslint.json', json => {
|
|
['no-trailing-whitespace', 'one-line', 'quotemark', 'typedef-whitespace', 'whitespace'].forEach(key => {
|
|
json[key] = undefined;
|
|
});
|
|
json['nx-enforce-module-boundaries'] = [true, { npmScope: npmScope(options), lazyLoad: [] }];
|
|
});
|
|
return host;
|
|
};
|
|
}
|
|
|
|
function npmScope(options: Schema): string {
|
|
return options && options.npmScope ? options.npmScope : options.name;
|
|
}
|
|
|
|
function updateProtractorConf() {
|
|
return (host: Tree) => {
|
|
if (!host.exists('protractor.conf.js')) {
|
|
throw new Error('Cannot find protractor.conf.js');
|
|
}
|
|
const protractorConf = host.read('protractor.conf.js')!.toString('utf-8');
|
|
const updatedConf = protractorConf
|
|
.replace(`./e2e/**/*.e2e-spec.ts`, `./apps/**/*.e2e-spec.ts`)
|
|
.replace(`e2e/tsconfig.e2e.json`, `./tsconfig.e2e.json`);
|
|
|
|
host.overwrite('protractor.conf.js', updatedConf);
|
|
|
|
return host;
|
|
};
|
|
}
|
|
|
|
function setUpCompilerOptions(tsconfig: any, npmScope: string): void {
|
|
if (!tsconfig.compilerOptions.paths) {
|
|
tsconfig.compilerOptions.paths = {};
|
|
}
|
|
tsconfig.compilerOptions.baseUrl = '.';
|
|
tsconfig.compilerOptions.paths[`@${npmScope}/*`] = ['libs/*'];
|
|
}
|
|
|
|
function moveFiles(options: Schema) {
|
|
return (host: Tree) => {
|
|
const angularCliJson = JSON.parse(host.read('.angular-cli.json')!.toString('utf-8'));
|
|
const app = angularCliJson.apps[0];
|
|
|
|
fs.mkdirSync('apps');
|
|
fs.mkdirSync('libs');
|
|
fs.unlinkSync(path.join(app.root, app.test));
|
|
fs.mkdirSync(path.join('apps', options.name));
|
|
fs.renameSync(path.join(app.root, app.tsconfig), 'tsconfig.app.json');
|
|
fs.renameSync(path.join(app.root, app.testTsconfig), 'tsconfig.spec.json');
|
|
fs.renameSync(path.join('e2e', 'tsconfig.e2e.json'), 'tsconfig.e2e.json');
|
|
fs.renameSync(app.root, join('apps', options.name, app.root));
|
|
fs.renameSync('e2e', join('apps', options.name, 'e2e'));
|
|
|
|
return host;
|
|
};
|
|
}
|
|
|
|
function dedup(array: any[]): any[] {
|
|
const res = [];
|
|
|
|
array.forEach(a => {
|
|
if (res.indexOf(a) === -1) {
|
|
res.push(a);
|
|
}
|
|
});
|
|
return res;
|
|
}
|
|
|
|
export default function(schema: Schema): Rule {
|
|
const options = { ...schema, name: toFileName(schema.name) };
|
|
return chain([
|
|
moveFiles(options),
|
|
branchAndMerge(chain([mergeWith(apply(url('./files'), []))])),
|
|
updatePackageJson(),
|
|
updateAngularCLIJson(options),
|
|
updateTsConfigsJson(options),
|
|
updateProtractorConf(),
|
|
updateTsLintJson(options)
|
|
]);
|
|
}
|