wanzhuang-cli 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 (87) hide show
  1. package/.gitattributes +41 -0
  2. package/README.md +113 -0
  3. package/dist/commands/create.d.ts +10 -0
  4. package/dist/commands/create.js +145 -0
  5. package/dist/commands/generate.d.ts +8 -0
  6. package/dist/commands/generate.js +26 -0
  7. package/dist/commands/update.d.ts +6 -0
  8. package/dist/commands/update.js +26 -0
  9. package/dist/createApiTest/displayEnumLabel.d.ts +3 -0
  10. package/dist/createApiTest/displayEnumLabel.js +10 -0
  11. package/dist/createApiTest/displayTypeLabel.d.ts +19 -0
  12. package/dist/createApiTest/displayTypeLabel.js +135 -0
  13. package/dist/createApiTest/index.d.ts +6 -0
  14. package/dist/createApiTest/index.js +24 -0
  15. package/dist/createApiTest/pet.d.ts +58 -0
  16. package/dist/createApiTest/pet.js +102 -0
  17. package/dist/createApiTest/store.d.ts +28 -0
  18. package/dist/createApiTest/store.js +48 -0
  19. package/dist/createApiTest/types.d.ts +110 -0
  20. package/dist/createApiTest/types.js +17 -0
  21. package/dist/createApiTest/user.d.ts +50 -0
  22. package/dist/createApiTest/user.js +85 -0
  23. package/dist/index.d.ts +2 -0
  24. package/dist/index.js +52 -0
  25. package/dist/utils/api.d.ts +1 -0
  26. package/dist/utils/api.js +48 -0
  27. package/dist/utils/configGen.d.ts +28 -0
  28. package/dist/utils/configGen.js +178 -0
  29. package/dist/utils/deps.d.ts +13 -0
  30. package/dist/utils/deps.js +47 -0
  31. package/dist/utils/fileOps.d.ts +29 -0
  32. package/dist/utils/fileOps.js +124 -0
  33. package/dist/utils/template.d.ts +12 -0
  34. package/dist/utils/template.js +31 -0
  35. package/package.json +44 -0
  36. package/src/commands/create.ts +141 -0
  37. package/src/commands/generate.ts +23 -0
  38. package/src/commands/update.ts +22 -0
  39. package/src/createApiTest/displayEnumLabel.ts +13 -0
  40. package/src/createApiTest/displayTypeLabel.ts +160 -0
  41. package/src/createApiTest/index.ts +10 -0
  42. package/src/createApiTest/pet.ts +159 -0
  43. package/src/createApiTest/store.ts +71 -0
  44. package/src/createApiTest/types.ts +134 -0
  45. package/src/createApiTest/user.ts +131 -0
  46. package/src/index.ts +54 -0
  47. package/src/utils/api.ts +47 -0
  48. package/src/utils/configGen.ts +139 -0
  49. package/src/utils/deps.ts +40 -0
  50. package/src/utils/fileOps.ts +86 -0
  51. package/src/utils/template.ts +32 -0
  52. package/templates/react/README.md +12 -0
  53. package/templates/react/eslint.config.js +33 -0
  54. package/templates/react/index.html +13 -0
  55. package/templates/react/package.json +27 -0
  56. package/templates/react/public/vite.svg +1 -0
  57. package/templates/react/src/App.css +42 -0
  58. package/templates/react/src/App.jsx +35 -0
  59. package/templates/react/src/assets/react.svg +1 -0
  60. package/templates/react/src/index.css +68 -0
  61. package/templates/react/src/main.jsx +10 -0
  62. package/templates/react/vite.config.js +7 -0
  63. package/templates/uniapp/index.html +20 -0
  64. package/templates/uniapp/package.json +67 -0
  65. package/templates/uniapp/shims-uni.d.ts +10 -0
  66. package/templates/uniapp/src/App.vue +17 -0
  67. package/templates/uniapp/src/main.js +10 -0
  68. package/templates/uniapp/src/manifest.json +72 -0
  69. package/templates/uniapp/src/pages/index/index.vue +48 -0
  70. package/templates/uniapp/src/pages.json +16 -0
  71. package/templates/uniapp/src/shime-uni.d.ts +6 -0
  72. package/templates/uniapp/src/static/logo.png +0 -0
  73. package/templates/uniapp/src/uni.scss +76 -0
  74. package/templates/uniapp/vite.config.js +8 -0
  75. package/templates/vue/.vscode/extensions.json +3 -0
  76. package/templates/vue/README.md +5 -0
  77. package/templates/vue/index.html +13 -0
  78. package/templates/vue/package.json +18 -0
  79. package/templates/vue/public/vite.svg +1 -0
  80. package/templates/vue/src/App.vue +30 -0
  81. package/templates/vue/src/assets/vue.svg +1 -0
  82. package/templates/vue/src/components/HelloWorld.vue +43 -0
  83. package/templates/vue/src/main.js +5 -0
  84. package/templates/vue/src/style.css +79 -0
  85. package/templates/vue/vite.config.js +7 -0
  86. package/tsconfig.json +19 -0
  87. package/vitest.config.ts +8 -0
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.genTsConfig = genTsConfig;
37
+ exports.genEslintConfig = genEslintConfig;
38
+ exports.genPrettierConfig = genPrettierConfig;
39
+ exports.genUnoConfig = genUnoConfig;
40
+ exports.genTailwindConfig = genTailwindConfig;
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ /**
44
+ * 生成 tsconfig.json,支持 react/vue/uniapp
45
+ * @param targetDir 目标目录
46
+ * @param type 模板类型
47
+ */
48
+ function genTsConfig(targetDir, type) {
49
+ const tsconfigPath = path.join(targetDir, 'tsconfig.json');
50
+ if (fs.existsSync(tsconfigPath))
51
+ return;
52
+ let config = {
53
+ compilerOptions: {
54
+ target: 'ESNext',
55
+ useDefineForClassFields: true,
56
+ lib: ['DOM', 'DOM.Iterable', 'ESNext'],
57
+ allowJs: true,
58
+ skipLibCheck: true,
59
+ esModuleInterop: true,
60
+ allowSyntheticDefaultImports: true,
61
+ strict: true,
62
+ forceConsistentCasingInFileNames: true,
63
+ module: 'ESNext',
64
+ moduleResolution: 'Node',
65
+ resolveJsonModule: true,
66
+ isolatedModules: true,
67
+ noEmit: true,
68
+ },
69
+ include: ['src'],
70
+ references: []
71
+ };
72
+ if (type === 'react')
73
+ config.compilerOptions.jsx = 'react-jsx';
74
+ if (type === 'vue' || type === 'uniapp')
75
+ config.compilerOptions.jsx = 'preserve';
76
+ fs.writeFileSync(tsconfigPath, JSON.stringify(config, null, 2));
77
+ }
78
+ /**
79
+ * 生成 .eslintrc.json,自动适配类型和 features
80
+ * @param targetDir 目标目录
81
+ * @param type 模板类型
82
+ * @param features 功能选项
83
+ */
84
+ function genEslintConfig(targetDir, type, features) {
85
+ const eslintrcPath = path.join(targetDir, '.eslintrc.json');
86
+ if (fs.existsSync(eslintrcPath))
87
+ return;
88
+ const useTS = features.includes('typescript');
89
+ const usePrettier = features.includes('prettier');
90
+ const baseConfig = {
91
+ env: { browser: true, es2021: true },
92
+ extends: [
93
+ 'eslint:recommended',
94
+ type === 'react' ? 'plugin:react/recommended' : null,
95
+ (type === 'vue' || type === 'uniapp') ? 'plugin:vue/vue3-recommended' : null,
96
+ useTS ? 'plugin:@typescript-eslint/recommended' : null,
97
+ usePrettier ? 'plugin:prettier/recommended' : null
98
+ ].filter(Boolean),
99
+ parser: useTS ? ((type === 'vue' || type === 'uniapp') ? 'vue-eslint-parser' : '@typescript-eslint/parser') : undefined,
100
+ parserOptions: {
101
+ ecmaVersion: 'latest',
102
+ sourceType: 'module',
103
+ ecmaFeatures: { jsx: type === 'react' }
104
+ },
105
+ plugins: [
106
+ type === 'react' ? 'react' : null,
107
+ type === 'react' ? 'react-hooks' : null,
108
+ (type === 'vue' || type === 'uniapp') ? 'vue' : null,
109
+ useTS ? '@typescript-eslint' : null
110
+ ].filter(Boolean),
111
+ rules: {
112
+ 'react/react-in-jsx-scope': 'off',
113
+ 'react/prop-types': 'off',
114
+ 'react-hooks/rules-of-hooks': 'error',
115
+ 'react-hooks/exhaustive-deps': 'warn',
116
+ 'vue/multi-word-component-names': 'off',
117
+ },
118
+ settings: type === 'react' ? { react: { version: 'detect' } } : undefined
119
+ };
120
+ fs.writeFileSync(eslintrcPath, JSON.stringify(baseConfig, null, 2));
121
+ }
122
+ /**
123
+ * 生成 .prettierrc 和 .prettierignore
124
+ * @param targetDir 目标目录
125
+ */
126
+ function genPrettierConfig(targetDir) {
127
+ const prettierRcPath = path.join(targetDir, '.prettierrc');
128
+ if (!fs.existsSync(prettierRcPath)) {
129
+ fs.writeFileSync(prettierRcPath, JSON.stringify({
130
+ semi: false,
131
+ singleQuote: true,
132
+ trailingComma: 'all',
133
+ printWidth: 100
134
+ }, null, 2));
135
+ }
136
+ const prettierIgnorePath = path.join(targetDir, '.prettierignore');
137
+ if (!fs.existsSync(prettierIgnorePath)) {
138
+ fs.writeFileSync(prettierIgnorePath, 'node_modules\ndist\n');
139
+ }
140
+ }
141
+ /**
142
+ * 生成 uno.config.ts
143
+ * @param targetDir 目标目录
144
+ */
145
+ function genUnoConfig(targetDir) {
146
+ const unoConfigPath = path.join(targetDir, 'uno.config.ts');
147
+ if (!fs.existsSync(unoConfigPath)) {
148
+ fs.writeFileSync(unoConfigPath, `import { defineConfig, presetUno } from 'unocss'
149
+
150
+ export default defineConfig({
151
+ presets: [presetUno()],
152
+ })
153
+ `);
154
+ }
155
+ }
156
+ /**
157
+ * 生成 tailwind.config.js 和 postcss.config.js
158
+ * @param targetDir 目标目录
159
+ */
160
+ function genTailwindConfig(targetDir) {
161
+ const tailwindConfigPath = path.join(targetDir, 'tailwind.config.js');
162
+ if (!fs.existsSync(tailwindConfigPath)) {
163
+ fs.writeFileSync(tailwindConfigPath, `module.exports = {
164
+ content: ['./index.html', './src/**/*.{js,ts,jsx,tsx,vue}'],
165
+ theme: { extend: {} },
166
+ plugins: [],
167
+ }`);
168
+ }
169
+ const postcssConfigPath = path.join(targetDir, 'postcss.config.js');
170
+ if (!fs.existsSync(postcssConfigPath)) {
171
+ fs.writeFileSync(postcssConfigPath, `module.exports = {
172
+ plugins: {
173
+ tailwindcss: {},
174
+ autoprefixer: {},
175
+ },
176
+ }`);
177
+ }
178
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * 根据模板类型和 features 组装 devDependencies
3
+ * @param type 模板类型(react/vue/uniapp)
4
+ * @param features 功能选项
5
+ * @returns 依赖包名数组
6
+ */
7
+ export declare function getDevDeps(type: string, features: string[]): string[];
8
+ /**
9
+ * 安装 devDependencies
10
+ * @param targetDir 目标目录
11
+ * @param deps 依赖包名数组
12
+ */
13
+ export declare function installDevDeps(targetDir: string, deps: string[]): void;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getDevDeps = getDevDeps;
4
+ exports.installDevDeps = installDevDeps;
5
+ const child_process_1 = require("child_process");
6
+ /**
7
+ * 根据模板类型和 features 组装 devDependencies
8
+ * @param type 模板类型(react/vue/uniapp)
9
+ * @param features 功能选项
10
+ * @returns 依赖包名数组
11
+ */
12
+ function getDevDeps(type, features) {
13
+ const featureMap = {
14
+ typescript: ['typescript', '@typescript-eslint/eslint-plugin', '@typescript-eslint/parser'],
15
+ prettier: ['prettier', 'eslint-config-prettier', 'eslint-plugin-prettier'],
16
+ eslint: ['eslint'],
17
+ unocss: ['unocss'],
18
+ tailwindcss: ['tailwindcss', 'postcss', 'autoprefixer'],
19
+ react: ['@types/react', '@types/react-dom', 'eslint-plugin-react', 'eslint-plugin-react-hooks', '@vitejs/plugin-react'],
20
+ vue: ['eslint-plugin-vue', '@vitejs/plugin-vue', 'vue-eslint-parser'],
21
+ uniapp: ['eslint-plugin-vue', 'vue-eslint-parser'],
22
+ };
23
+ let deps = [];
24
+ for (const f of features) {
25
+ if (featureMap[f])
26
+ deps = deps.concat(featureMap[f]);
27
+ }
28
+ // 保证类型相关依赖
29
+ if (type === 'react')
30
+ deps = deps.concat(featureMap.react);
31
+ if (type === 'vue')
32
+ deps = deps.concat(featureMap.vue);
33
+ if (type === 'uniapp')
34
+ deps = deps.concat(featureMap.uniapp);
35
+ // 去重
36
+ return Array.from(new Set(deps));
37
+ }
38
+ /**
39
+ * 安装 devDependencies
40
+ * @param targetDir 目标目录
41
+ * @param deps 依赖包名数组
42
+ */
43
+ function installDevDeps(targetDir, deps) {
44
+ if (!deps.length)
45
+ return;
46
+ (0, child_process_1.execSync)(`pnpm add -D ${deps.join(' ')}`, { cwd: targetDir, stdio: 'inherit' });
47
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * 递归将所有 fromExt 文件重命名为 toExt
3
+ * @param dir 目录路径
4
+ * @param fromExt 原始扩展名(如 .js)
5
+ * @param toExt 目标扩展名(如 .ts)
6
+ */
7
+ export declare function convertExtRecursive(dir: string, fromExt: string, toExt: string): void;
8
+ /**
9
+ * 递归替换 import 路径中的扩展名
10
+ * @param dir 目录路径
11
+ * @param fromExt 原始扩展名(如 .js)
12
+ * @param toExt 目标扩展名(如 .ts)
13
+ */
14
+ export declare function replaceImportExtRecursive(dir: string, fromExt: string, toExt: string): void;
15
+ /**
16
+ * 为单个 .vue 文件的 <script> 标签加 lang="ts"
17
+ * @param filePath .vue 文件路径
18
+ */
19
+ export declare function addLangTsToVueScript(filePath: string): void;
20
+ /**
21
+ * 递归为所有 .vue 文件加 lang="ts"
22
+ * @param dir 目录路径
23
+ */
24
+ export declare function addLangTsToAllVue(dir: string): void;
25
+ /**
26
+ * 将根目录 vite.config.js 转为 vite.config.ts
27
+ * @param targetDir 目标项目目录
28
+ */
29
+ export declare function convertViteConfigToTs(targetDir: string): void;
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.convertExtRecursive = convertExtRecursive;
37
+ exports.replaceImportExtRecursive = replaceImportExtRecursive;
38
+ exports.addLangTsToVueScript = addLangTsToVueScript;
39
+ exports.addLangTsToAllVue = addLangTsToAllVue;
40
+ exports.convertViteConfigToTs = convertViteConfigToTs;
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ /**
44
+ * 递归将所有 fromExt 文件重命名为 toExt
45
+ * @param dir 目录路径
46
+ * @param fromExt 原始扩展名(如 .js)
47
+ * @param toExt 目标扩展名(如 .ts)
48
+ */
49
+ function convertExtRecursive(dir, fromExt, toExt) {
50
+ const files = fs.readdirSync(dir);
51
+ for (const file of files) {
52
+ const fullPath = path.join(dir, file);
53
+ const stat = fs.statSync(fullPath);
54
+ if (stat.isDirectory()) {
55
+ convertExtRecursive(fullPath, fromExt, toExt);
56
+ }
57
+ else if (file.endsWith(fromExt)) {
58
+ const newPath = fullPath.replace(new RegExp(fromExt + '$'), toExt);
59
+ fs.renameSync(fullPath, newPath);
60
+ }
61
+ }
62
+ }
63
+ /**
64
+ * 递归替换 import 路径中的扩展名
65
+ * @param dir 目录路径
66
+ * @param fromExt 原始扩展名(如 .js)
67
+ * @param toExt 目标扩展名(如 .ts)
68
+ */
69
+ function replaceImportExtRecursive(dir, fromExt, toExt) {
70
+ const files = fs.readdirSync(dir);
71
+ for (const file of files) {
72
+ const fullPath = path.join(dir, file);
73
+ const stat = fs.statSync(fullPath);
74
+ if (stat.isDirectory()) {
75
+ replaceImportExtRecursive(fullPath, fromExt, toExt);
76
+ }
77
+ else if (file.endsWith(toExt)) {
78
+ let content = fs.readFileSync(fullPath, 'utf-8');
79
+ const reg = new RegExp(`(from ['\"].*?)${fromExt}(['\"])`, 'g');
80
+ content = content.replace(reg, `$1${toExt}$2`);
81
+ fs.writeFileSync(fullPath, content);
82
+ }
83
+ }
84
+ }
85
+ /**
86
+ * 为单个 .vue 文件的 <script> 标签加 lang="ts"
87
+ * @param filePath .vue 文件路径
88
+ */
89
+ function addLangTsToVueScript(filePath) {
90
+ let content = fs.readFileSync(filePath, 'utf-8');
91
+ content = content.replace(/<script(\s+lang=["']\w+["'])?/, '<script lang="ts"');
92
+ fs.writeFileSync(filePath, content);
93
+ }
94
+ /**
95
+ * 递归为所有 .vue 文件加 lang="ts"
96
+ * @param dir 目录路径
97
+ */
98
+ function addLangTsToAllVue(dir) {
99
+ const files = fs.readdirSync(dir);
100
+ for (const file of files) {
101
+ const fullPath = path.join(dir, file);
102
+ const stat = fs.statSync(fullPath);
103
+ if (stat.isDirectory()) {
104
+ addLangTsToAllVue(fullPath);
105
+ }
106
+ else if (file.endsWith('.vue')) {
107
+ addLangTsToVueScript(fullPath);
108
+ }
109
+ }
110
+ }
111
+ /**
112
+ * 将根目录 vite.config.js 转为 vite.config.ts
113
+ * @param targetDir 目标项目目录
114
+ */
115
+ function convertViteConfigToTs(targetDir) {
116
+ const viteConfigJs = path.join(targetDir, 'vite.config.js');
117
+ const viteConfigTs = path.join(targetDir, 'vite.config.ts');
118
+ if (fs.existsSync(viteConfigJs)) {
119
+ let content = fs.readFileSync(viteConfigJs, 'utf-8');
120
+ // 可选:如需做内容适配,可在这里处理
121
+ fs.writeFileSync(viteConfigTs, content);
122
+ fs.unlinkSync(viteConfigJs);
123
+ }
124
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * 复制项目模板到目标目录
3
+ * @param template - 模板名称
4
+ * @param targetDir - 目标目录路径
5
+ */
6
+ export declare function copyTemplate(template: string, targetDir: string): Promise<void>;
7
+ /**
8
+ * 更新项目的 package.json 文件
9
+ * @param targetDir - 目标目录路径
10
+ * @param projectName - 项目名称
11
+ */
12
+ export declare function updatePackageJson(targetDir: string, projectName: string): Promise<void>;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.copyTemplate = copyTemplate;
4
+ exports.updatePackageJson = updatePackageJson;
5
+ const path_1 = require("path");
6
+ const fs_1 = require("fs");
7
+ const fs_extra_1 = require("fs-extra");
8
+ /**
9
+ * 复制项目模板到目标目录
10
+ * @param template - 模板名称
11
+ * @param targetDir - 目标目录路径
12
+ */
13
+ async function copyTemplate(template, targetDir) {
14
+ const templatePath = (0, path_1.join)(__dirname, '../../templates', template);
15
+ (0, fs_extra_1.copySync)(templatePath, targetDir);
16
+ }
17
+ /**
18
+ * 更新项目的 package.json 文件
19
+ * @param targetDir - 目标目录路径
20
+ * @param projectName - 项目名称
21
+ */
22
+ async function updatePackageJson(targetDir, projectName) {
23
+ const packageJsonPath = (0, path_1.join)(targetDir, 'package.json');
24
+ const packageJson = JSON.parse((0, fs_1.readFileSync)(packageJsonPath, 'utf-8'));
25
+ // 更新项目基本信息
26
+ packageJson.name = projectName;
27
+ packageJson.version = '1.0.0';
28
+ packageJson.description = `${projectName} - 基于万桩UI组件库的项目`;
29
+ // 将更新后的内容写入文件
30
+ (0, fs_1.writeFileSync)(packageJsonPath, JSON.stringify(packageJson, null, 2));
31
+ }
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "wanzhuang-cli",
3
+ "version": "1.0.0",
4
+ "description": "万桩项目脚手架工具",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "wz": "./dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "dev": "tsc -w",
11
+ "build": "rimraf dist && tsc",
12
+ "test": "vitest",
13
+ "lint": "eslint src --ext .ts",
14
+ "prepare": "npm run build"
15
+ },
16
+ "keywords": [
17
+ "cli",
18
+ "scaffold",
19
+ "generator"
20
+ ],
21
+ "author": "万桩",
22
+ "license": "MIT",
23
+ "dependencies": {
24
+ "chalk": "^4.1.2",
25
+ "commander": "^11.1.0",
26
+ "fs-extra": "^11.3.0",
27
+ "inquirer": "^8.2.6",
28
+ "openapi-ts-request": "^1.3.2",
29
+ "ora": "^5.4.1"
30
+ },
31
+ "devDependencies": {
32
+ "@types/fs-extra": "^11.0.4",
33
+ "@types/inquirer": "^9.0.7",
34
+ "@types/node": "^20.17.32",
35
+ "@vitest/coverage-v8": "^1.0.0",
36
+ "prettier": "^3.5.3",
37
+ "rimraf": "^5.0.5",
38
+ "typescript": "^5.8.3",
39
+ "vitest": "^1.0.0"
40
+ },
41
+ "engines": {
42
+ "node": ">=14.0.0"
43
+ }
44
+ }
@@ -0,0 +1,141 @@
1
+ import { join } from 'path';
2
+ import { existsSync, mkdirSync } from 'fs';
3
+ import { execSync } from 'child_process';
4
+ import inquirer from 'inquirer';
5
+ import chalk from 'chalk';
6
+ import ora from 'ora';
7
+ import { copyTemplate, updatePackageJson } from '../utils/template';
8
+ import { removeSync } from 'fs-extra';
9
+ import { convertExtRecursive, replaceImportExtRecursive, addLangTsToAllVue, convertViteConfigToTs } from '../utils/fileOps';
10
+ import { genTsConfig, genEslintConfig, genPrettierConfig, genUnoConfig, genTailwindConfig } from '../utils/configGen';
11
+ import { getDevDeps, installDevDeps } from '../utils/deps';
12
+
13
+ /**
14
+ * 创建新项目的主函数
15
+ * 1. 交互选择模板和功能
16
+ * 2. 复制模板
17
+ * 3. 自动类型/配置/依赖集成
18
+ * 4. 安装依赖并输出提示
19
+ */
20
+ export async function createProject(projectName: string, options: { force: boolean }) {
21
+ // 目标目录
22
+ const targetDir = join(process.cwd(), projectName);
23
+
24
+ // 1. 检查目标目录是否已存在,处理覆盖逻辑
25
+ if (existsSync(targetDir)) {
26
+ if (options.force) {
27
+ console.log(chalk.yellow(`正在删除目录: ${targetDir}`));
28
+ removeSync(targetDir);
29
+ } else {
30
+ const { action } = await inquirer.prompt([
31
+ {
32
+ name: 'action',
33
+ type: 'list',
34
+ message: '目标目录已存在,请选择操作:',
35
+ choices: [
36
+ { name: '覆盖', value: 'overwrite' },
37
+ { name: '取消', value: false },
38
+ ],
39
+ },
40
+ ]);
41
+ if (!action) return;
42
+ if (action === 'overwrite') {
43
+ console.log(chalk.yellow(`正在删除目录: ${targetDir}`));
44
+ removeSync(targetDir);
45
+ }
46
+ }
47
+ }
48
+
49
+ // 2. 创建新目录
50
+ mkdirSync(targetDir, { recursive: true });
51
+
52
+ // 3. 交互选择模板
53
+ const { template } = await inquirer.prompt([
54
+ {
55
+ name: 'template',
56
+ type: 'list',
57
+ message: '请选择项目模板:',
58
+ choices: [
59
+ { name: 'React', value: 'react' },
60
+ { name: 'Vue', value: 'vue' },
61
+ { name: 'UniApp', value: 'uniapp' },
62
+ ],
63
+ },
64
+ ]);
65
+
66
+ // 4. 交互多选功能
67
+ const { features } = await inquirer.prompt([
68
+ {
69
+ name: 'features',
70
+ type: 'checkbox',
71
+ message: '请选择要包含的功能:',
72
+ choices: [
73
+ { name: 'TypeScript', value: 'typescript' },
74
+ { name: 'Prettier', value: 'prettier' },
75
+ { name: 'ESLint', value: 'eslint' },
76
+ { name: 'UnoCSS', value: 'unocss' },
77
+ { name: 'Tailwind CSS', value: 'tailwindcss' },
78
+ ],
79
+ },
80
+ ]);
81
+ console.log(chalk.cyan('已选择功能:'), features);
82
+
83
+ // 5. 复制模板到目标目录
84
+ await copyTemplate(template, targetDir);
85
+
86
+ // 6. 类型/文件自动转换(React: jsx->tsx,Vue/UniApp: js->ts + vue lang="ts")
87
+ const srcDir = join(targetDir, 'src');
88
+ if (features.includes('typescript')) {
89
+ if (template === 'react' && existsSync(srcDir)) {
90
+ convertExtRecursive(srcDir, '.jsx', '.tsx');
91
+ replaceImportExtRecursive(srcDir, '.jsx', '.tsx');
92
+ }
93
+ if ((template === 'vue' || template === 'uniapp') && existsSync(srcDir)) {
94
+ convertExtRecursive(srcDir, '.js', '.ts');
95
+ replaceImportExtRecursive(srcDir, '.js', '.ts');
96
+ addLangTsToAllVue(srcDir);
97
+ }
98
+ // 新增:根目录 vite.config.js -> vite.config.ts
99
+ convertViteConfigToTs(targetDir);
100
+ genTsConfig(targetDir, template);
101
+ }
102
+
103
+ // 7. 配置文件自动生成
104
+ if (features.includes('eslint')) genEslintConfig(targetDir, template, features);
105
+ if (features.includes('prettier')) genPrettierConfig(targetDir);
106
+ if (features.includes('unocss')) genUnoConfig(targetDir);
107
+ if (features.includes('tailwindcss')) genTailwindConfig(targetDir);
108
+
109
+ // 8. 安装开发依赖
110
+ const devDeps = getDevDeps(template, features);
111
+ installDevDeps(targetDir, devDeps);
112
+
113
+ // 9. 进度提示与最终依赖安装
114
+ const spinner = ora('正在创建项目...').start();
115
+ try {
116
+ // 更新 package.json
117
+ await updatePackageJson(targetDir, projectName);
118
+ // 安装依赖
119
+ spinner.text = '正在安装依赖...';
120
+ execSync('pnpm install', { cwd: targetDir, stdio: 'inherit' });
121
+ spinner.succeed(chalk.green('项目创建成功!'));
122
+ // 使用说明
123
+ if (template === 'uniapp') {
124
+ console.log('\n开始使用:');
125
+ console.log(` cd ${projectName}`);
126
+ console.log(' # 推荐用 HBuilderX 打开项目,或使用 dcloud 官方 CLI');
127
+ console.log(' # 例如:');
128
+ console.log(' pnpm build:alipay # 打包支付宝小程序');
129
+ console.log(' pnpm dev:alipay # 运行支付宝小程序');
130
+ console.log(' pnpm build:mp-weixin # 打包微信小程序');
131
+ console.log(' pnpm dev:mp-weixin # 运行微信小程序');
132
+ } else {
133
+ console.log('\n开始使用:');
134
+ console.log(` cd ${projectName}`);
135
+ console.log(' pnpm dev');
136
+ }
137
+ } catch (error) {
138
+ spinner.fail(chalk.red('项目创建失败!'));
139
+ console.error(error);
140
+ }
141
+ }
@@ -0,0 +1,23 @@
1
+ import { join } from 'path';
2
+ import chalk from 'chalk';
3
+ import ora from 'ora';
4
+ import { generateApi as generateApiUtil } from '../utils/api';
5
+
6
+ /**
7
+ * 生成 API 的函数
8
+ * @param url - API 文档的 URL 地址
9
+ * @param options - 配置选项,包含输出目录
10
+ */
11
+ export async function generateApi(url: string, options: { output: string }) {
12
+ const spinner = ora('正在生成 API...').start();
13
+
14
+ try {
15
+ // 调用 API 生成工具函数
16
+ await generateApiUtil(url, options.output);
17
+
18
+ spinner.succeed(chalk.green('API 生成成功!'));
19
+ } catch (error) {
20
+ spinner.fail(chalk.red('API 生成失败!'));
21
+ console.error(error);
22
+ }
23
+ }
@@ -0,0 +1,22 @@
1
+ import { execSync } from 'child_process';
2
+ import chalk from 'chalk';
3
+ import ora from 'ora';
4
+
5
+ /**
6
+ * 更新项目依赖的函数
7
+ * 使用 pnpm update 命令更新所有依赖包到最新版本
8
+ * 如果更新失败会显示错误信息
9
+ */
10
+ export async function updateDeps() {
11
+ const spinner = ora('正在更新依赖...').start();
12
+
13
+ try {
14
+ // 执行 pnpm update 命令更新依赖
15
+ execSync('pnpm update', { stdio: 'inherit' });
16
+
17
+ spinner.succeed(chalk.green('依赖更新成功!'));
18
+ } catch (error) {
19
+ spinner.fail(chalk.red('依赖更新失败!'));
20
+ console.error(error);
21
+ }
22
+ }
@@ -0,0 +1,13 @@
1
+ /* eslint-disable */
2
+ // @ts-ignore
3
+ import * as API from './types';
4
+
5
+ export function displayStatusEnum(field: API.StatusEnum) {
6
+ return { placed: 'placed', approved: 'approved', delivered: 'delivered' }[
7
+ field
8
+ ];
9
+ }
10
+
11
+ export function displayStatusEnum2(field: API.StatusEnum2) {
12
+ return { available: 'available', pending: 'pending', sold: 'sold' }[field];
13
+ }