181 lines
4.4 KiB
TypeScript

import {
chain,
move,
noop,
Rule,
schematic,
SchematicContext,
Tree
} from '@angular-devkit/schematics';
import { Schema } from './schema';
import {
NodePackageInstallTask,
RepositoryInitializerTask
} from '@angular-devkit/schematics/tasks';
import { addDepsToPackageJson } from '../../utils/ast-utils';
import { toFileName } from '../../utils/name-utils';
import { formatFiles } from '../../utils/rules/format-files';
import { nxVersion } from '../../utils/versions';
import * as path from 'path';
import { Observable } from 'rxjs';
import { spawn } from 'child_process';
import { platform } from 'os';
class RunPresetTask {
toConfiguration() {
return {
name: 'RunPreset'
};
}
}
function createPresetTaskExecutor(opts: Schema) {
return {
name: 'RunPreset',
create: () => {
return Promise.resolve(() => {
const spawnOptions = {
stdio: [process.stdin, process.stdout, process.stderr],
shell: true,
cwd: path.join(process.cwd(), opts.directory)
};
const ng =
platform() === 'win32'
? '.\\node_modules\\.bin\\ng'
: './node_modules/.bin/ng';
const args = [
`g`,
`@nrwl/workspace:preset`,
`--name=${opts.name}`,
opts.style ? `--style=${opts.style}` : null,
opts.npmScope ? `--npmScope=${opts.npmScope}` : null,
opts.preset ? `--preset=${opts.preset}` : null
].filter(e => !!e);
return new Observable(obs => {
spawn(ng, args, spawnOptions).on('close', (code: number) => {
if (code === 0) {
obs.next();
obs.complete();
} else {
const message = 'Workspace creation failed, see above.';
obs.error(new Error(message));
}
});
});
});
}
};
}
export default function(options: Schema): Rule {
if (options.skipInstall && options.preset !== 'empty') {
throw new Error(`Cannot select a preset when skipInstall is set to true.`);
}
options = normalizeOptions(options);
const workspaceOpts = { ...options, preset: undefined };
return (host: Tree, context: SchematicContext) => {
const engineHost = (context.engine.workflow as any).engineHost;
engineHost.registerTaskExecutor(createPresetTaskExecutor(options));
return chain([
schematic('workspace', workspaceOpts),
addDependencies(options),
move('/', options.directory),
addTasks(options),
formatFiles()
])(Tree.empty(), context);
};
}
function addDependencies(options: Schema) {
if (options.preset === 'empty') {
return noop();
} else if (options.preset === 'angular') {
return addDepsToPackageJson(
{
'@nrwl/angular': nxVersion
},
{},
false
);
} else if (options.preset === 'react') {
return addDepsToPackageJson(
{},
{
'@nrwl/react': nxVersion
},
false
);
} else if (options.preset === 'web-components') {
return addDepsToPackageJson(
{},
{
'@nrwl/web': nxVersion
},
false
);
} else {
return addDepsToPackageJson(
{
'@nrwl/angular': nxVersion
},
{
'@nrwl/nest': nxVersion
},
false
);
}
}
function addTasks(options: Schema) {
return (host: Tree, context: SchematicContext) => {
let packageTask;
let presetInstallTask;
if (!options.skipInstall) {
packageTask = context.addTask(
new NodePackageInstallTask(options.directory)
);
}
if (options.preset !== 'empty') {
const createPresetTask = context.addTask(new RunPresetTask(), [
packageTask
]);
presetInstallTask = context.addTask(
new NodePackageInstallTask(options.directory),
[createPresetTask]
);
}
if (!options.skipGit) {
const commit =
typeof options.commit == 'object'
? options.commit
: !!options.commit
? {}
: false;
context.addTask(
new RepositoryInitializerTask(options.directory, commit),
presetInstallTask
? [presetInstallTask]
: packageTask
? [packageTask]
: []
);
}
};
}
function normalizeOptions(options: Schema): Schema {
options.name = toFileName(options.name);
if (!options.directory) {
options.directory = options.name;
}
return options;
}