@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,58 @@
1
+ export interface IInstallOptions {
2
+ dev: boolean;
3
+ peerDependencies?: boolean;
4
+ }
5
+ export interface INpmConfig {
6
+ dir: string;
7
+ name: string;
8
+ }
9
+ export interface IResolvedCache {
10
+ [key: string]: {
11
+ main: string;
12
+ files: string[];
13
+ };
14
+ }
15
+ export interface IPrettierConfig {
16
+ printWidth?: number;
17
+ tabWidth?: number;
18
+ useTabs?: boolean;
19
+ semi?: boolean;
20
+ singleQuote?: boolean;
21
+ jsxSingleQuote?: boolean;
22
+ trailingComma?: 'none' | 'es5' | 'all';
23
+ bracketSpacing?: boolean;
24
+ jsxBracketSameLine?: boolean;
25
+ arrowParens?: 'avoid' | 'always';
26
+ rangeStart?: number;
27
+ rangeEnd?: number;
28
+ parser?: 'babel' | 'babylon' | 'flow' | 'typescript' | 'css' | 'scss' | 'less' | 'json' | 'json5' | 'json-stringify' | 'graphql' | 'markdown' | 'mdx' | 'html' | 'vue' | 'angular' | 'yaml';
29
+ filepath?: string;
30
+ requirePragma?: boolean;
31
+ insertPragma?: boolean;
32
+ proseWrap?: 'always' | 'never' | 'preserve';
33
+ htmlWhitespaceSensitivity?: 'css' | 'strict' | 'ignore';
34
+ endOfLine?: 'auto' | 'lf' | 'crlf' | 'cr';
35
+ }
36
+ export interface IBuildOptions {
37
+ type?: string;
38
+ watch?: boolean;
39
+ platform?: string;
40
+ port?: number;
41
+ release?: boolean;
42
+ envHasBeenSet?: boolean;
43
+ page?: string;
44
+ component?: string;
45
+ uiIndex?: string;
46
+ }
47
+ export interface IMiniAppBuildConfig {
48
+ adapter: string;
49
+ watch?: boolean;
50
+ envHasBeenSet?: boolean;
51
+ port?: number;
52
+ release?: boolean;
53
+ page?: string;
54
+ component?: string;
55
+ }
56
+ export interface IOption {
57
+ [key: string]: any;
58
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/util/types.ts"],"names":[],"mappings":""}
package/global.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ declare module '*.json' {
2
+ const value: any
3
+ export default value
4
+ }
package/index.js ADDED
@@ -0,0 +1,3 @@
1
+ module.exports = require('./dist/index.js').default;
2
+
3
+ module.exports.default = module.exports;
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "@spcsn/taro-cli",
3
+ "version": "0.1.0",
4
+ "description": "cli tool for taro",
5
+ "author": "O2Team",
6
+ "license": "MIT",
7
+ "main": "index.js",
8
+ "types": "dist/index.d.ts",
9
+ "files": [
10
+ "bin",
11
+ "src",
12
+ "dist",
13
+ "templates",
14
+ "postinstall.js",
15
+ "index.js",
16
+ "global.d.ts"
17
+ ],
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/NervJS/taro.git"
21
+ },
22
+ "bin": {
23
+ "taro": "bin/taro"
24
+ },
25
+ "keywords": [
26
+ "taro",
27
+ "weapp"
28
+ ],
29
+ "engines": {
30
+ "node": ">= 22"
31
+ },
32
+ "dependencies": {
33
+ "@tarojs/plugin-doctor": "^0.0.13",
34
+ "adm-zip": "^0.5.12",
35
+ "axios": "^1.6.8",
36
+ "cli-highlight": "^2.1.11",
37
+ "download-git-repo": "^3.0.2",
38
+ "envinfo": "^7.12.0",
39
+ "inquirer": "^8.2.6",
40
+ "latest-version": "^5.1.0",
41
+ "minimist": "^1.2.8",
42
+ "ora": "^5.4.1",
43
+ "semver": "^7.6.0",
44
+ "validate-npm-package-name": "^5.0.0",
45
+ "@spcsn/taro-helper": "0.1.0",
46
+ "@spcsn/taro-plugin-generator": "0.1.0",
47
+ "@spcsn/taro-plugin-framework-react": "0.1.0",
48
+ "@spcsn/taro-vite-runner": "0.1.0",
49
+ "@spcsn/taro-shared": "0.1.0",
50
+ "@spcsn/babel-preset-taro": "0.1.0",
51
+ "@spcsn/taro-service": "0.1.0",
52
+ "@spcsn/taro-plugin-platform-weapp": "0.1.0",
53
+ "@spcsn/taro-binding": "0.1.0"
54
+ },
55
+ "devDependencies": {
56
+ "@babel/types": "^7.24.0",
57
+ "@types/babel__traverse": "^7.20.6",
58
+ "@spcsn/taro": "0.1.0",
59
+ "@spcsn/taro-plugin-platform-weapp": "0.1.0"
60
+ },
61
+ "scripts": {
62
+ "prod": "pnpm run build",
63
+ "postinstall": "node postinstall.js",
64
+ "test": "cross-env NODE_ENV=test jest",
65
+ "test:ci": "cross-env NODE_ENV=test jest --ci -i --coverage --silent",
66
+ "test:dev": "cross-env NODE_ENV=test jest --watch",
67
+ "test:coverage": "cross-env NODE_ENV=test jest --coverage",
68
+ "updateSnapshot": "cross-env NODE_ENV=test jest --updateSnapshot",
69
+ "prebuild": "pnpm run clean",
70
+ "build": "tsc || true",
71
+ "dev": "tsc -w",
72
+ "clean": "rimraf dist"
73
+ }
74
+ }
package/postinstall.js ADDED
@@ -0,0 +1,17 @@
1
+ const { exec } = require('child_process');
2
+ const axios = require('axios');
3
+
4
+ axios
5
+ .get('https://taro.jd.com/', { timeout: 5000 })
6
+ .then(() => {
7
+ exec(
8
+ './bin/taro global-config add-plugin @jdtaro/plugin-build-report-performance@latest --registry http://registry.m.jd.com',
9
+ (error, _stdout, _stderr) => {
10
+ if (error) {
11
+ console.error(`install performance plugin error: ${error}`);
12
+ }
13
+ },
14
+ );
15
+ console.log('cli postinstall success');
16
+ })
17
+ .catch(() => {});
@@ -0,0 +1,15 @@
1
+ import * as path from 'node:path';
2
+
3
+ export default () => {
4
+ return {
5
+ plugins: [
6
+ // hooks
7
+ path.resolve(__dirname, '../../presets', 'hooks', 'build.ts'),
8
+
9
+ // 兼容其他平台小程序插件
10
+ path.resolve(__dirname, '../../presets', 'files', 'writeFileToDist.ts'),
11
+ path.resolve(__dirname, '../../presets', 'files', 'generateProjectConfig.ts'),
12
+ path.resolve(__dirname, '../../presets', 'files', 'generateFrameworkInfo.ts'),
13
+ ],
14
+ };
15
+ };
@@ -0,0 +1,66 @@
1
+ import * as path from 'node:path';
2
+
3
+ import { emptyDirectory } from '@spcsn/taro-helper';
4
+
5
+ import { run } from './utils';
6
+
7
+ const runBuild = run('build', ['commands/build', require.resolve('@spcsn/taro-plugin-platform-weapp')]);
8
+
9
+ jest.mock('@spcsn/taro-helper', () => {
10
+ const helper = jest.requireActual('@spcsn/taro-helper');
11
+ const fs = helper.fs;
12
+ return {
13
+ __esModule: true,
14
+ ...helper,
15
+ emptyDirectory: jest.fn(),
16
+ fs: {
17
+ ...fs,
18
+ },
19
+ };
20
+ });
21
+
22
+ const APP_PATH = path.join(__dirname, 'fixtures/default');
23
+ const OUTPUT_PATH = path.join(__dirname, 'fixtures/default/dist');
24
+
25
+ describe('构建配置测试', () => {
26
+ const emptyDirectoryMocked = emptyDirectory as jest.Mock<any>;
27
+
28
+ beforeEach(() => {
29
+ emptyDirectoryMocked.mockReset();
30
+ process.argv = [];
31
+ });
32
+
33
+ afterEach(() => {
34
+ process.argv = [];
35
+ emptyDirectoryMocked.mockReset();
36
+ });
37
+
38
+ describe('小程序', () => {
39
+ it(`项目 output.clean = clean: { keep: ['project.config.json'] } ==> 清空dist文件夹但保留指定文件`, async () => {
40
+ const exitSpy = jest.spyOn(process, 'exit') as jest.SpyInstance<void, any>;
41
+ const logSpy = jest.spyOn(console, 'log');
42
+ const errorSpy = jest.spyOn(console, 'error');
43
+ logSpy.mockImplementation(() => {});
44
+ errorSpy.mockImplementation(() => {});
45
+ exitSpy.mockImplementation(() => {
46
+ throw new Error();
47
+ });
48
+
49
+ try {
50
+ await runBuild(APP_PATH, {
51
+ options: {
52
+ type: 'weapp',
53
+ platform: 'weapp',
54
+ },
55
+ });
56
+ } catch (error) {
57
+ // no handler
58
+ }
59
+ expect(emptyDirectoryMocked).toBeCalledWith(OUTPUT_PATH, { excludes: ['project.config.json'] });
60
+
61
+ exitSpy.mockRestore();
62
+ logSpy.mockRestore();
63
+ errorSpy.mockRestore();
64
+ });
65
+ });
66
+ });
@@ -0,0 +1,226 @@
1
+ import { Kernel } from '@spcsn/taro-service';
2
+
3
+ import CLI from '../cli';
4
+ import { getPkgVersion } from '../util';
5
+
6
+ jest.mock('@spcsn/taro-service');
7
+ const MockedKernel = Kernel as unknown as jest.Mock<Kernel>;
8
+ const APP_PATH = '/a/b/c';
9
+
10
+ function setProcessArgv(cmd: string) {
11
+ // @ts-ignore
12
+ process.argv = [null, ...cmd.split(' ')];
13
+ }
14
+
15
+ describe('inspect', () => {
16
+ let cli: CLI;
17
+
18
+ beforeAll(() => {
19
+ cli = new CLI(APP_PATH);
20
+ });
21
+
22
+ beforeEach(() => {
23
+ MockedKernel.mockClear();
24
+ process.argv = [];
25
+ delete process.env.NODE_ENV;
26
+ delete process.env.TARO_ENV;
27
+ });
28
+
29
+ afterEach(() => {
30
+ MockedKernel.mockClear();
31
+ process.argv = [];
32
+ delete process.env.NODE_ENV;
33
+ delete process.env.TARO_ENV;
34
+ });
35
+
36
+ describe('build', () => {
37
+ const baseOpts = {
38
+ _: ['build'],
39
+ options: {
40
+ args: expect.any(Object),
41
+ platform: undefined,
42
+ publicPath: undefined,
43
+ isWatch: false,
44
+ withoutBuild: false,
45
+ env: undefined,
46
+ blended: false,
47
+ assetsDest: undefined,
48
+ bundleOutput: undefined,
49
+ plugin: undefined,
50
+ isBuildNativeComp: false,
51
+ newBlended: false,
52
+ noInjectGlobalStyle: false,
53
+ noCheck: false,
54
+ sourceMapUrl: undefined,
55
+ sourcemapOutput: undefined,
56
+ sourcemapSourcesRoot: undefined,
57
+ },
58
+ isHelp: false,
59
+ };
60
+
61
+ it('should make configs', async () => {
62
+ const platform = 'weapp';
63
+ setProcessArgv('taro build --type weapp --watch --port 8080');
64
+ await cli.run();
65
+ const ins = MockedKernel.mock.instances[0];
66
+
67
+ const opts = Object.assign({}, baseOpts);
68
+ opts.options = Object.assign({}, baseOpts.options, {
69
+ platform,
70
+ isWatch: true,
71
+ port: 8080,
72
+ deviceType: undefined,
73
+ resetCache: false,
74
+ qr: false,
75
+ });
76
+
77
+ expect(ins.run).toHaveBeenCalledWith({
78
+ name: 'build',
79
+ opts,
80
+ });
81
+ });
82
+
83
+ it('should not set node env again', async () => {
84
+ process.env.NODE_ENV = 'development';
85
+ setProcessArgv('taro build --type weapp');
86
+ await cli.run();
87
+ expect(process.env.NODE_ENV).toEqual('development');
88
+ });
89
+
90
+ it.skip('should make plugin config', async () => {
91
+ setProcessArgv('taro build --plugin');
92
+ await cli.run();
93
+ const ins = MockedKernel.mock.instances[0];
94
+ expect(ins.run).toHaveBeenCalledWith({
95
+ name: 'build',
96
+ opts: Object.assign({}, baseOpts, {
97
+ platform: 'plugin',
98
+ plugin: 'weapp',
99
+ }),
100
+ });
101
+ expect(process.env.NODE_ENV).toEqual('production');
102
+ expect(process.env.TARO_ENV).toEqual('plugin');
103
+ });
104
+ });
105
+
106
+ describe('init', () => {
107
+ it('should make configs', async () => {
108
+ const projectName = 'temp';
109
+ const templateSource = 'https://url';
110
+ const template = 'mobx';
111
+ const css = 'sass';
112
+ setProcessArgv('taro init temp --typescript --template-source=https://url --clone --template mobx --css sass');
113
+ await cli.run();
114
+ const ins = MockedKernel.mock.instances[0];
115
+ expect(ins.run).toHaveBeenCalledWith({
116
+ name: 'init',
117
+ opts: {
118
+ _: ['init', 'temp'],
119
+ options: {
120
+ appPath: APP_PATH,
121
+ projectName,
122
+ typescript: true,
123
+ templateSource,
124
+ description: undefined,
125
+ clone: true,
126
+ template,
127
+ css,
128
+ },
129
+ isHelp: false,
130
+ },
131
+ });
132
+ });
133
+
134
+ it('should set project name', async () => {
135
+ const projectName = 'demo';
136
+ setProcessArgv('taro init --name demo');
137
+ await cli.run();
138
+ const ins = MockedKernel.mock.instances[0];
139
+ expect(ins.run).toHaveBeenCalledWith({
140
+ name: 'init',
141
+ opts: {
142
+ _: ['init'],
143
+ options: {
144
+ appPath: APP_PATH,
145
+ projectName,
146
+ typescript: undefined,
147
+ templateSource: undefined,
148
+ description: undefined,
149
+ clone: false,
150
+ template: undefined,
151
+ css: undefined,
152
+ },
153
+ isHelp: false,
154
+ },
155
+ });
156
+ });
157
+ });
158
+
159
+ describe('convert', () => {
160
+ it('should make configs', async () => {
161
+ setProcessArgv('taro convert');
162
+ await cli.run();
163
+ const ins = MockedKernel.mock.instances[0];
164
+ expect(ins.run).toHaveBeenCalledWith({
165
+ name: 'convert',
166
+ opts: {
167
+ _: ['convert'],
168
+ options: {
169
+ build: true,
170
+ check: true,
171
+ 'inject-global-style': true,
172
+ },
173
+ isHelp: false,
174
+ },
175
+ });
176
+ });
177
+ });
178
+
179
+ describe('customCommand', () => {
180
+ it('should make configs', async () => {
181
+ const cmd = 'inspect';
182
+ const _ = [cmd, 'entry'];
183
+ const type = 'weapp';
184
+ setProcessArgv('taro inspect entry --type weapp -h --version');
185
+ await cli.run();
186
+ const ins = MockedKernel.mock.instances[0];
187
+ expect(ins.run).toHaveBeenCalledWith({
188
+ name: cmd,
189
+ opts: {
190
+ _,
191
+ options: {
192
+ build: true,
193
+ check: true,
194
+ 'inject-global-style': true,
195
+ type,
196
+ },
197
+ isHelp: true,
198
+ },
199
+ });
200
+ });
201
+ });
202
+
203
+ describe('others', () => {
204
+ it('should log helps', async () => {
205
+ const spy = jest.spyOn(console, 'log');
206
+ spy.mockImplementation(() => {});
207
+
208
+ setProcessArgv('taro -h');
209
+ await cli.run();
210
+ expect(spy).toBeCalledTimes(16);
211
+
212
+ spy.mockRestore();
213
+ });
214
+
215
+ it('should log version', async () => {
216
+ const spy = jest.spyOn(console, 'log');
217
+ spy.mockImplementation(() => {});
218
+
219
+ setProcessArgv('taro -v');
220
+ await cli.run();
221
+ expect(spy).toBeCalledWith(getPkgVersion());
222
+
223
+ spy.mockRestore();
224
+ });
225
+ });
226
+ });
@@ -0,0 +1,224 @@
1
+ import * as path from 'node:path';
2
+
3
+ import { fs, getUserHomeDir, TARO_BASE_CONFIG, TARO_CONFIG_FOLDER } from '@spcsn/taro-helper';
4
+ import { CONFIG_DIR_NAME, DEFAULT_CONFIG_FILE } from '@spcsn/taro-service/src/utils/constants';
5
+
6
+ import { run } from './utils';
7
+
8
+ jest.mock('@spcsn/taro-helper', () => {
9
+ const helper = jest.requireActual('@spcsn/taro-helper');
10
+ const fs = helper.fs;
11
+ return {
12
+ __esModule: true,
13
+ ...helper,
14
+ getUserHomeDir: jest.fn(),
15
+ fs: {
16
+ ...fs,
17
+ existsSync: jest.fn(),
18
+ readJSONSync: jest.fn(),
19
+ writeJSONSync: jest.fn(),
20
+ ensureFileSync: jest.fn(),
21
+ },
22
+ };
23
+ });
24
+
25
+ const runConfig = run('config', ['commands/config']);
26
+
27
+ describe('config', () => {
28
+ const getUserHomeDirMocked = getUserHomeDir as jest.Mock<any>;
29
+ const existsSyncMocked = fs.existsSync as jest.Mock<any>;
30
+ const readJSONSyncMocked = fs.readJSONSync as jest.Mock<any>;
31
+ const writeJSONSyncMocked = fs.writeJSONSync as jest.Mock<any>;
32
+ const ensureFileSyncMocked = fs.ensureFileSync as jest.Mock<any>;
33
+ const appPath = '/';
34
+
35
+ beforeEach(() => {
36
+ getUserHomeDirMocked.mockReturnValue(appPath);
37
+ // Note: 设置项目配置文件为不存在,config 指令不一定在项目内执行,故而当前测试跳过配置(与过往配置保持一致,后续可视情况调整)
38
+ existsSyncMocked.mockImplementation(
39
+ (filePath = '') => !filePath.includes(path.join(appPath, CONFIG_DIR_NAME, DEFAULT_CONFIG_FILE)),
40
+ );
41
+ });
42
+
43
+ afterEach(() => {
44
+ getUserHomeDirMocked.mockReset();
45
+ existsSyncMocked.mockReset();
46
+ });
47
+
48
+ it("should exit because can't find home dir", async () => {
49
+ const logSpy = jest.spyOn(console, 'log');
50
+ logSpy.mockImplementation(() => {});
51
+
52
+ getUserHomeDirMocked.mockReturnValue('');
53
+
54
+ await runConfig(appPath);
55
+
56
+ expect(logSpy).toBeCalledWith('找不到用户根目录');
57
+ logSpy.mockRestore();
58
+ });
59
+
60
+ it('should warn when getting config without args key', async () => {
61
+ const logSpy = jest.spyOn(console, 'log');
62
+ logSpy.mockImplementation(() => {});
63
+
64
+ await runConfig(appPath, { args: ['get'] });
65
+
66
+ expect(logSpy).toBeCalledWith('Usage: taro config get <key>');
67
+ logSpy.mockRestore();
68
+ });
69
+
70
+ it('should get config', async () => {
71
+ const key = 'k';
72
+ const value = 'v';
73
+ const configPath = path.join('/', `${TARO_CONFIG_FOLDER}/${TARO_BASE_CONFIG}`);
74
+
75
+ const logSpy = jest.spyOn(console, 'log');
76
+ logSpy.mockImplementation(() => {});
77
+ readJSONSyncMocked.mockImplementation(() => ({
78
+ [key]: value,
79
+ }));
80
+
81
+ await runConfig(appPath, { args: ['get', key] });
82
+
83
+ expect(logSpy).nthCalledWith(1, `Config path: ${configPath}`);
84
+ expect(logSpy).nthCalledWith(2);
85
+ expect(logSpy).nthCalledWith(3, `key: ${key}, value: ${value}`);
86
+
87
+ logSpy.mockRestore();
88
+ readJSONSyncMocked.mockReset();
89
+ });
90
+
91
+ it('should warn when getting config without args value', async () => {
92
+ const logSpy = jest.spyOn(console, 'log');
93
+ logSpy.mockImplementation(() => {});
94
+
95
+ await runConfig(appPath, { args: ['set', 'k'] });
96
+
97
+ expect(logSpy).toBeCalledWith('Usage: taro config set <key> <value>');
98
+ logSpy.mockRestore();
99
+ });
100
+
101
+ it('should set config', async () => {
102
+ const key = 'k';
103
+ const value = 'v';
104
+ const configPath = path.join('/', `${TARO_CONFIG_FOLDER}/${TARO_BASE_CONFIG}`);
105
+
106
+ const logSpy = jest.spyOn(console, 'log');
107
+ logSpy.mockImplementation(() => {});
108
+ readJSONSyncMocked.mockReturnValue({ a: 1 });
109
+
110
+ await runConfig(appPath, { args: ['set', key, value] });
111
+
112
+ expect(writeJSONSyncMocked).toBeCalledWith(configPath, {
113
+ a: 1,
114
+ [key]: value,
115
+ });
116
+ expect(logSpy).nthCalledWith(1, `Config path: ${configPath}`);
117
+ expect(logSpy).nthCalledWith(2);
118
+ expect(logSpy).nthCalledWith(3, `set key: ${key}, value: ${value}`);
119
+
120
+ logSpy.mockRestore();
121
+ readJSONSyncMocked.mockReset();
122
+ writeJSONSyncMocked.mockClear();
123
+ });
124
+
125
+ it('should set config with init', async () => {
126
+ const key = 'k';
127
+ const value = 'v';
128
+ const configPath = path.join('/', `${TARO_CONFIG_FOLDER}/${TARO_BASE_CONFIG}`);
129
+
130
+ const logSpy = jest.spyOn(console, 'log');
131
+ logSpy.mockImplementation(() => {});
132
+ existsSyncMocked.mockReturnValue(false);
133
+
134
+ await runConfig(appPath, { args: ['set', key, value] });
135
+
136
+ expect(ensureFileSyncMocked).toBeCalledWith(configPath);
137
+ expect(writeJSONSyncMocked).toBeCalledWith(configPath, { [key]: value });
138
+ expect(logSpy).toBeCalledWith(`set key: ${key}, value: ${value}`);
139
+
140
+ logSpy.mockRestore();
141
+ existsSyncMocked.mockReset();
142
+ ensureFileSyncMocked.mockClear();
143
+ writeJSONSyncMocked.mockClear();
144
+ });
145
+
146
+ it('should warn when deleting config without args key', async () => {
147
+ const logSpy = jest.spyOn(console, 'log');
148
+ logSpy.mockImplementation(() => {});
149
+
150
+ await runConfig(appPath, { args: ['delete'] });
151
+
152
+ expect(logSpy).toBeCalledWith('Usage: taro config delete <key>');
153
+ logSpy.mockRestore();
154
+ });
155
+
156
+ it('should delete config', async () => {
157
+ const key = 'k';
158
+ const configPath = path.join('/', `${TARO_CONFIG_FOLDER}/${TARO_BASE_CONFIG}`);
159
+
160
+ const logSpy = jest.spyOn(console, 'log');
161
+ logSpy.mockImplementation(() => {});
162
+ readJSONSyncMocked.mockReturnValue({
163
+ a: 1,
164
+ [key]: 'v',
165
+ });
166
+
167
+ await runConfig(appPath, { args: ['delete', key] });
168
+
169
+ expect(writeJSONSyncMocked).toBeCalledWith(configPath, { a: 1 });
170
+ expect(logSpy).nthCalledWith(1, `Config path: ${configPath}`);
171
+ expect(logSpy).nthCalledWith(2);
172
+ expect(logSpy).nthCalledWith(3, `deleted: ${key}`);
173
+
174
+ logSpy.mockRestore();
175
+ readJSONSyncMocked.mockReset();
176
+ writeJSONSyncMocked.mockClear();
177
+ });
178
+
179
+ it('should list config', async () => {
180
+ const configPath = path.join('/', `${TARO_CONFIG_FOLDER}/${TARO_BASE_CONFIG}`);
181
+ const logSpy = jest.spyOn(console, 'log');
182
+ logSpy.mockImplementation(() => {});
183
+ readJSONSyncMocked.mockReturnValue({
184
+ a: 1,
185
+ b: 2,
186
+ });
187
+
188
+ await runConfig(appPath, { args: ['list'] });
189
+
190
+ expect(logSpy).nthCalledWith(1, `Config path: ${configPath}`);
191
+ expect(logSpy).nthCalledWith(2);
192
+ expect(logSpy).nthCalledWith(3, 'Config info:');
193
+ expect(logSpy).nthCalledWith(4, 'a=1');
194
+ expect(logSpy).nthCalledWith(5, 'b=2');
195
+
196
+ logSpy.mockRestore();
197
+ readJSONSyncMocked.mockReset();
198
+ });
199
+
200
+ it('should list config in json', async () => {
201
+ const configPath = path.join('/', `${TARO_CONFIG_FOLDER}/${TARO_BASE_CONFIG}`);
202
+ const logSpy = jest.spyOn(console, 'log');
203
+ logSpy.mockImplementation(() => {});
204
+ readJSONSyncMocked.mockReturnValue({
205
+ a: 1,
206
+ b: 2,
207
+ });
208
+
209
+ await runConfig(appPath, {
210
+ args: ['list'],
211
+ options: {
212
+ json: true,
213
+ },
214
+ });
215
+
216
+ expect(logSpy).nthCalledWith(1, `Config path: ${configPath}`);
217
+ expect(logSpy).nthCalledWith(2);
218
+ expect(logSpy).nthCalledWith(3, 'Config info:');
219
+ expect(logSpy).nthCalledWith(4, JSON.stringify({ a: 1, b: 2 }, null, 2));
220
+
221
+ logSpy.mockRestore();
222
+ readJSONSyncMocked.mockReset();
223
+ });
224
+ });