1 | import fs from 'fs';
|
2 | import inquirer from 'inquirer';
|
3 | import path from 'path';
|
4 | import yeoman from 'yeoman-environment';
|
5 | import { install } from '../../shared/npm';
|
6 |
|
7 | const loadGenerator = (root: string, rootPkg: string) => {
|
8 | return new Promise<any>((resolve, reject) => {
|
9 | fs.readFile(rootPkg, 'utf8', (err, data) => {
|
10 | if (err) {
|
11 | reject(err);
|
12 | } else {
|
13 | const json = JSON.parse(data);
|
14 | const deps = json.dependencies || json.devDependencies || {};
|
15 | const generators = Object.keys(deps)
|
16 | .filter((name) => {
|
17 | if (!/^generator-|^@[^/]+\/generator-/.test(name)) {
|
18 | return false;
|
19 | }
|
20 | const generatorPath = path.join(root, 'node_modules', name);
|
21 | return fs.existsSync(generatorPath);
|
22 | })
|
23 | .map((name) => {
|
24 | const generatorPkgPath = path.join(
|
25 | root,
|
26 | 'node_modules',
|
27 | name,
|
28 | 'package.json'
|
29 | );
|
30 | const generatorPkgData = fs.readFileSync(generatorPkgPath, 'utf8');
|
31 | const generatorPkgJson = JSON.parse(generatorPkgData);
|
32 | const desc = generatorPkgJson.description;
|
33 |
|
34 | return { name, desc };
|
35 | });
|
36 | resolve(generators);
|
37 | }
|
38 | });
|
39 | });
|
40 | };
|
41 |
|
42 | const run = (ctx: any, name: string) => {
|
43 | const root = ctx.root;
|
44 | const yeomanEnv = yeoman.createEnv();
|
45 | let generatorEntry = path.join(root, 'node_modules', name, 'app/index.js');
|
46 |
|
47 | if (!fs.existsSync(generatorEntry)) {
|
48 | generatorEntry = path.join(
|
49 | root,
|
50 | 'node_modules',
|
51 | name,
|
52 | 'generators',
|
53 | 'app/index.js'
|
54 | );
|
55 | }
|
56 | yeomanEnv.register(require.resolve(generatorEntry), name);
|
57 | yeomanEnv.run(name, ctx, (err) => {
|
58 | ctx.reporter && ctx.reporter.reportInitResult()
|
59 | if (err) {
|
60 | ctx.logger.error(err);
|
61 | } else {
|
62 | ctx.logger.debug('create project success!');
|
63 | }
|
64 | });
|
65 | };
|
66 |
|
67 | module.exports = (ctx: any) => {
|
68 | ctx.commander.register('init', 'Create a new project', () => {
|
69 | const { root, rootPkg, args } = ctx;
|
70 | const { generator } = args;
|
71 | loadGenerator(root, rootPkg).then(async (generators: any) => {
|
72 |
|
73 | if (generator && /^generator-|^@[^/]+\/generator-/.test(generator)) {
|
74 | const isGeneratorInstalled = generators.some((item: any) => {
|
75 | return item.name === generator
|
76 | });
|
77 | if (generators.length && isGeneratorInstalled) {
|
78 | run(ctx, generator);
|
79 | return;
|
80 | } else {
|
81 | const askIfInstallGenerator = [
|
82 | {
|
83 | type: 'confirm',
|
84 | name: 'ifInstall',
|
85 | message: `You have not installed the generator ${generator},if you want to install and use ?`,
|
86 | default: true
|
87 | }
|
88 | ];
|
89 | const answer = await inquirer.prompt(askIfInstallGenerator);
|
90 | if (answer.ifInstall) {
|
91 | const packageManager = ctx.config && ctx.config.packageManager;
|
92 | install(
|
93 | packageManager,
|
94 | ctx.root,
|
95 | 'install',
|
96 | generator,
|
97 | false,
|
98 | true
|
99 | ).then(() => {
|
100 | ctx.logger.info(`install success`);
|
101 | run(ctx, generator);
|
102 | });
|
103 | return;
|
104 | }
|
105 | }
|
106 | }
|
107 | const options = generators.map((item: any) => {
|
108 | return item.desc;
|
109 | });
|
110 | if (generators.length) {
|
111 | inquirer
|
112 | .prompt([
|
113 | {
|
114 | type: 'list',
|
115 | name: 'desc',
|
116 | message: '您想要创建哪种类型的工程?',
|
117 | choices: options
|
118 | }
|
119 | ])
|
120 | .then((answer: any) => {
|
121 | let name;
|
122 | generators.map((item: any) => {
|
123 | if (item.desc === answer.desc) {
|
124 | name = item.name;
|
125 | }
|
126 | });
|
127 | ctx.reporter.report('init', name)
|
128 | name && run(ctx, name);
|
129 | });
|
130 | } else {
|
131 | ctx.logger.warn(
|
132 | 'You have not installed a template yet, ' +
|
133 | ' please use install command. Guide: https://github.com/Tencent/feflow'
|
134 | );
|
135 | }
|
136 | });
|
137 | });
|
138 | };
|