1 | const {generator, clone, getOptions} = require('../index')
|
2 | const debug = require('debug')('create')
|
3 | const fse = require('fs-extra')
|
4 | const path = require('path')
|
5 | const async = require('async')
|
6 | const {
|
7 | localpath
|
8 | } = require('../lib/utils/localpath')
|
9 | const {
|
10 | evaluate
|
11 | } = require('../lib/utils/eval')
|
12 |
|
13 | const exists = fse.existsSync
|
14 |
|
15 |
|
16 | module.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 |
|
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 |
|
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 |
|
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 |
|
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) {
|
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 |