@spcsn/taro-cli 0.1.6 → 1.0.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 (188) hide show
  1. package/README.md +10 -7
  2. package/define-config.d.ts +1 -0
  3. package/define-config.js +1 -0
  4. package/dist/cli.js +140 -110
  5. package/dist/cli.js.map +1 -1
  6. package/dist/commands/{customCommand.d.ts → custom-command.d.ts} +1 -1
  7. package/dist/commands/custom-command.js +23 -0
  8. package/dist/commands/custom-command.js.map +1 -0
  9. package/dist/create/creator.js +2 -0
  10. package/dist/create/creator.js.map +1 -1
  11. package/dist/create/{fetchTemplate.js → fetch-template.js} +26 -33
  12. package/dist/create/fetch-template.js.map +1 -0
  13. package/dist/create/project.d.ts +2 -6
  14. package/dist/create/project.js +240 -285
  15. package/dist/create/project.js.map +1 -1
  16. package/dist/create/template-creator.d.ts +75 -0
  17. package/dist/create/template-creator.js +275 -0
  18. package/dist/create/template-creator.js.map +1 -0
  19. package/dist/doctor/validators.d.ts +7 -6
  20. package/dist/doctor/validators.js +6 -7
  21. package/dist/doctor/validators.js.map +1 -1
  22. package/dist/platform-weapp/apis-list.d.ts +1 -0
  23. package/dist/platform-weapp/apis-list.js +37 -0
  24. package/dist/platform-weapp/apis-list.js.map +1 -0
  25. package/dist/platform-weapp/apis.d.ts +16 -0
  26. package/dist/platform-weapp/apis.js +34 -0
  27. package/dist/platform-weapp/apis.js.map +1 -0
  28. package/dist/platform-weapp/components-react.d.ts +80 -0
  29. package/dist/platform-weapp/components-react.js +86 -0
  30. package/dist/platform-weapp/components-react.js.map +1 -0
  31. package/dist/platform-weapp/components.d.ts +4 -0
  32. package/dist/platform-weapp/components.js +520 -0
  33. package/dist/platform-weapp/components.js.map +1 -0
  34. package/dist/platform-weapp/index.d.ts +11 -0
  35. package/dist/platform-weapp/index.js +17 -0
  36. package/dist/platform-weapp/index.js.map +1 -0
  37. package/dist/platform-weapp/program.d.ts +35 -0
  38. package/dist/platform-weapp/program.js +64 -0
  39. package/dist/platform-weapp/program.js.map +1 -0
  40. package/dist/platform-weapp/runtime-utils.d.ts +27 -0
  41. package/dist/platform-weapp/runtime-utils.js +48 -0
  42. package/dist/platform-weapp/runtime-utils.js.map +1 -0
  43. package/dist/platform-weapp/runtime.d.ts +1 -0
  44. package/dist/platform-weapp/runtime.js +7 -0
  45. package/dist/platform-weapp/runtime.js.map +1 -0
  46. package/dist/platform-weapp/template.d.ts +39 -0
  47. package/dist/platform-weapp/template.js +119 -0
  48. package/dist/platform-weapp/template.js.map +1 -0
  49. package/dist/presets/commands/build.js +25 -45
  50. package/dist/presets/commands/build.js.map +1 -1
  51. package/dist/presets/commands/init.js +2 -4
  52. package/dist/presets/commands/init.js.map +1 -1
  53. package/dist/presets/constant/hooks.d.ts +0 -2
  54. package/dist/presets/constant/hooks.js +1 -3
  55. package/dist/presets/constant/hooks.js.map +1 -1
  56. package/dist/presets/files/generate-framework-info.js +68 -0
  57. package/dist/presets/files/generate-framework-info.js.map +1 -0
  58. package/dist/presets/files/{generateProjectConfig.js → generate-project-config.js} +1 -1
  59. package/dist/presets/files/generate-project-config.js.map +1 -0
  60. package/dist/presets/files/{writeFileToDist.js → write-file-to-dist.js} +1 -1
  61. package/dist/presets/files/write-file-to-dist.js.map +1 -0
  62. package/dist/presets/hooks/build.js +1 -3
  63. package/dist/presets/hooks/build.js.map +1 -1
  64. package/dist/presets/index.js +3 -5
  65. package/dist/presets/index.js.map +1 -1
  66. package/dist/util/{appConfig.d.ts → app-config.d.ts} +2 -2
  67. package/dist/util/{appConfig.js → app-config.js} +4 -3
  68. package/dist/util/app-config.js.map +1 -0
  69. package/dist/util/defineConfig.d.ts +5 -5
  70. package/dist/util/defineConfig.js.map +1 -1
  71. package/dist/util/index.d.ts +9 -1
  72. package/dist/util/index.js +54 -23
  73. package/dist/util/index.js.map +1 -1
  74. package/package.json +36 -39
  75. package/postinstall.js +1 -17
  76. package/src/cli.ts +185 -132
  77. package/src/commands/custom-command.ts +22 -0
  78. package/src/create/{fetchTemplate.ts → fetch-template.ts} +30 -35
  79. package/src/create/project.ts +31 -78
  80. package/src/create/template-creator.ts +325 -0
  81. package/src/doctor/validators.js +1 -0
  82. package/src/doctor/validators.ts +8 -6
  83. package/src/platform-weapp/apis-list.ts +33 -0
  84. package/src/platform-weapp/apis.ts +48 -0
  85. package/src/platform-weapp/components-react.ts +81 -0
  86. package/src/platform-weapp/components.ts +521 -0
  87. package/src/platform-weapp/index.ts +25 -0
  88. package/src/platform-weapp/program.ts +70 -0
  89. package/src/platform-weapp/runtime-utils.ts +57 -0
  90. package/src/platform-weapp/runtime.ts +6 -0
  91. package/src/platform-weapp/template.ts +150 -0
  92. package/src/presets/commands/build.ts +20 -40
  93. package/src/presets/commands/init.ts +1 -4
  94. package/src/presets/constant/hooks.js +12 -0
  95. package/src/presets/constant/hooks.ts +0 -2
  96. package/src/presets/files/{generateFrameworkInfo.ts → generate-framework-info.ts} +7 -1
  97. package/src/presets/hooks/build.ts +1 -3
  98. package/src/presets/index.ts +3 -5
  99. package/src/util/app-config.js +1 -0
  100. package/src/util/{appConfig.ts → app-config.ts} +5 -4
  101. package/src/util/defineConfig.ts +6 -6
  102. package/src/util/index.ts +67 -25
  103. package/templates/default/config/dev.js +1 -1
  104. package/templates/default/config/index.js +28 -40
  105. package/templates/default/config/prod.js +1 -1
  106. package/templates/default/package.json.tmpl +2 -17
  107. package/templates/default/types/global.d.ts +0 -4
  108. package/templates/plugin-compile/README.md +3 -1
  109. package/templates/plugin-compile/package.json.tmpl +1 -2
  110. package/templates/plugin-compile/src/index.ts +18 -28
  111. package/LICENSE +0 -174
  112. package/dist/commands/customCommand.js +0 -23
  113. package/dist/commands/customCommand.js.map +0 -1
  114. package/dist/config/packagesManagement.d.ts +0 -19
  115. package/dist/config/packagesManagement.js +0 -22
  116. package/dist/config/packagesManagement.js.map +0 -1
  117. package/dist/create/fetchTemplate.js.map +0 -1
  118. package/dist/create/page.d.ts +0 -65
  119. package/dist/create/page.js +0 -266
  120. package/dist/create/page.js.map +0 -1
  121. package/dist/create/plugin.d.ts +0 -16
  122. package/dist/create/plugin.js +0 -77
  123. package/dist/create/plugin.js.map +0 -1
  124. package/dist/presets/commands/config.js +0 -121
  125. package/dist/presets/commands/config.js.map +0 -1
  126. package/dist/presets/commands/create.js +0 -112
  127. package/dist/presets/commands/create.js.map +0 -1
  128. package/dist/presets/commands/doctor.js +0 -15
  129. package/dist/presets/commands/doctor.js.map +0 -1
  130. package/dist/presets/commands/global-config.d.ts +0 -3
  131. package/dist/presets/commands/global-config.js +0 -175
  132. package/dist/presets/commands/global-config.js.map +0 -1
  133. package/dist/presets/commands/help.d.ts +0 -3
  134. package/dist/presets/commands/help.js +0 -16
  135. package/dist/presets/commands/help.js.map +0 -1
  136. package/dist/presets/commands/info.d.ts +0 -3
  137. package/dist/presets/commands/info.js +0 -96
  138. package/dist/presets/commands/info.js.map +0 -1
  139. package/dist/presets/commands/inspect.d.ts +0 -3
  140. package/dist/presets/commands/inspect.js +0 -155
  141. package/dist/presets/commands/inspect.js.map +0 -1
  142. package/dist/presets/commands/update.d.ts +0 -3
  143. package/dist/presets/commands/update.js +0 -187
  144. package/dist/presets/commands/update.js.map +0 -1
  145. package/dist/presets/files/generateFrameworkInfo.d.ts +0 -3
  146. package/dist/presets/files/generateFrameworkInfo.js +0 -30
  147. package/dist/presets/files/generateFrameworkInfo.js.map +0 -1
  148. package/dist/presets/files/generateProjectConfig.d.ts +0 -3
  149. package/dist/presets/files/generateProjectConfig.js.map +0 -1
  150. package/dist/presets/files/writeFileToDist.d.ts +0 -3
  151. package/dist/presets/files/writeFileToDist.js.map +0 -1
  152. package/dist/presets/hooks/create.d.ts +0 -3
  153. package/dist/presets/hooks/create.js +0 -42
  154. package/dist/presets/hooks/create.js.map +0 -1
  155. package/dist/presets/platforms/plugin.d.ts +0 -3
  156. package/dist/presets/platforms/plugin.js +0 -106
  157. package/dist/presets/platforms/plugin.js.map +0 -1
  158. package/dist/presets/platforms/rn.d.ts +0 -3
  159. package/dist/presets/platforms/rn.js +0 -130
  160. package/dist/presets/platforms/rn.js.map +0 -1
  161. package/dist/util/appConfig.js.map +0 -1
  162. package/dist/util/createPage.d.ts +0 -9
  163. package/dist/util/createPage.js +0 -114
  164. package/dist/util/createPage.js.map +0 -1
  165. package/src/commands/customCommand.ts +0 -22
  166. package/src/config/packagesManagement.ts +0 -20
  167. package/src/config/rn-stylelint.json +0 -4
  168. package/src/create/page.ts +0 -325
  169. package/src/create/plugin.ts +0 -55
  170. package/src/presets/commands/config.ts +0 -86
  171. package/src/presets/commands/create.ts +0 -104
  172. package/src/presets/commands/doctor.ts +0 -21
  173. package/src/presets/commands/global-config.ts +0 -140
  174. package/src/presets/commands/help.ts +0 -17
  175. package/src/presets/commands/info.ts +0 -81
  176. package/src/presets/commands/inspect.ts +0 -137
  177. package/src/presets/commands/update.ts +0 -175
  178. package/src/presets/hooks/create.ts +0 -9
  179. package/src/presets/platforms/plugin.ts +0 -75
  180. package/src/presets/platforms/rn.ts +0 -125
  181. package/src/util/createPage.ts +0 -139
  182. package/templates/default/babel.config.js +0 -14
  183. /package/dist/create/{fetchTemplate.d.ts → fetch-template.d.ts} +0 -0
  184. /package/dist/presets/{commands/config.d.ts → files/generate-framework-info.d.ts} +0 -0
  185. /package/dist/presets/{commands/create.d.ts → files/generate-project-config.d.ts} +0 -0
  186. /package/dist/presets/{commands/doctor.d.ts → files/write-file-to-dist.d.ts} +0 -0
  187. /package/src/presets/files/{generateProjectConfig.ts → generate-project-config.ts} +0 -0
  188. /package/src/presets/files/{writeFileToDist.ts → write-file-to-dist.ts} +0 -0
