1 | const {
|
2 | generator,
|
3 | clone,
|
4 | getOptions
|
5 | } = require('../index')
|
6 | const {
|
7 | localpath
|
8 | } = require('../lib/utils/localpath')
|
9 | const {
|
10 | evaluate
|
11 | } = require('../lib/utils/eval')
|
12 | const fse = require('fs-extra');
|
13 | const debug = require('debug')('create')
|
14 | const path = require('path')
|
15 | const async = require('async')
|
16 |
|
17 | const exists = fse.existsSync
|
18 |
|
19 | module.exports = {
|
20 | name: 'create',
|
21 | description: 'Create a weex project',
|
22 | run: async ({
|
23 | logger,
|
24 | parameters,
|
25 | inquirer,
|
26 | meta
|
27 | }) => {
|
28 | const first = parameters.first
|
29 | const second = parameters.second
|
30 | const options = parameters.options
|
31 | const globalConfig = options.__config
|
32 |
|
33 |
|
34 | const promptMapping = {
|
35 | string: 'input',
|
36 | boolean: 'confirm'
|
37 | };
|
38 |
|
39 | const showHelp = async () => {
|
40 | let params = {
|
41 | commandend: 'Create a weex project',
|
42 | commands: [{
|
43 | heading: ['Usage', 'Description']
|
44 | },
|
45 | {
|
46 | key: 'create [project-name]',
|
47 | description: 'Create a official weex project'
|
48 | },
|
49 | {
|
50 | key: 'create <template-name | git-repo> [project-name]',
|
51 | description: 'Create a project from specify template name or git repository'
|
52 | }
|
53 | ],
|
54 | options: {
|
55 | 'Base': [{
|
56 | key: '--no-cache',
|
57 | description: 'Fetching latest template with no cache.'
|
58 | }, {
|
59 | key: '--clone',
|
60 | description: 'If true use git clone instead of an http download. While this can be a bit slower, it does allow private repositories to be used if the appropriate SSH keys are setup'
|
61 | }],
|
62 | 'Miscellaneous:': [{
|
63 | key: '-v, --version',
|
64 | description: 'Output the version number'
|
65 | },
|
66 | {
|
67 | key: '-h, --help',
|
68 | description: 'Show help'
|
69 | }
|
70 | ]
|
71 | }
|
72 | }
|
73 | meta.generateHelp(params)
|
74 | }
|
75 |
|
76 | const askQuestion = async (name, templatePath) => {
|
77 | debug(`Render from local path ${templatePath}`)
|
78 | const meta = getOptions(name, templatePath)
|
79 | let propmts = []
|
80 | let keys = Object.keys(meta.prompts)
|
81 | keys.forEach(key => {
|
82 | let prompt = meta.prompts[key]
|
83 | promptDefault = typeof prompt.default !== 'undefined' ? prompt.default : ''
|
84 | propmts.push({
|
85 | type: promptMapping[prompt.type] || prompt.type,
|
86 | name: key,
|
87 | message: prompt.message || prompt.label || key,
|
88 | default: promptDefault,
|
89 | choices: prompt.choices || [],
|
90 | validate: prompt.validate || (() => true)
|
91 | })
|
92 | })
|
93 | let answer = await inquirer.prompt(propmts)
|
94 |
|
95 | return Object.assign(meta, answer)
|
96 | }
|
97 |
|
98 | if (options.version || options.v) {
|
99 |
|
100 | logger.info(`${require("../package.json").version}`);
|
101 |
|
102 | } else if (options.help || options.h) {
|
103 | await showHelp()
|
104 | } else {
|
105 | let templateName = globalConfig.defaultWeexTemplate || 'webpack'
|
106 | let projectName
|
107 | if (!first) {
|
108 | logger.warn('You need to provide all the required parameters.')
|
109 | logger.error('Project name cannot be empty.')
|
110 | await showHelp()
|
111 | return
|
112 | }
|
113 | if (first && second) {
|
114 | templateName = first
|
115 | projectName = second
|
116 | } else if (first) {
|
117 | projectName = first
|
118 | }
|
119 | let target = path.resolve(projectName);
|
120 | if (exists(target)) {
|
121 | let res = await inquirer.prompt([{
|
122 | type: 'confirm',
|
123 | message: 'Target directory exists. Continue?',
|
124 | name: 'yes'
|
125 | }])
|
126 | if (res.yes) {
|
127 | let spinner = logger.spin(`Remove ${target} ...`);
|
128 | await fse.remove(target);
|
129 | spinner.stop();
|
130 | } else {
|
131 | return
|
132 | }
|
133 | }
|
134 | if (localpath.isLocalPath(templateName)) {
|
135 | const templatePath = localpath.getTemplatePath(templateName);
|
136 | if (exists(templatePath)) {
|
137 | let answer = await askQuestion(projectName, templatePath)
|
138 | let metadata = Object.assign(answer, {
|
139 | destDirName: projectName,
|
140 | inPlace: target === process.cwd(),
|
141 | noEscape: true
|
142 | })
|
143 | await generator(templatePath, target, metadata)
|
144 | } else {
|
145 | logger.error(`Local template "${templatePath}" not found.`);
|
146 | }
|
147 | } else {
|
148 | const hasHash = /\//.test(templateName)
|
149 | if (!hasHash) {
|
150 |
|
151 | templateName = `${globalConfig.defaultWeexTemplateRepo || 'weex-templates'}/${templateName}`
|
152 | }
|
153 | const templatesTarget = path.join(globalConfig.templatePath, templateName)
|
154 | let spinner = logger.spin(`Download from ${templateName} repo ...`);
|
155 | const templatePath = await clone(templateName, templatesTarget, {
|
156 | cache: exists(templatesTarget) && (typeof options.cache === 'boolean' ? options.cache : true),
|
157 | clone: options.clone || false
|
158 | })
|
159 | spinner.stop();
|
160 | let answer = await askQuestion(projectName, templatePath)
|
161 | let metadata = Object.assign(answer, {
|
162 | destDirName: projectName,
|
163 | inPlace: target === process.cwd(),
|
164 | noEscape: true
|
165 | })
|
166 | await generator(templatePath, target, metadata)
|
167 |
|
168 | }
|
169 |
|
170 | }
|
171 | }
|
172 | } |
\ | No newline at end of file |