UNPKG

10.7 kBJavaScriptView Raw
1const {generator, clone, getOptions} = require('../index')
2const debug = require('debug')('create')
3const fse = require('fs-extra')
4const path = require('path')
5const async = require('async')
6const {
7 localpath
8} = require('../lib/utils/localpath')
9const {
10 evaluate
11} = require('../lib/utils/eval')
12
13const exists = fse.existsSync
14
15
16module.exports = {
17 name: 'platform',
18 description: 'Manage iOS/Android project',
19 run: async (
20 {
21 logger,
22 parameters,
23 inquirer,
24 meta
25 }
26 ) => {
27 const first = parameters.first
28 const second = parameters.second
29 const third = parameters.third
30 const options = parameters.options
31 const array = parameters.array
32 const globalConfig = options.__config
33 const platformConfigFile = path.join(process.cwd(), globalConfig.defaultWeexPlatformFloder || 'platforms', globalConfig.platformConfigName || 'platforms.json')
34 const platformFloder = path.join(process.cwd(), globalConfig.defaultWeexPlatformFloder || 'platforms')
35 // Support types from prompt-for which was used before
36 const promptMapping = {
37 string: 'input',
38 boolean: 'confirm'
39 };
40
41 const DEFAULT_TEMPLATES = globalConfig.defaultWeexPlatformTemplate || {
42 ios: 'weex-playground-ios',
43 android: 'weex-playground-android'
44 }
45
46 const PLATFORMS = globalConfig.defaultWeexPlatforms || ['ios', 'android']
47
48 const askQuestion = async (name, templatePath) => {
49 debug(`Render from local path ${templatePath}`)
50 const meta = getOptions(name, templatePath)
51 let propmts = []
52 let keys = Object.keys(meta.prompts)
53 if (keys.length <= 2) {
54 return meta
55 }
56 keys.forEach(key => {
57 let prompt = meta.prompts[key]
58 promptDefault = typeof prompt.default !== 'undefined' ? prompt.default : ''
59 propmts.push({
60 type: promptMapping[prompt.type] || prompt.type,
61 name: key,
62 message: prompt.message || prompt.label || key,
63 default: promptDefault,
64 choices: prompt.choices || [],
65 validate: prompt.validate || (() => true)
66 })
67 })
68 let answer = await inquirer.prompt(propmts)
69 // assign metadata to answer
70 return Object.assign(meta, answer)
71 }
72
73 const add = async (platform, template) => {
74 let target = path.resolve(globalConfig.defaultWeexPlatformFloder || 'platforms', platform);
75 let templatePath = template
76 if (exists(target)) {
77 let res = await inquirer.prompt([{
78 type: 'confirm',
79 message: `The ${platform} project exists. Continue?`,
80 name: 'yes'
81 }])
82 if (res.yes) {
83 let spinner = logger.spin(`Remove ${target} ...`);
84 await fse.remove(target);
85 spinner.stop();
86 } else {
87 return
88 }
89 }
90 if (!template) {
91 template = DEFAULT_TEMPLATES[platform]
92 }
93 if (localpath.isLocalPath(template)) {
94 templatePath = localpath.getTemplatePath(template);
95 if (exists(templatePath)) {
96 let answer = await askQuestion(platform, templatePath)
97 let metadata = Object.assign(answer, {
98 destDirName: platform,
99 inPlace: target === process.cwd(),
100 noEscape: true
101 })
102 await generator(templatePath, target, metadata)
103 } else {
104 logger.error(`Local template "${templatePath}" not found`);
105 }
106 } else {
107 const hasHash = /\//.test(template)
108 if (!hasHash) {
109 // fetch from official repo
110 template = `${globalConfig.defaultWeexTemplateRepo || 'weex-templates'}/${template}`
111 }
112 const templatesTarget = path.join(globalConfig.templatePath, template)
113 let spinner = logger.spin(`Download from ${template} repo ...`);
114 templatePath = await clone(template, templatesTarget, {
115 cache: exists(templatesTarget) && (typeof options.cache === 'boolean' ? options.cache : true),
116 clone: options.clone || false
117 })
118 spinner.stop();
119 let answer = await askQuestion(platform, templatePath)
120 let metadata = Object.assign(answer, {
121 destDirName: platform,
122 inPlace: target === process.cwd(),
123 noEscape: true
124 })
125 await generator(templatePath, target, metadata)
126 }
127 await updatePlatformConfig(platform, templatePath)
128 logger.success(`${logger.checkmark} Add ${platform} project success`)
129 }
130
131 const remove = async (platform) => {
132 const project = `${platformFloder}/${platform}`
133 const exist = await fse.exists(project)
134 if (exist) {
135 let spinner = logger.spin(`Platform ${platform} detated, try to remove ...`);
136 await fse.remove(project)
137 await updatePlatformConfig(platform, '', true)
138 spinner.stop();
139 logger.success(`${logger.checkmark} Remove ${platform} project success`)
140 } else {
141 logger.warn(`Current workspace has not ${platform} project, please check`)
142 }
143 }
144
145 const list = async () => {
146 const platformMetaData = await fse.readJson(platformConfigFile)
147 logger.success(`Installed:`)
148 Object.keys(platformMetaData).forEach(key => {
149 if (PLATFORMS.indexOf(key) >= 0) {
150 logger.log(`- ${key}@${platformMetaData[key]}`)
151 }
152 })
153 logger.success('Supported:')
154 PLATFORMS.forEach(platform => {
155 logger.log(`- ${platform}`)
156 })
157 }
158
159 const update = async (platform, template) => {
160 let target = path.resolve(globalConfig.defaultWeexPlatformFloder || 'platforms', platform);
161 let templatePath = template
162 if (!template) {
163 template = DEFAULT_TEMPLATES[platform]
164 }
165 if (localpath.isLocalPath(template)) {
166 templatePath = localpath.getTemplatePath(template);
167 if (exists(templatePath)) {
168 let answer = await askQuestion(platform, templatePath)
169 let metadata = Object.assign(answer, {
170 destDirName: platform,
171 inPlace: target === process.cwd(),
172 noEscape: true
173 })
174 await generator(templatePath, target, metadata)
175 } else {
176 logger.error(`Local template "${templatePath}" not found`);
177 }
178 } else {
179 const hasHash = /\//.test(template)
180 if (!hasHash) {
181 // fetch from official repo
182 template = `${globalConfig.defaultWeexTemplateRepo || 'weex-templates'}/${template}`
183 }
184 const templatesTarget = path.join(globalConfig.templatePath, template)
185 let spinner = logger.spin(`Download from ${template} repo ...`);
186 templatePath = await clone(template, templatesTarget, {
187 cache: false,
188 clone: options.clone || false
189 })
190 spinner.stop();
191 let answer = await askQuestion(platform, templatePath)
192 let metadata = Object.assign(answer, {
193 destDirName: platform,
194 inPlace: target === process.cwd(),
195 noEscape: true
196 })
197 await generator(templatePath, target, metadata)
198 }
199 await updatePlatformConfig(platform, templatePath)
200 logger.success(`${logger.checkmark} Update ${platform} project success`)
201 }
202
203 const updatePlatformConfig = async (platform, template, del) => {
204 let package
205 const exist = await fse.exists(platformConfigFile)
206 let json
207 if (exist) {
208 json = await fse.readJson(platformConfigFile, { throws: false })
209 } else {
210 json = {}
211 }
212 if (del) {
213 delete json[platform]
214 }
215 else {
216 try {
217 package = require(`${template}/package.json`)
218 } catch(e) {
219 package = {
220 version: 'unkown'
221 }
222 }
223 json[platform] = package.version
224 }
225 await fse.outputJson(platformConfigFile, json, {spaces: '\t'})
226 }
227
228 const showHelp = async () => {
229 let params = {
230 commandend: 'Manage iOS/Android project',
231 commands: [{
232 heading: ['Usage', 'Description']
233 },
234 {
235 key: 'platform add',
236 type:'[ios|android]',
237 description: 'Create a official ios or weex project'
238 },
239 {
240 key: 'platform add',
241 type:'<template | git-repo> [ios|android]',
242 description: 'Create a ios or weex project with a specify template name or git repo'
243 },
244 {
245 key: 'platform remove',
246 type:'[ios|android]',
247 description: 'Remove ios or weex project'
248 },
249 {
250 key: 'platform update',
251 type:'[ios|android]',
252 description: 'Update ios or weex project'
253 },
254 {
255 key: 'platform list',
256 description: 'List all platform supported and installed'
257 },
258 ],
259 options: {
260 'Base': [{
261 key: '--no-cache',
262 description: 'Fetching latest template with no cache'
263 }, {
264 key: '--clone',
265 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'
266 }],
267 'Miscellaneous:': [{
268 key: '-v, --version',
269 description: 'Output the version number'
270 },
271 {
272 key: '-h, --help',
273 description: 'Show help'
274 }
275 ]
276 }
277 }
278 meta.generateHelp(params)
279 }
280
281 const isWeexWorkSpace = async (local) => {
282 const isWeex = await fse.exists(path.join(local, 'platforms'))
283 return isWeex
284 }
285
286 if (options.version || options.v) { // version from package.json
287
288 logger.info(`${require("../package.json").version}`);
289
290 } else if (options.help || options.h) {
291 await showHelp()
292 } else {
293 let command = first
294 let platform = second
295 let template
296
297 if (array.length >= 3) {
298 template = second
299 command = first
300 platform = third
301 }
302
303 if (!isWeexWorkSpace(process.cwd())) {
304 logger.error('The current directory is not the project directory of weex, please check')
305 return
306 }
307
308 switch(command) {
309 case 'add':
310 await add(platform, template);
311 break;
312 case 'remove':
313 await remove(platform);
314 break;
315 case 'update':
316 await update(platform, template);
317 break;
318 case 'list':
319 await list();
320 break;
321 default:
322 await showHelp();
323 break;
324 }
325
326 }
327 }
328}
\No newline at end of file