@spcsn/taro-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/LICENSE +174 -0
  2. package/README.md +0 -0
  3. package/bin/taro +7 -0
  4. package/dist/cli.d.ts +6 -0
  5. package/dist/cli.js +266 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/customCommand.d.ts +5 -0
  8. package/dist/commands/customCommand.js +23 -0
  9. package/dist/commands/customCommand.js.map +1 -0
  10. package/dist/config/index.d.ts +8 -0
  11. package/dist/config/index.js +10 -0
  12. package/dist/config/index.js.map +1 -0
  13. package/dist/config/packagesManagement.d.ts +19 -0
  14. package/dist/config/packagesManagement.js +22 -0
  15. package/dist/config/packagesManagement.js.map +1 -0
  16. package/dist/create/constants.d.ts +1 -0
  17. package/dist/create/constants.js +5 -0
  18. package/dist/create/constants.js.map +1 -0
  19. package/dist/create/creator.d.ts +9 -0
  20. package/dist/create/creator.js +64 -0
  21. package/dist/create/creator.js.map +1 -0
  22. package/dist/create/fetchTemplate.d.ts +8 -0
  23. package/dist/create/fetchTemplate.js +169 -0
  24. package/dist/create/fetchTemplate.js.map +1 -0
  25. package/dist/create/page.d.ts +65 -0
  26. package/dist/create/page.js +266 -0
  27. package/dist/create/page.js.map +1 -0
  28. package/dist/create/plugin.d.ts +16 -0
  29. package/dist/create/plugin.js +77 -0
  30. package/dist/create/plugin.js.map +1 -0
  31. package/dist/create/project.d.ts +70 -0
  32. package/dist/create/project.js +481 -0
  33. package/dist/create/project.js.map +1 -0
  34. package/dist/doctor/index.d.ts +4 -0
  35. package/dist/doctor/index.js +23 -0
  36. package/dist/doctor/index.js.map +1 -0
  37. package/dist/index.d.ts +16 -0
  38. package/dist/index.js +24 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/presets/commands/build.d.ts +3 -0
  41. package/dist/presets/commands/build.js +236 -0
  42. package/dist/presets/commands/build.js.map +1 -0
  43. package/dist/presets/commands/config.d.ts +3 -0
  44. package/dist/presets/commands/config.js +121 -0
  45. package/dist/presets/commands/config.js.map +1 -0
  46. package/dist/presets/commands/create.d.ts +3 -0
  47. package/dist/presets/commands/create.js +112 -0
  48. package/dist/presets/commands/create.js.map +1 -0
  49. package/dist/presets/commands/global-config.d.ts +3 -0
  50. package/dist/presets/commands/global-config.js +175 -0
  51. package/dist/presets/commands/global-config.js.map +1 -0
  52. package/dist/presets/commands/help.d.ts +3 -0
  53. package/dist/presets/commands/help.js +16 -0
  54. package/dist/presets/commands/help.js.map +1 -0
  55. package/dist/presets/commands/info.d.ts +3 -0
  56. package/dist/presets/commands/info.js +96 -0
  57. package/dist/presets/commands/info.js.map +1 -0
  58. package/dist/presets/commands/init.d.ts +3 -0
  59. package/dist/presets/commands/init.js +46 -0
  60. package/dist/presets/commands/init.js.map +1 -0
  61. package/dist/presets/commands/inspect.d.ts +3 -0
  62. package/dist/presets/commands/inspect.js +155 -0
  63. package/dist/presets/commands/inspect.js.map +1 -0
  64. package/dist/presets/commands/update.d.ts +3 -0
  65. package/dist/presets/commands/update.js +187 -0
  66. package/dist/presets/commands/update.js.map +1 -0
  67. package/dist/presets/constant/hooks.d.ts +13 -0
  68. package/dist/presets/constant/hooks.js +17 -0
  69. package/dist/presets/constant/hooks.js.map +1 -0
  70. package/dist/presets/constant/index.d.ts +1 -0
  71. package/dist/presets/constant/index.js +18 -0
  72. package/dist/presets/constant/index.js.map +1 -0
  73. package/dist/presets/files/generateFrameworkInfo.d.ts +3 -0
  74. package/dist/presets/files/generateFrameworkInfo.js +30 -0
  75. package/dist/presets/files/generateFrameworkInfo.js.map +1 -0
  76. package/dist/presets/files/generateProjectConfig.d.ts +3 -0
  77. package/dist/presets/files/generateProjectConfig.js +72 -0
  78. package/dist/presets/files/generateProjectConfig.js.map +1 -0
  79. package/dist/presets/files/writeFileToDist.d.ts +3 -0
  80. package/dist/presets/files/writeFileToDist.js +50 -0
  81. package/dist/presets/files/writeFileToDist.js.map +1 -0
  82. package/dist/presets/hooks/build.d.ts +3 -0
  83. package/dist/presets/hooks/build.js +55 -0
  84. package/dist/presets/hooks/build.js.map +1 -0
  85. package/dist/presets/hooks/create.d.ts +3 -0
  86. package/dist/presets/hooks/create.js +42 -0
  87. package/dist/presets/hooks/create.js.map +1 -0
  88. package/dist/presets/index.d.ts +4 -0
  89. package/dist/presets/index.js +50 -0
  90. package/dist/presets/index.js.map +1 -0
  91. package/dist/presets/platforms/plugin.d.ts +3 -0
  92. package/dist/presets/platforms/plugin.js +106 -0
  93. package/dist/presets/platforms/plugin.js.map +1 -0
  94. package/dist/presets/platforms/rn.d.ts +3 -0
  95. package/dist/presets/platforms/rn.js +130 -0
  96. package/dist/presets/platforms/rn.js.map +1 -0
  97. package/dist/util/appConfig.d.ts +11 -0
  98. package/dist/util/appConfig.js +27 -0
  99. package/dist/util/appConfig.js.map +1 -0
  100. package/dist/util/createPage.d.ts +9 -0
  101. package/dist/util/createPage.js +114 -0
  102. package/dist/util/createPage.js.map +1 -0
  103. package/dist/util/defineConfig.d.ts +17 -0
  104. package/dist/util/defineConfig.js +11 -0
  105. package/dist/util/defineConfig.js.map +1 -0
  106. package/dist/util/index.d.ts +23 -0
  107. package/dist/util/index.js +149 -0
  108. package/dist/util/index.js.map +1 -0
  109. package/dist/util/types.d.ts +58 -0
  110. package/dist/util/types.js +3 -0
  111. package/dist/util/types.js.map +1 -0
  112. package/global.d.ts +4 -0
  113. package/index.js +3 -0
  114. package/package.json +74 -0
  115. package/postinstall.js +17 -0
  116. package/src/__tests__/__mocks__/presets.ts +15 -0
  117. package/src/__tests__/build-config.spec.ts +66 -0
  118. package/src/__tests__/cli.spec.ts +226 -0
  119. package/src/__tests__/config.spec.ts +224 -0
  120. package/src/__tests__/doctor-config.spec.ts +943 -0
  121. package/src/__tests__/doctor-recommand.spec.ts +136 -0
  122. package/src/__tests__/doctor.spec.ts +94 -0
  123. package/src/__tests__/dotenv-parse.spec.ts +105 -0
  124. package/src/__tests__/env/.env +2 -0
  125. package/src/__tests__/fixtures/default/.env +3 -0
  126. package/src/__tests__/fixtures/default/.env.development +1 -0
  127. package/src/__tests__/fixtures/default/.env.local +1 -0
  128. package/src/__tests__/fixtures/default/.env.pre +3 -0
  129. package/src/__tests__/fixtures/default/.env.production +1 -0
  130. package/src/__tests__/fixtures/default/.env.uat +5 -0
  131. package/src/__tests__/fixtures/default/.env.uat.local +1 -0
  132. package/src/__tests__/fixtures/default/babel.config.js +10 -0
  133. package/src/__tests__/fixtures/default/config/dev.js +9 -0
  134. package/src/__tests__/fixtures/default/config/index.js +84 -0
  135. package/src/__tests__/fixtures/default/config/prod.js +18 -0
  136. package/src/__tests__/fixtures/default/package.json +27 -0
  137. package/src/__tests__/fixtures/default/src/app.config.js +11 -0
  138. package/src/__tests__/fixtures/default/src/app.js +16 -0
  139. package/src/__tests__/fixtures/default/src/app.scss +0 -0
  140. package/src/__tests__/fixtures/default/src/index.html +19 -0
  141. package/src/__tests__/fixtures/default/src/pages/index/index.config.js +3 -0
  142. package/src/__tests__/fixtures/default/src/pages/index/index.jsx +22 -0
  143. package/src/__tests__/fixtures/default/src/pages/index/index.scss +0 -0
  144. package/src/__tests__/info.spec.ts +72 -0
  145. package/src/__tests__/inspect.spec.ts +160 -0
  146. package/src/__tests__/update.spec.ts +310 -0
  147. package/src/__tests__/utils/index.ts +54 -0
  148. package/src/cli.ts +240 -0
  149. package/src/commands/customCommand.ts +22 -0
  150. package/src/config/index.ts +7 -0
  151. package/src/config/manifest.default.json +33 -0
  152. package/src/config/packagesManagement.ts +20 -0
  153. package/src/config/rn-stylelint.json +4 -0
  154. package/src/config/tsconfig.json +22 -0
  155. package/src/create/constants.ts +1 -0
  156. package/src/create/creator.ts +37 -0
  157. package/src/create/fetchTemplate.ts +161 -0
  158. package/src/create/page.ts +325 -0
  159. package/src/create/plugin.ts +55 -0
  160. package/src/create/project.ts +539 -0
  161. package/src/doctor/index.ts +21 -0
  162. package/src/index.ts +24 -0
  163. package/src/presets/commands/build.ts +215 -0
  164. package/src/presets/commands/config.ts +86 -0
  165. package/src/presets/commands/create.ts +104 -0
  166. package/src/presets/commands/global-config.ts +140 -0
  167. package/src/presets/commands/help.ts +17 -0
  168. package/src/presets/commands/info.ts +81 -0
  169. package/src/presets/commands/init.ts +63 -0
  170. package/src/presets/commands/inspect.ts +137 -0
  171. package/src/presets/commands/update.ts +175 -0
  172. package/src/presets/constant/hooks.ts +14 -0
  173. package/src/presets/constant/index.ts +1 -0
  174. package/src/presets/files/generateFrameworkInfo.ts +30 -0
  175. package/src/presets/files/generateProjectConfig.ts +41 -0
  176. package/src/presets/files/writeFileToDist.ts +17 -0
  177. package/src/presets/hooks/build.ts +22 -0
  178. package/src/presets/hooks/create.ts +9 -0
  179. package/src/presets/index.ts +15 -0
  180. package/src/presets/platforms/plugin.ts +75 -0
  181. package/src/presets/platforms/rn.ts +125 -0
  182. package/src/util/appConfig.ts +32 -0
  183. package/src/util/createPage.ts +139 -0
  184. package/src/util/defineConfig.ts +28 -0
  185. package/src/util/index.ts +126 -0
  186. package/src/util/types.ts +81 -0
  187. package/templates/default/_editorconfig +12 -0
  188. package/templates/default/_env.development +2 -0
  189. package/templates/default/_env.production +1 -0
  190. package/templates/default/_env.test +1 -0
  191. package/templates/default/_gitignore +8 -0
  192. package/templates/default/babel.config.js +14 -0
  193. package/templates/default/config/dev.js +5 -0
  194. package/templates/default/config/index.js +61 -0
  195. package/templates/default/config/prod.js +5 -0
  196. package/templates/default/package.json.tmpl +52 -0
  197. package/templates/default/project.config.json +15 -0
  198. package/templates/default/src/app.config.js +11 -0
  199. package/templates/default/src/app.css +0 -0
  200. package/templates/default/src/app.js +15 -0
  201. package/templates/default/src/pages/index/index.config.js +3 -0
  202. package/templates/default/src/pages/index/index.css +0 -0
  203. package/templates/default/src/pages/index/index.jsx +15 -0
  204. package/templates/default/template_creator.js +61 -0
  205. package/templates/default/tsconfig.json +30 -0
  206. package/templates/default/types/global.d.ts +27 -0
  207. package/templates/global-config/index.json +4 -0
  208. package/templates/global-config/package.json +5 -0
  209. package/templates/plugin-compile/README.md +32 -0
  210. package/templates/plugin-compile/index.js +3 -0
  211. package/templates/plugin-compile/package.json.tmpl +43 -0
  212. package/templates/plugin-compile/src/index.ts +153 -0
  213. package/templates/plugin-compile/tsconfig.json +28 -0
