UNPKG

4.41 kBPlain TextView Raw
1import * as fs from 'fs-extra'
2import * as path from 'path'
3import * as ora from 'ora'
4import * as AdmZip from 'adm-zip'
5import * as download from 'download-git-repo'
6import * as request from 'request'
7import { chalk } from '@tarojs/helper'
8import { TEMPLATE_CREATOR } from './init'
9
10import { getTemplateSourceType, readDirWithFileTypes } from '../util'
11
12export interface ITemplates {
13 name: string,
14 platforms?: string | string[]
15 desc?: string
16}
17
18const TEMP_DOWNLOAD_FLODER = 'taro-temp'
19
20export default function fetchTemplate (templateSource: string, templateRootPath: string, clone?: boolean): Promise<ITemplates[]> {
21 const type = getTemplateSourceType(templateSource)
22 const tempPath = path.join(templateRootPath, TEMP_DOWNLOAD_FLODER)
23 let name: string
24
25 // eslint-disable-next-line no-async-promise-executor
26 return new Promise(async (resolve) => {
27 // 下载文件的缓存目录
28 if (fs.existsSync(tempPath)) await fs.remove(tempPath)
29 await fs.mkdir(tempPath)
30
31 const spinner = ora(`正在从 ${templateSource} 拉取远程模板...`).start()
32
33 if (type === 'git') {
34 name = path.basename(templateSource)
35 download(templateSource, path.join(tempPath, name), { clone }, async error => {
36 if (error) {
37 console.log(error)
38 spinner.color = 'red'
39 spinner.fail(chalk.red('拉取远程模板仓库失败!'))
40 await fs.remove(tempPath)
41 return resolve()
42 }
43 spinner.color = 'green'
44 spinner.succeed(`${chalk.grey('拉取远程模板仓库成功!')}`)
45 resolve()
46 })
47 } else if (type === 'url') {
48 const zipPath = path.join(tempPath, 'temp.zip')
49 request
50 .get(templateSource)
51 .on('close', () => {
52 // unzip
53 const zip = new AdmZip(zipPath)
54 zip.extractAllTo(tempPath, true)
55 const files = readDirWithFileTypes(tempPath).filter(
56 file => !file.name.startsWith('.') && file.isDirectory && file.name !== '__MACOSX'
57 )
58 if (files.length !== 1) {
59 spinner.color = 'red'
60 spinner.fail(chalk.red(`拉取远程模板仓库失败!\n${new Error('远程模板源组织格式错误')}`))
61 return resolve()
62 }
63
64 name = files[0].name
65 spinner.color = 'green'
66 spinner.succeed(`${chalk.grey('拉取远程模板仓库成功!')}`)
67 resolve()
68 })
69 .on('error', async err => {
70 spinner.color = 'red'
71 spinner.fail(chalk.red(`拉取远程模板仓库失败!\n${err}`))
72 await fs.remove(tempPath)
73 return resolve()
74 })
75 .pipe(fs.createWriteStream(zipPath))
76 }
77 }).then(async () => {
78 const templateFloder = name ? path.join(tempPath, name) : ''
79
80 // 下载失败,只显示默认模板
81 if (!fs.existsSync(templateFloder)) return Promise.resolve([])
82
83 const isTemplateGroup = !fs.existsSync(path.join(templateFloder, 'package.json'))
84
85 if (isTemplateGroup) {
86 // 模板组
87 const files = readDirWithFileTypes(templateFloder)
88 .filter(file => !file.name.startsWith('.') && file.isDirectory && file.name !== '__MACOSX')
89 .map(file => file.name)
90 await Promise.all(
91 files.map(file => {
92 const src = path.join(templateFloder, file)
93 const dest = path.join(templateRootPath, file)
94 return fs.move(src, dest, { overwrite: true })
95 })
96 )
97 await fs.remove(tempPath)
98
99 const res: ITemplates[] = files.map(name => {
100 const creatorFile = path.join(templateRootPath, name, TEMPLATE_CREATOR)
101
102 if (!fs.existsSync(creatorFile)) return { name }
103
104 const { platforms = '', desc = '' } = require(creatorFile)
105
106 return {
107 name,
108 platforms,
109 desc
110 }
111 })
112 return Promise.resolve(res)
113 } else {
114 // 单模板
115 await fs.move(templateFloder, path.join(templateRootPath, name), { overwrite: true })
116 await fs.remove(tempPath)
117
118 let res: ITemplates = { name }
119 const creatorFile = path.join(templateRootPath, name, TEMPLATE_CREATOR)
120
121 if (fs.existsSync(creatorFile)) {
122 const { platforms = '', desc = '' } = require(creatorFile)
123
124 res = {
125 name,
126 platforms,
127 desc
128 }
129 }
130
131 return Promise.resolve([res])
132 }
133 })
134}