@@ -1,6 +1,5 @@
1
1
  import * as path from 'node:path';
2
2
 
3
- import { CompilerType, createProject, CSSType, FrameworkType, NpmType, PeriodType } from '@spcsn/taro-binding';
4
3
  import {
5
4
  chalk,
6
5
  DEFAULT_TEMPLATE_SRC,
@@ -12,17 +11,16 @@ import {
12
11
  TARO_CONFIG_FOLDER,
13
12
  } from '@spcsn/taro-helper';
14
13
  import { isArray } from '@spcsn/taro-shared';
15
- import axios from 'axios';
16
14
  import * as inquirer from 'inquirer';
17
15
  import ora from 'ora';
18
- import * as semver from 'semver';
19
16
 
20
17
  import { clearConsole, getPkgVersion, getRootPath } from '../util';
21
18
  import { TEMPLATE_CREATOR } from './constants';
22
19
  import Creator from './creator';
23
- import fetchTemplate from './fetchTemplate';
20
+ import fetchTemplate from './fetch-template';
21
+ import { CompilerType, createProject, CSSType, FrameworkType, NpmType, PeriodType } from './template-creator';
24
22
 
25
- import type { ITemplates } from './fetchTemplate';
23
+ import type { ITemplates } from './fetch-template';
26
24
 
27
25
  export interface IProjectConf {
28
26
  projectName: string;
@@ -33,7 +31,6 @@ export interface IProjectConf {
33
31
  template: string;
34
32
  description?: string;
35
33
  typescript?: boolean;
36
- buildEs5?: boolean;
37
34
  css: CSSType;
38
35
  date?: string;
39
36
  src?: string;
@@ -67,8 +64,8 @@ export default class Project extends Creator {
67
64
 
68
65
  constructor(options: IProjectConfOptions) {
69
66
  super(options.sourceRoot);
70
- const unSupportedVer = semver.lt(process.version, 'v18.0.0');
71
- if (unSupportedVer) {
67
+ const nodeMajorVersion = Number(process.versions.node.split('.')[0]);
68
+ if (nodeMajorVersion < 18) {
72
69
  throw new Error('Node.js 版本过低,推荐升级 Node.js 至 v18.0.0+');
73
70
  }
74
71
  this.rootPath = this._rootPath;
@@ -111,8 +108,6 @@ export default class Project extends Creator {
111
108
  this.askProjectName(conf, prompts);
112
109
  this.askDescription(conf, prompts);
113
110
  this.askTypescript(conf, prompts);
114
- this.askBuildEs5(conf, prompts);
115
- this.askCSS(conf, prompts);
116
111
  this.askNpm(conf, prompts);
117
112
  const answers = await inquirer.prompt<IProjectConf>(prompts);
118
113
 
@@ -205,54 +200,8 @@ export default class Project extends Creator {
205
200
  });
206
201
  }
207
202
  };
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
203
  askCompiler: AskMethods = function (conf, prompts) {
251
204
  const compilerChoices = [
252
- {
253
- name: 'Webpack5',
254
- value: CompilerType.Webpack5,
255
- },
256
205
  {
257
206
  name: 'Vite',
258
207
  value: CompilerType.Vite,
@@ -486,12 +435,11 @@ export default class Project extends Creator {
486
435
  template,
487
436
  npm,
488
437
  framework,
489
- css: this.conf.css || CSSType.None,
438
+ css: CSSType.None,
490
439
  autoInstall: autoInstall,
491
440
  templateRoot: getRootPath(),
492
441
  version: getPkgVersion(),
493
442
  typescript: this.conf.typescript,
494
- buildEs5: this.conf.buildEs5,
495
443
  date: this.conf.date,
496
444
  description: this.conf.description,
497
445
  compiler: this.conf.compiler,
@@ -504,24 +452,29 @@ export default class Project extends Creator {
504
452
  }
505
453
  }
506
454
 
507
- function getOpenSourceTemplates(platform: string) {
508
- return new Promise((resolve, reject) => {
509
- const spinner = ora({ text: '正在拉取开源模板列表...', discardStdin: false }).start();
510
- axios
511
- .get('https://gitee.com/NervJS/awesome-taro/raw/next/index.json')
512
- .then((response) => {
513
- spinner.succeed(`${chalk.grey('拉取开源模板列表成功!')}`);
514
- const collection = response.data;
515
- switch (platform.toLowerCase()) {
516
- case 'react':
517
- return resolve(collection.react);
518
- default:
519
- return resolve([NONE_AVAILABLE_TEMPLATE]);
520
- }
521
- })
522
- .catch((_error) => {
523
- spinner.fail(chalk.red('拉取开源模板列表失败!'));
524
- return reject(new Error());
525
- });
526
- });
455
+ interface OpenSourceTemplateCollection {
456
+ react?: unknown;
457
+ }
458
+
459
+ async function getOpenSourceTemplates(platform: string) {
460
+ const spinner = ora({ text: '正在拉取开源模板列表...', discardStdin: false }).start();
461
+
462
+ try {
463
+ const response = await fetch('https://gitee.com/NervJS/awesome-taro/raw/next/index.json');
464
+ if (!response.ok) {
465
+ throw new Error(`HTTP ${response.status} ${response.statusText}`);
466
+ }
467
+
468
+ spinner.succeed(`${chalk.grey('拉取开源模板列表成功!')}`);
469
+ const collection = (await response.json()) as OpenSourceTemplateCollection;
470
+ switch (platform.toLowerCase()) {
471
+ case 'react':
472
+ return collection.react;
473
+ default:
474
+ return [NONE_AVAILABLE_TEMPLATE];
475
+ }
476
+ } catch {
477
+ spinner.fail(chalk.red('拉取开源模板列表失败!'));
478
+ throw new Error();
479
+ }
527
480
  }
@@ -0,0 +1,325 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { copyFile, mkdir, readdir, readFile, writeFile } from 'node:fs/promises';
3
+ import * as path from 'node:path';
4
+
5
+ import { chalk } from '@spcsn/taro-helper';
6
+
7
+ export enum CompilerType {
8
+ Webpack4 = 'Webpack4',
9
+ Webpack5 = 'Webpack5',
10
+ Vite = 'Vite',
11
+ }
12
+
13
+ export enum CSSType {
14
+ None = 'None',
15
+ Sass = 'Sass',
16
+ Stylus = 'Stylus',
17
+ Less = 'Less',
18
+ }
19
+
20
+ export enum FrameworkType {
21
+ React = 'React',
22
+ Preact = 'Preact',
23
+ Vue3 = 'Vue3',
24
+ Solid = 'Solid',
25
+ None = 'None',
26
+ }
27
+
28
+ export enum NpmType {
29
+ Yarn = 'Yarn',
30
+ Cnpm = 'Cnpm',
31
+ Pnpm = 'Pnpm',
32
+ Npm = 'Npm',
33
+ }
34
+
35
+ export enum PeriodType {
36
+ CreateAPP = 'CreateAPP',
37
+ CreatePage = 'CreatePage',
38
+ }
39
+
40
+ export interface CreateOptions {
41
+ css?: CSSType;
42
+ cssExt?: string;
43
+ framework?: FrameworkType;
44
+ description?: string;
45
+ projectName: string;
46
+ version?: string;
47
+ date?: string;
48
+ typescript?: boolean;
49
+ buildEs5?: boolean;
50
+ template: string;
51
+ pageName?: string;
52
+ compiler?: CompilerType;
53
+ setPageName?: string;
54
+ subPkg?: string;
55
+ pageDir?: string;
56
+ setSubPkgPageName?: string;
57
+ changeExt?: boolean;
58
+ isCustomTemplate?: boolean;
59
+ pluginType?: string;
60
+ }
61
+
62
+ export interface ProjectConfig {
63
+ projectRoot: string;
64
+ projectName: string;
65
+ npm: NpmType;
66
+ description?: string;
67
+ typescript?: boolean;
68
+ buildEs5?: boolean;
69
+ template: string;
70
+ css: CSSType;
71
+ autoInstall?: boolean;
72
+ framework: FrameworkType;
73
+ templateRoot: string;
74
+ version: string;
75
+ date?: string;
76
+ compiler?: CompilerType;
77
+ period: PeriodType;
78
+ }
79
+
80
+ type TemplateHandlerResult = boolean | { setPageName?: string; setSubPkgName?: string; changeExt?: boolean };
81
+ type TemplateHandler = (error: Error | null, options: CreateOptions) => TemplateHandlerResult;
82
+ type TemplateHandlers = Record<string, TemplateHandler>;
83
+
84
+ const TEMPLATE_CREATOR = 'template_creator.js';
85
+ const FILE_FILTER = new Set([TEMPLATE_CREATOR, '.DS_Store', '.npmrc']);
86
+ const MEDIA_FILE_PATTERN = /\.(png|jpe?g|gif|svg|webp|jar|keystore|tgz)$/i;
87
+ const STYLE_EXTENSIONS: Record<CSSType, string> = {
88
+ [CSSType.None]: 'css',
89
+ [CSSType.Sass]: 'scss',
90
+ [CSSType.Stylus]: 'styl',
91
+ [CSSType.Less]: 'less',
92
+ };
93
+ const PACKAGE_MANAGERS: Record<NpmType, string> = {
94
+ [NpmType.Yarn]: 'yarn',
95
+ [NpmType.Cnpm]: 'cnpm',
96
+ [NpmType.Pnpm]: 'pnpm',
97
+ [NpmType.Npm]: 'npm',
98
+ };
99
+
100
+ export async function createProject(conf: ProjectConfig, handlers: TemplateHandlers): Promise<void> {
101
+ const projectPath = path.join(conf.projectRoot, conf.projectName);
102
+ const templatePath = path.join(conf.templateRoot, 'templates', conf.template);
103
+ const templateFiles = await collectTemplateFiles(templatePath);
104
+ const createOptions: CreateOptions = {
105
+ css: conf.css,
106
+ cssExt: STYLE_EXTENSIONS[conf.css],
107
+ framework: conf.framework,
108
+ description: conf.description,
109
+ projectName: conf.projectName,
110
+ version: conf.version,
111
+ date: conf.date,
112
+ typescript: conf.typescript,
113
+ buildEs5: conf.buildEs5,
114
+ template: conf.template,
115
+ pageName: 'index',
116
+ compiler: conf.compiler,
117
+ };
118
+
119
+ console.log();
120
+ console.log(`${chalk.green('✔')} ${chalk.rgb(102, 102, 102)(`创建项目: ${conf.projectName}`)}`);
121
+
122
+ for (const templateFile of templateFiles) {
123
+ await createTemplateFile({ templateFile, templatePath, projectPath, options: createOptions, handlers });
124
+ }
125
+
126
+ console.log();
127
+ await initGit(conf.projectName, projectPath);
128
+
129
+ if (conf.autoInstall ?? true) {
130
+ await installDeps(conf.npm, projectPath, () => printCreateSuccess(conf.projectName));
131
+ return;
132
+ }
133
+
134
+ printCreateSuccess(conf.projectName);
135
+ }
136
+
137
+ async function createTemplateFile(args: {
138
+ templateFile: string;
139
+ templatePath: string;
140
+ projectPath: string;
141
+ options: CreateOptions;
142
+ handlers: TemplateHandlers;
143
+ }): Promise<void> {
144
+ const { templateFile, templatePath, projectPath, options, handlers } = args;
145
+ const relativeTemplatePath = normalizePath(templateFile.replace(templatePath, ''));
146
+ if (shouldSkipByFramework(relativeTemplatePath, options.framework)) return;
147
+
148
+ const handlerResult = handlers[relativeTemplatePath]?.(null, { ...options });
149
+ if (handlerResult === false) return;
150
+
151
+ const destinationRelativePath = resolveDestinationRelativePath(relativeTemplatePath, handlerResult, options);
152
+ const sourcePath = path.join(templatePath, relativeTemplatePath);
153
+ const destinationPath = normalizeTemplateDestination(path.join(projectPath, destinationRelativePath));
154
+
155
+ await writeTemplateFile(sourcePath, destinationPath, options);
156
+ console.log(`${chalk.green('✔')} ${chalk.rgb(102, 102, 102)(`创建文件: ${destinationPath}`)}`);
157
+ }
158
+
159
+ function shouldSkipByFramework(relativeTemplatePath: string, framework?: FrameworkType): boolean {
160
+ const isVueFramework = framework === FrameworkType.Vue3;
161
+ if (isVueFramework && relativeTemplatePath.endsWith('.jsx')) return true;
162
+ return !isVueFramework && relativeTemplatePath.endsWith('.vue');
163
+ }
164
+
165
+ function resolveDestinationRelativePath(
166
+ relativeTemplatePath: string,
167
+ handlerResult: TemplateHandlerResult | undefined,
168
+ options: CreateOptions,
169
+ ): string {
170
+ const handlerDestination = typeof handlerResult === 'object' ? handlerResult : undefined;
171
+ let destinationRelativePath = handlerDestination?.setPageName ?? relativeTemplatePath;
172
+
173
+ if (options.subPkg && handlerDestination?.setSubPkgName) {
174
+ destinationRelativePath = handlerDestination.setSubPkgName;
175
+ }
176
+
177
+ if (destinationRelativePath.startsWith('/')) {
178
+ destinationRelativePath = destinationRelativePath.slice(1);
179
+ }
180
+
181
+ const shouldChangeExt = handlerDestination?.changeExt ?? true;
182
+ if (options.typescript && shouldChangeExt && shouldConvertScriptExtension(destinationRelativePath)) {
183
+ destinationRelativePath = destinationRelativePath.replace(/\.jsx?$/, (extension) =>
184
+ extension === '.jsx' ? '.tsx' : '.ts',
185
+ );
186
+ }
187
+
188
+ if (shouldChangeExt && destinationRelativePath.endsWith('.css')) {
189
+ destinationRelativePath = destinationRelativePath.replace(/\.css$/, `.${options.cssExt ?? 'css'}`);
190
+ }
191
+
192
+ return destinationRelativePath;
193
+ }
194
+
195
+ function shouldConvertScriptExtension(filePath: string): boolean {
196
+ if (!(filePath.endsWith('.js') || filePath.endsWith('.jsx'))) return false;
197
+ return !(filePath.endsWith('babel.config.js') || filePath.endsWith('.eslintrc.js'));
198
+ }
199
+
200
+ async function writeTemplateFile(sourcePath: string, destinationPath: string, options: CreateOptions): Promise<void> {
201
+ await mkdir(path.dirname(destinationPath), { recursive: true });
202
+
203
+ if (MEDIA_FILE_PATTERN.test(sourcePath)) {
204
+ await copyFile(sourcePath, destinationPath);
205
+ return;
206
+ }
207
+
208
+ const templateContent = await readFile(sourcePath, 'utf8');
209
+ const renderedContent = renderTemplate(templateContent, options);
210
+ await writeFile(destinationPath, renderedContent);
211
+ }
212
+
213
+ function renderTemplate(templateContent: string, options: CreateOptions): string {
214
+ return templateContent
215
+ .replace(/{{#if \(eq css "Sass"\) }}([\s\S]*?){{\/if}}/g, options.css === CSSType.Sass ? '$1' : '')
216
+ .replace(/{{#if \(eq css "Less"\) }}([\s\S]*?){{\/if}}/g, options.css === CSSType.Less ? '$1' : '')
217
+ .replace(/{{#if \(eq css "Stylus"\) }}([\s\S]*?){{\/if}}/g, options.css === CSSType.Stylus ? '$1' : '')
218
+ .replace(/{{#if typescript }}([\s\S]*?){{\/if}}/g, options.typescript ? '$1' : '')
219
+ .replace(/{{\s*to_pascal_case\s+pageName\s*}}/g, toPascalCase(options.pageName ?? 'index'))
220
+ .replace(/{{\s*projectName\s*}}/g, options.projectName)
221
+ .replace(/{{\s*description\s*}}/g, options.description ?? '')
222
+ .replace(/{{\s*template\s*}}/g, options.template)
223
+ .replace(/{{\s*typescript\s*}}/g, String(Boolean(options.typescript)))
224
+ .replace(/{{\s*css\s*}}/g, options.css ?? CSSType.None)
225
+ .replace(/{{\s*framework\s*}}/g, options.framework ?? FrameworkType.React)
226
+ .replace(/{{\s*version\s*}}/g, options.version ?? '')
227
+ .replace(/{{\s*date\s*}}/g, options.date ?? '')
228
+ .replace(/{{\s*cssExt\s*}}/g, options.cssExt ?? 'css')
229
+ .replace(/{{\s*pageName\s*}}/g, options.pageName ?? 'index');
230
+ }
231
+
232
+ function toPascalCase(value: string): string {
233
+ return value
234
+ .split(/[^a-zA-Z0-9]+/)
235
+ .filter(Boolean)
236
+ .map((word) => `${word.charAt(0).toUpperCase()}${word.slice(1)}`)
237
+ .join('');
238
+ }
239
+
240
+ function normalizeTemplateDestination(destinationPath: string): string {
241
+ const parsedPath = path.parse(destinationPath);
242
+ let normalizedPath = destinationPath;
243
+
244
+ if (parsedPath.ext === '.tmpl') {
245
+ normalizedPath = path.join(parsedPath.dir, parsedPath.name);
246
+ }
247
+
248
+ const basename = path.basename(normalizedPath);
249
+ if (basename.startsWith('_')) {
250
+ normalizedPath = path.join(path.dirname(normalizedPath), basename.slice(1));
251
+ }
252
+
253
+ return normalizedPath;
254
+ }
255
+
256
+ async function collectTemplateFiles(templatePath: string): Promise<string[]> {
257
+ const entries = await readdir(templatePath, { withFileTypes: true });
258
+ const files = await Promise.all(
259
+ entries.map(async (entry) => {
260
+ const entryPath = path.join(templatePath, entry.name);
261
+ if (entry.isDirectory()) return collectTemplateFiles(entryPath);
262
+ if (FILE_FILTER.has(entry.name)) return [];
263
+ return [entryPath];
264
+ }),
265
+ );
266
+
267
+ return files.flat();
268
+ }
269
+
270
+ async function initGit(projectName: string, projectPath: string): Promise<void> {
271
+ console.log(`cd ${projectName}, 执行 ${chalk.cyan.bold('git init')}`);
272
+
273
+ try {
274
+ await executeCommand('git', ['init'], projectPath);
275
+ console.log(`${chalk.green('✔')} ${chalk.green('初始化 git 成功')}`);
276
+ } catch (error) {
277
+ console.log(`${chalk.red('✘')} ${chalk.red('初始化 git 失败')}`);
278
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
279
+ console.log('没有找到命令 git, 请检查!');
280
+ return;
281
+ }
282
+ console.log(error);
283
+ }
284
+ }
285
+
286
+ async function installDeps(npm: NpmType, projectPath: string, onSuccess: () => void): Promise<void> {
287
+ const command = PACKAGE_MANAGERS[npm];
288
+ if (!command) return;
289
+
290
+ console.log(`执行安装项目依赖 ${chalk.cyan.bold(`${command} install`)}, 需要一会儿...`);
291
+
292
+ try {
293
+ await executeCommand(command, ['install'], projectPath);
294
+ console.log(`${chalk.green('✔')} ${chalk.green('安装项目依赖成功')}`);
295
+ onSuccess();
296
+ } catch (error) {
297
+ console.log(`${chalk.red('✘')} ${chalk.red('安装项目依赖失败,请自行重新安装!')}`);
298
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
299
+ console.log(`没有找到命令 ${command}, 请检查!`);
300
+ }
301
+ }
302
+ }
303
+
304
+ function executeCommand(command: string, args: string[], cwd: string): Promise<void> {
305
+ return new Promise((resolve, reject) => {
306
+ const childProcess = spawn(command, args, { cwd, stdio: 'inherit' });
307
+ childProcess.on('error', reject);
308
+ childProcess.on('close', (exitCode) => {
309
+ if (exitCode === 0) {
310
+ resolve();
311
+ return;
312
+ }
313
+ reject(new Error(`${command} ${args.join(' ')} failed with exit code ${exitCode}`));
314
+ });
315
+ });
316
+ }
317
+
318
+ function printCreateSuccess(projectName: string): void {
319
+ console.log(chalk.green(`创建项目 ${chalk.green.bold(projectName)} 成功!`));
320
+ console.log(chalk.green(`请进入项目目录 ${chalk.green.bold(projectName)} 开始工作吧!😝`));
321
+ }
322
+
323
+ function normalizePath(value: string): string {
324
+ return value.replace(/\\/g, '/').replace(/\/{2,}/g, '/');
325
+ }
@@ -0,0 +1 @@
1
+ module.exports = require('./validators.ts');
@@ -1,9 +1,11 @@
1
- export enum MessageKind {
2
- Error = 'error',
3
- Warning = 'warning',
4
- Success = 'success',
5
- Manual = 'manual',
6
- }
1
+ export const MessageKind = {
2
+ Error: 'error',
3
+ Warning: 'warning',
4
+ Success: 'success',
5
+ Manual: 'manual',
6
+ } as const;
7
+
8
+ export type MessageKind = (typeof MessageKind)[keyof typeof MessageKind];
7
9
 
8
10
  export interface ValidateMessage {
9
11
  kind: MessageKind;
@@ -0,0 +1,33 @@
1
+ export const needPromiseApis = new Set([
2
+ 'addFileToFavorites',
3
+ 'addVideoToFavorites',
4
+ 'authPrivateMessage',
5
+ 'checkIsAddedToMyMiniProgram',
6
+ 'chooseContact',
7
+ 'cropImage',
8
+ 'disableAlertBeforeUnload',
9
+ 'editImage',
10
+ 'enableAlertBeforeUnload',
11
+ 'getBackgroundFetchData',
12
+ 'getChannelsLiveInfo',
13
+ 'getChannelsLiveNoticeInfo',
14
+ 'getFuzzyLocation',
15
+ 'getGroupEnterInfo',
16
+ 'getLocalIPAddress',
17
+ 'getShareInfo',
18
+ 'getUserProfile',
19
+ 'getWeRunData',
20
+ 'join1v1Chat',
21
+ 'openChannelsActivity',
22
+ 'openChannelsEvent',
23
+ 'openChannelsLive',
24
+ 'openChannelsUserProfile',
25
+ 'openCustomerServiceChat',
26
+ 'openVideoEditor',
27
+ 'saveFileToDisk',
28
+ 'scanItem',
29
+ 'setEnable1v1Chat',
30
+ 'setWindowSize',
31
+ 'sendBizRedPacket',
32
+ 'startFacialRecognitionVerify',
33
+ ]);
@@ -0,0 +1,48 @@
1
+ import { processApis } from '@spcsn/taro-shared';
2
+
3
+ import { needPromiseApis } from './apis-list';
4
+
5
+ interface WeappNativeApi {
6
+ cloud?: unknown;
7
+ }
8
+
9
+ interface TaroApiTarget {
10
+ cloud?: unknown;
11
+ getTabBar?: (pageCtx?: { getTabBar?: () => { $taroInstances?: unknown } }) => unknown;
12
+ getRenderer?: () => string;
13
+ getCurrentInstance?: () => { page?: { renderer?: string } };
14
+ }
15
+
16
+ declare const wx: WeappNativeApi;
17
+
18
+ export function initNativeApi(taro: TaroApiTarget) {
19
+ processApis(taro, wx, {
20
+ needPromiseApis,
21
+ modifyApis(apis) {
22
+ // fix https://github.com/NervJS/taro/issues/9899
23
+ apis.delete('lanDebug');
24
+ },
25
+ transformMeta(api: string, options: Record<string, unknown>) {
26
+ if (api === 'showShareMenu') {
27
+ const showShareItems = Array.isArray(options.showShareItems) ? options.showShareItems : [];
28
+ options.menus = showShareItems.map((item) =>
29
+ item === 'wechatFriends' ? 'shareAppMessage' : item === 'wechatMoment' ? 'shareTimeline' : item,
30
+ );
31
+ }
32
+
33
+ return {
34
+ key: api,
35
+ options,
36
+ };
37
+ },
38
+ });
39
+ taro.cloud = wx.cloud;
40
+ taro.getTabBar = function (pageCtx) {
41
+ if (typeof pageCtx?.getTabBar === 'function') {
42
+ return pageCtx.getTabBar()?.$taroInstances;
43
+ }
44
+ };
45
+ taro.getRenderer = function () {
46
+ return taro.getCurrentInstance?.()?.page?.renderer ?? 'webview';
47
+ };
48
+ }
@@ -0,0 +1,81 @@
1
+ // For React.createElement's type
2
+ export const View = 'view';
3
+ export const Block = 'block';
4
+ export const CustomWrapper = 'custom-wrapper';
5
+ export const Slot = 'slot';
6
+ export const NativeSlot = 'native-slot';
7
+ export const Icon = 'icon';
8
+ export const Progress = 'progress';
9
+ export const RichText = 'rich-text';
10
+ export const Text = 'text';
11
+ export const Button = 'button';
12
+ export const Checkbox = 'checkbox';
13
+ export const CheckboxGroup = 'checkbox-group';
14
+ export const Form = 'form';
15
+ export const Input = 'input';
16
+ export const Label = 'label';
17
+ export const Picker = 'picker';
18
+ export const PickerView = 'picker-view';
19
+ export const PickerViewColumn = 'picker-view-column';
20
+ export const Radio = 'radio';
21
+ export const RadioGroup = 'radio-group';
22
+ export const Slider = 'slider';
23
+ export const Switch = 'switch';
24
+ export const Textarea = 'textarea';
25
+ export const CoverImage = 'cover-image';
26
+ export const CoverView = 'cover-view';
27
+ export const MovableArea = 'movable-area';
28
+ export const MovableView = 'movable-view';
29
+ export const ScrollView = 'scroll-view';
30
+ export const Swiper = 'swiper';
31
+ export const SwiperItem = 'swiper-item';
32
+ export const Navigator = 'navigator';
33
+ export const Editor = 'editor';
34
+ export const MatchMedia = 'match-media';
35
+ export const FunctionalPageNavigator = 'functional-page-navigator';
36
+ export const Audio = 'audio';
37
+ export const Camera = 'camera';
38
+ export const Image = 'image';
39
+ export const LivePlayer = 'live-player';
40
+ export const LivePusher = 'live-pusher';
41
+ export const Video = 'video';
42
+ export const Canvas = 'canvas';
43
+ export const Ad = 'ad';
44
+ export const OfficialAccount = 'official-account';
45
+ export const OpenData = 'open-data';
46
+ export const WebView = 'web-view';
47
+ export const Map = 'map';
48
+ export const NavigationBar = 'navigation-bar';
49
+ export const PageMeta = 'page-meta';
50
+ export const VoipRoom = 'voip-room';
51
+ export const AdCustom = 'ad-custom';
52
+ export const PageContainer = 'page-container';
53
+ export const ShareElement = 'share-element';
54
+ export const KeyboardAccessory = 'keyboard-accessory';
55
+ export const RootPortal = 'root-portal';
56
+ export const ChannelLive = 'channel-live';
57
+ export const ChannelVideo = 'channel-video';
58
+ export const ListView = 'list-view';
59
+ export const ListBuilder = 'list-builder';
60
+ export const List = 'list';
61
+ export const ListItem = 'list-item';
62
+ export const GridView = 'grid-view';
63
+ export const GridBuilder = 'grid-builder';
64
+ export const StickyHeader = 'sticky-header';
65
+ export const StickySection = 'sticky-section';
66
+ export const NestedScrollHeader = 'nested-scroll-header';
67
+ export const NestedScrollBody = 'nested-scroll-body';
68
+ export const PullToRefresh = 'pull-to-refresh';
69
+ export const Script = 'script';
70
+ export const Snapshot = 'snapshot';
71
+ export const Span = 'span';
72
+ export const OpenContainer = 'open-container';
73
+ export const DraggableSheet = 'draggable-sheet';
74
+ export const DoubleTapGestureHandler = 'double-tap-gesture-handler';
75
+ export const ForcePressGestureHandler = 'force-press-gesture-handler';
76
+ export const HorizontalDragGestureHandler = 'horizontal-drag-gesture-handler';
77
+ export const LongPressGestureHandler = 'long-press-gesture-handler';
78
+ export const PanGestureHandler = 'pan-gesture-handler';
79
+ export const ScaleGestureHandler = 'scale-gesture-handler';
80
+ export const TapGestureHandler = 'tap-gesture-handler';
81
+ export const VerticalDragGestureHandler = 'vertical-drag-gesture-handler';