@@ -0,0 +1,539 @@
1
+ import * as path from 'node:path';
2
+
3
+ import { CompilerType, createProject, CSSType, FrameworkType, NpmType, PeriodType } from '@spcsn/taro-binding';
4
+ import {
5
+ chalk,
6
+ DEFAULT_TEMPLATE_SRC,
7
+ DEFAULT_TEMPLATE_SRC_GITEE,
8
+ fs,
9
+ getUserHomeDir,
10
+ SOURCE_DIR,
11
+ TARO_BASE_CONFIG,
12
+ TARO_CONFIG_FOLDER,
13
+ } from '@spcsn/taro-helper';
14
+ import { isArray } from '@spcsn/taro-shared';
15
+ import axios from 'axios';
16
+ import * as inquirer from 'inquirer';
17
+ import ora from 'ora';
18
+ import * as semver from 'semver';
19
+
20
+ import { clearConsole, getPkgVersion, getRootPath } from '../util';
21
+ import { TEMPLATE_CREATOR } from './constants';
22
+ import Creator from './creator';
23
+ import fetchTemplate from './fetchTemplate';
24
+
25
+ import type { ITemplates } from './fetchTemplate';
26
+
27
+ export interface IProjectConf {
28
+ projectName: string;
29
+ projectDir: string;
30
+ npm: NpmType;
31
+ templateSource: string;
32
+ clone?: boolean;
33
+ template: string;
34
+ description?: string;
35
+ typescript?: boolean;
36
+ buildEs5?: boolean;
37
+ css: CSSType;
38
+ date?: string;
39
+ src?: string;
40
+ sourceRoot?: string;
41
+ env?: string;
42
+ autoInstall?: boolean;
43
+ hideDefaultTemplate?: boolean;
44
+ framework: FrameworkType;
45
+ compiler?: CompilerType;
46
+ ask?: (config: object) => Promise<void> | void;
47
+ }
48
+
49
+ type CustomPartial<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
50
+
51
+ type IProjectConfOptions = CustomPartial<
52
+ IProjectConf,
53
+ 'projectName' | 'projectDir' | 'template' | 'css' | 'npm' | 'framework' | 'templateSource'
54
+ >;
55
+
56
+ interface AskMethods {
57
+ (conf: IProjectConfOptions, prompts: Record<string, unknown>[], choices?: ITemplates[]): void;
58
+ }
59
+
60
+ const NONE_AVAILABLE_TEMPLATE = '无可用模板';
61
+ const SUPPORTED_FRAMEWORK = FrameworkType.React;
62
+ const SUPPORTED_COMPILER = CompilerType.Vite;
63
+
64
+ export default class Project extends Creator {
65
+ public rootPath: string;
66
+ public conf: IProjectConfOptions;
67
+
68
+ constructor(options: IProjectConfOptions) {
69
+ super(options.sourceRoot);
70
+ const unSupportedVer = semver.lt(process.version, 'v18.0.0');
71
+ if (unSupportedVer) {
72
+ throw new Error('Node.js 版本过低,推荐升级 Node.js 至 v18.0.0+');
73
+ }
74
+ this.rootPath = this._rootPath;
75
+
76
+ this.conf = Object.assign(
77
+ {
78
+ projectName: '',
79
+ projectDir: '',
80
+ template: '',
81
+ description: '',
82
+ npm: '',
83
+ },
84
+ options,
85
+ );
86
+ }
87
+
88
+ init() {
89
+ clearConsole();
90
+ console.log(chalk.green('Taro 即将创建一个新项目!'));
91
+ console.log(`Need help? Go and open issue: ${chalk.blueBright('https://tls.jd.com/taro-issue-helper')}`);
92
+ console.log();
93
+ }
94
+
95
+ async create() {
96
+ try {
97
+ const answers = await this.ask();
98
+ const date = new Date();
99
+ this.conf = Object.assign(this.conf, answers);
100
+ this.conf.date = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
101
+ this.write();
102
+ } catch (error) {
103
+ console.log(chalk.red('创建项目失败: ', error));
104
+ }
105
+ }
106
+
107
+ async ask() {
108
+ let prompts: Record<string, unknown>[] = [];
109
+ const conf = this.conf;
110
+
111
+ this.askProjectName(conf, prompts);
112
+ this.askDescription(conf, prompts);
113
+ this.askTypescript(conf, prompts);
114
+ this.askBuildEs5(conf, prompts);
115
+ this.askCSS(conf, prompts);
116
+ this.askNpm(conf, prompts);
117
+ const answers = await inquirer.prompt<IProjectConf>(prompts);
118
+
119
+ if (conf.framework && conf.framework !== SUPPORTED_FRAMEWORK) {
120
+ console.log(chalk.yellow('当前 Fork 仅支持 React 模板,将自动切换为 React。'));
121
+ }
122
+ if (conf.compiler && conf.compiler !== SUPPORTED_COMPILER) {
123
+ console.log(chalk.yellow('当前 Fork 仅支持 Vite 编译,将自动切换为 Vite。'));
124
+ }
125
+ answers.framework = SUPPORTED_FRAMEWORK;
126
+ answers.compiler = SUPPORTED_COMPILER;
127
+
128
+ prompts = [];
129
+ await this.askTemplateSource(conf, prompts);
130
+ const compilerAndTemplateSourceAnswer = await inquirer.prompt<IProjectConf>(prompts);
131
+ compilerAndTemplateSourceAnswer.compiler = SUPPORTED_COMPILER;
132
+
133
+ prompts = [];
134
+ const templates = await this.fetchTemplates(Object.assign({}, answers, compilerAndTemplateSourceAnswer));
135
+ await this.askTemplate(conf, prompts, templates);
136
+ const templateChoiceAnswer = await inquirer.prompt<IProjectConf>(prompts);
137
+
138
+ // 导航步骤扩展
139
+ try {
140
+ if (typeof conf.ask === 'function') {
141
+ const { ask, ...other } = conf;
142
+ await ask({ ...other, templatePath: this.templatePath(templateChoiceAnswer.template) });
143
+ }
144
+ } catch (e) {
145
+ console.error(e);
146
+ }
147
+
148
+ return {
149
+ ...answers,
150
+ ...compilerAndTemplateSourceAnswer,
151
+ ...templateChoiceAnswer,
152
+ };
153
+ }
154
+
155
+ askProjectName: AskMethods = function (conf, prompts) {
156
+ if (typeof conf.projectName !== 'string') {
157
+ prompts.push({
158
+ type: 'input',
159
+ name: 'projectName',
160
+ message: '请输入项目名称!',
161
+ validate(input) {
162
+ if (!input) {
163
+ return '项目名不能为空!';
164
+ }
165
+ if (fs.existsSync(input)) {
166
+ return '当前目录已经存在同名项目,请换一个项目名!';
167
+ }
168
+ return true;
169
+ },
170
+ });
171
+ } else if (fs.existsSync(conf.projectName!)) {
172
+ prompts.push({
173
+ type: 'input',
174
+ name: 'projectName',
175
+ message: '当前目录已经存在同名项目,请换一个项目名!',
176
+ validate(input) {
177
+ if (!input) {
178
+ return '项目名不能为空!';
179
+ }
180
+ if (fs.existsSync(input)) {
181
+ return '项目名依然重复!';
182
+ }
183
+ return true;
184
+ },
185
+ });
186
+ }
187
+ };
188
+
189
+ askDescription: AskMethods = function (conf, prompts) {
190
+ if (typeof conf.description !== 'string') {
191
+ prompts.push({
192
+ type: 'input',
193
+ name: 'description',
194
+ message: '请输入项目介绍',
195
+ });
196
+ }
197
+ };
198
+
199
+ askTypescript: AskMethods = function (conf, prompts) {
200
+ if (typeof conf.typescript !== 'boolean') {
201
+ prompts.push({
202
+ type: 'confirm',
203
+ name: 'typescript',
204
+ message: '是否需要使用 TypeScript ?',
205
+ });
206
+ }
207
+ };
208
+
209
+ askBuildEs5: AskMethods = function (conf, prompts) {
210
+ if (typeof conf.buildEs5 !== 'boolean') {
211
+ prompts.push({
212
+ type: 'confirm',
213
+ name: 'buildEs5',
214
+ message: '是否需要编译为 ES5 ?',
215
+ default: false,
216
+ });
217
+ }
218
+ };
219
+
220
+ askCSS: AskMethods = function (conf, prompts) {
221
+ const cssChoices = [
222
+ {
223
+ name: 'Sass',
224
+ value: CSSType.Sass,
225
+ },
226
+ {
227
+ name: 'Less',
228
+ value: CSSType.Less,
229
+ },
230
+ {
231
+ name: 'Stylus',
232
+ value: CSSType.Stylus,
233
+ },
234
+ {
235
+ name: '无',
236
+ value: CSSType.None,
237
+ },
238
+ ];
239
+
240
+ if (typeof conf.css !== 'string') {
241
+ prompts.push({
242
+ type: 'list',
243
+ name: 'css',
244
+ message: '请选择 CSS 预处理器(Sass/Less/Stylus)',
245
+ choices: cssChoices,
246
+ });
247
+ }
248
+ };
249
+
250
+ askCompiler: AskMethods = function (conf, prompts) {
251
+ const compilerChoices = [
252
+ {
253
+ name: 'Webpack5',
254
+ value: CompilerType.Webpack5,
255
+ },
256
+ {
257
+ name: 'Vite',
258
+ value: CompilerType.Vite,
259
+ },
260
+ ];
261
+
262
+ if (typeof conf.compiler !== 'string') {
263
+ prompts.push({
264
+ type: 'list',
265
+ name: 'compiler',
266
+ message: '请选择编译工具',
267
+ choices: compilerChoices,
268
+ });
269
+ }
270
+ };
271
+
272
+ askFramework: AskMethods = function (conf, prompts) {
273
+ const frameworks = [
274
+ {
275
+ name: 'React',
276
+ value: FrameworkType.React,
277
+ },
278
+ {
279
+ name: 'PReact',
280
+ value: FrameworkType.Preact,
281
+ },
282
+ {
283
+ name: 'Vue3',
284
+ value: FrameworkType.Vue3,
285
+ },
286
+ {
287
+ name: 'Solid',
288
+ value: FrameworkType.Solid,
289
+ },
290
+ ];
291
+
292
+ if (typeof conf.framework !== 'string') {
293
+ prompts.push({
294
+ type: 'list',
295
+ name: 'framework',
296
+ message: '请选择框架',
297
+ choices: frameworks,
298
+ });
299
+ }
300
+ };
301
+
302
+ askTemplateSource: AskMethods = async function (conf, prompts) {
303
+ if (conf.template === 'default' || conf.templateSource) return;
304
+
305
+ const homedir = getUserHomeDir();
306
+ const taroConfigPath = path.join(homedir, TARO_CONFIG_FOLDER);
307
+ const taroConfig = path.join(taroConfigPath, TARO_BASE_CONFIG);
308
+
309
+ let localTemplateSource: string;
310
+
311
+ // 检查本地配置
312
+ if (fs.existsSync(taroConfig)) {
313
+ // 存在则把模板源读出来
314
+ const config = await fs.readJSON(taroConfig);
315
+ localTemplateSource = config?.templateSource;
316
+ } else {
317
+ // 不存在则创建配置
318
+ await fs.createFile(taroConfig);
319
+ await fs.writeJSON(taroConfig, { templateSource: DEFAULT_TEMPLATE_SRC });
320
+ localTemplateSource = DEFAULT_TEMPLATE_SRC;
321
+ }
322
+
323
+ const choices = [
324
+ {
325
+ name: 'Gitee(最快)',
326
+ value: DEFAULT_TEMPLATE_SRC_GITEE,
327
+ },
328
+ {
329
+ name: 'Github(最新)',
330
+ value: DEFAULT_TEMPLATE_SRC,
331
+ },
332
+ {
333
+ name: 'CLI 内置默认模板',
334
+ value: 'default-template',
335
+ },
336
+ {
337
+ name: '自定义',
338
+ value: 'self-input',
339
+ },
340
+ {
341
+ name: '社区优质模板源',
342
+ value: 'open-source',
343
+ },
344
+ ];
345
+
346
+ if (
347
+ localTemplateSource &&
348
+ localTemplateSource !== DEFAULT_TEMPLATE_SRC &&
349
+ localTemplateSource !== DEFAULT_TEMPLATE_SRC_GITEE
350
+ ) {
351
+ choices.unshift({
352
+ name: `本地模板源:${localTemplateSource}`,
353
+ value: localTemplateSource,
354
+ });
355
+ }
356
+
357
+ prompts.push(
358
+ {
359
+ type: 'list',
360
+ name: 'templateSource',
361
+ message: '请选择模板源',
362
+ choices,
363
+ },
364
+ {
365
+ type: 'input',
366
+ name: 'templateSource',
367
+ message: '请输入模板源!',
368
+ askAnswered: true,
369
+ when(answers) {
370
+ return answers.templateSource === 'self-input';
371
+ },
372
+ },
373
+ {
374
+ type: 'list',
375
+ name: 'templateSource',
376
+ message: '请选择社区模板源',
377
+ async choices(answers) {
378
+ const choices = await getOpenSourceTemplates(answers.framework);
379
+ return choices;
380
+ },
381
+ askAnswered: true,
382
+ when(answers) {
383
+ return answers.templateSource === 'open-source';
384
+ },
385
+ },
386
+ );
387
+ };
388
+
389
+ askTemplate: AskMethods = function (conf, prompts, list = []) {
390
+ const choices = list.map((item) => ({
391
+ name: item.desc ? `${item.name}(${item.desc})` : item.name,
392
+ value: item.value || item.name,
393
+ }));
394
+
395
+ if (!conf.hideDefaultTemplate) {
396
+ choices.unshift({
397
+ name: '默认模板',
398
+ value: 'default',
399
+ });
400
+ }
401
+
402
+ if ((typeof conf.template as 'string' | undefined) !== 'string') {
403
+ prompts.push({
404
+ type: 'list',
405
+ name: 'template',
406
+ message: '请选择模板',
407
+ choices,
408
+ });
409
+ }
410
+ };
411
+
412
+ askNpm: AskMethods = function (conf, prompts) {
413
+ const packages = [
414
+ {
415
+ name: 'yarn',
416
+ value: NpmType.Yarn,
417
+ },
418
+ {
419
+ name: 'pnpm',
420
+ value: NpmType.Pnpm,
421
+ },
422
+ {
423
+ name: 'npm',
424
+ value: NpmType.Npm,
425
+ },
426
+ {
427
+ name: 'cnpm',
428
+ value: NpmType.Cnpm,
429
+ },
430
+ ];
431
+
432
+ if ((typeof conf.npm as string | undefined) !== 'string') {
433
+ prompts.push({
434
+ type: 'list',
435
+ name: 'npm',
436
+ message: '请选择包管理工具',
437
+ choices: packages,
438
+ });
439
+ }
440
+ };
441
+
442
+ async fetchTemplates(answers: IProjectConf): Promise<ITemplates[]> {
443
+ const { templateSource, framework, compiler } = answers;
444
+ this.conf.framework = this.conf.framework || framework || '';
445
+ this.conf.templateSource = this.conf.templateSource || templateSource;
446
+
447
+ // 使用默认模版
448
+ if (answers.templateSource === 'default-template') {
449
+ this.conf.template = 'default';
450
+ answers.templateSource = DEFAULT_TEMPLATE_SRC_GITEE;
451
+ }
452
+ if (this.conf.template === 'default' || answers.templateSource === NONE_AVAILABLE_TEMPLATE)
453
+ return Promise.resolve([]);
454
+
455
+ // 从模板源下载模板
456
+ const isClone = /gitee/.test(this.conf.templateSource) || this.conf.clone;
457
+ const templateChoices = await fetchTemplate(this.conf.templateSource, this.templatePath(''), isClone);
458
+
459
+ const filterFramework = (_framework) => {
460
+ const current = this.conf.framework?.toLowerCase();
461
+
462
+ if (typeof _framework === 'string' && _framework) {
463
+ return current === _framework.toLowerCase();
464
+ } else if (isArray(_framework)) {
465
+ return _framework?.map((name) => name.toLowerCase()).includes(current);
466
+ } else {
467
+ return true;
468
+ }
469
+ };
470
+
471
+ const filterCompiler = (_compiler) => {
472
+ if (_compiler && isArray(_compiler)) {
473
+ return _compiler?.includes(compiler);
474
+ }
475
+ return true;
476
+ };
477
+
478
+ // 根据用户选择的框架筛选模板
479
+ const newTemplateChoices: ITemplates[] = templateChoices.filter((templateChoice) => {
480
+ const { platforms, compiler } = templateChoice;
481
+ return filterFramework(platforms) && filterCompiler(compiler);
482
+ });
483
+
484
+ return newTemplateChoices;
485
+ }
486
+
487
+ write(cb?: () => void) {
488
+ this.conf.src = SOURCE_DIR;
489
+ const { projectName, projectDir, template, autoInstall = true, framework, npm } = this.conf as IProjectConf;
490
+ // 引入模板编写者的自定义逻辑
491
+ const templatePath = this.templatePath(template);
492
+ const handlerPath = path.join(templatePath, TEMPLATE_CREATOR);
493
+ const handler = fs.existsSync(handlerPath) ? require(handlerPath).handler : {};
494
+ createProject(
495
+ {
496
+ projectRoot: projectDir,
497
+ projectName,
498
+ template,
499
+ npm,
500
+ framework,
501
+ css: this.conf.css || CSSType.None,
502
+ autoInstall: autoInstall,
503
+ templateRoot: getRootPath(),
504
+ version: getPkgVersion(),
505
+ typescript: this.conf.typescript,
506
+ buildEs5: this.conf.buildEs5,
507
+ date: this.conf.date,
508
+ description: this.conf.description,
509
+ compiler: this.conf.compiler,
510
+ period: PeriodType.CreateAPP,
511
+ },
512
+ handler,
513
+ ).then(() => {
514
+ cb && cb();
515
+ });
516
+ }
517
+ }
518
+
519
+ function getOpenSourceTemplates(platform: string) {
520
+ return new Promise((resolve, reject) => {
521
+ const spinner = ora({ text: '正在拉取开源模板列表...', discardStdin: false }).start();
522
+ axios
523
+ .get('https://gitee.com/NervJS/awesome-taro/raw/next/index.json')
524
+ .then((response) => {
525
+ spinner.succeed(`${chalk.grey('拉取开源模板列表成功!')}`);
526
+ const collection = response.data;
527
+ switch (platform.toLowerCase()) {
528
+ case 'react':
529
+ return resolve(collection.react);
530
+ default:
531
+ return resolve([NONE_AVAILABLE_TEMPLATE]);
532
+ }
533
+ })
534
+ .catch((_error) => {
535
+ spinner.fail(chalk.red('拉取开源模板列表失败!'));
536
+ return reject(new Error());
537
+ });
538
+ });
539
+ }
@@ -0,0 +1,21 @@
1
+ import { validateConfig, validateEnv, validateEslint, validatePackage, validateRecommend } from '@tarojs/plugin-doctor';
2
+
3
+ export default {
4
+ validators: [
5
+ () => {
6
+ return validateEnv.call(this);
7
+ },
8
+ (args) => {
9
+ return validateConfig.call(this, args.projectConfig, args.helper);
10
+ },
11
+ (args) => {
12
+ return validatePackage.call(this, args.appPath, args.nodeModulesPath);
13
+ },
14
+ (args) => {
15
+ return validateRecommend.call(this, args.appPath);
16
+ },
17
+ async (args) => {
18
+ return await validateEslint.call(this, args.projectConfig, args.chalk);
19
+ },
20
+ ],
21
+ };
package/src/index.ts ADDED
@@ -0,0 +1,24 @@
1
+ import Creator from './create/creator';
2
+ import Project from './create/project';
3
+ import doctor from './doctor';
4
+ import { getRootPath } from './util';
5
+ import { type ConfigEnv, type UserConfigExport, type UserConfigFn, defineConfig } from './util/defineConfig';
6
+
7
+ export default {
8
+ doctor,
9
+ Project,
10
+ Creator,
11
+ defineConfig,
12
+ getRootPath,
13
+ };
14
+
15
+ export {
16
+ type ConfigEnv,
17
+ type UserConfigExport,
18
+ type UserConfigFn,
19
+ Creator,
20
+ defineConfig,
21
+ doctor,
22
+ getRootPath,
23
+ Project,
24
+ };