neo-cmp-cli 1.6.2 → 1.6.3

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.
package/README.md CHANGED
@@ -88,6 +88,11 @@ module.exports = {
88
88
  ```
89
89
  **详细使用说明**:请参考下方「[发布自定义组件至 NeoCRM](#6发布自定义组件至-neocrm)」章节。
90
90
 
91
+ #### 8) 删除线上自定义组件
92
+ 执行 `neo deleteCmp` 即可从 NeoCRM 平台删除指定的自定义组件。
93
+ **删除前请确保**:已配置 NeoCRM 平台授权信息,且确认要删除的组件名称正确(删除操作不可恢复)。
94
+ **详细使用说明**:请参考下方「[删除线上自定义组件](#8删除线上自定义组件)」章节。
95
+
91
96
  ## 常用命令说明
92
97
  - **neo init**: 交互式创建自定义组件(支持 -t、--name);
93
98
  - **neo createProject**: 创建自定义组件项目(支持 --name);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo-cmp-cli",
3
- "version": "1.6.2",
3
+ "version": "1.6.3",
4
4
  "description": "前端脚手架:自定义组件开发工具,支持react 和 vue2.0技术栈。",
5
5
  "keywords": [
6
6
  "neo-cli",
@@ -14,7 +14,6 @@
14
14
  "main": "src/module/main.js",
15
15
  "scripts": {
16
16
  "neo": "neo",
17
- "dev": "node ./test/demo.js",
18
17
  "format": "prettier --write \"src/**/**/*.{js,jsx,vue,tsx,ts,scss,less,json}\""
19
18
  },
20
19
  "files": [
@@ -12,7 +12,7 @@ const mainAction = require('./main.js'); // 入口文件
12
12
  const getCmpTypeByDir = require('../utils/cmpUtils/getCmpTypeByDir.js');
13
13
  const NeoService = require('../neo/neoService.js');
14
14
  const curConfig = require('../config/index'); // 获取当前项目根目录下的配置文件
15
- const hasNeoProject = require('../utils/hasNeoProject.js');
15
+ const hasNeoProject = require('../utils/projectUtils/hasNeoProject.js');
16
16
  const consoleTag = require('../utils/neoParams').consoleTag;
17
17
  // neo 的 package 文件
18
18
  const neoPackage = require('../../package.json');
@@ -571,18 +571,50 @@ yargs
571
571
  default: 'auto',
572
572
  choices: ['cursor', 'vscode', 'code', 'auto']
573
573
  })
574
- .option('path', {
575
- alias: 'p',
576
- describe: '要打开的项目路径,默认为当前目录'
574
+ .option('name', {
575
+ alias: 'n',
576
+ describe: '要打开的项目名称,默认为当前目录'
577
577
  })
578
578
  .alias('h', 'help');
579
579
  },
580
580
  (argv) => {
581
- mainAction.openEditor(argv.editor, argv.path);
581
+ mainAction.openEditor(argv.editor, argv.name);
582
582
  }
583
583
  )
584
584
  .alias('h', 'help')
585
585
  .alias('v', 'version')
586
+ .strict()
587
+ .fail((msg, err, yargs) => {
588
+ console.error(chalk.red(`\n运行命令时发生错误: ${msg}。\n`));
589
+ console.log(titleTip('当前可用命令列表:'));
590
+ console.log('');
591
+ // 定义所有可用命令及其描述
592
+ const commands = [
593
+ { cmd: 'init [options]', desc: '根据模板创建一个自定义组件' },
594
+ // { cmd: 'config init', desc: '创建 neo.config.js 配置文件' },
595
+ { cmd: 'createProject [options]', desc: '创建自定义组件项目(含工程代码)' },
596
+ { cmd: 'createCmp [options]', desc: '创建自定义组件' },
597
+ { cmd: 'pullCmp [options]', desc: '拉取线上自定义组件' },
598
+ { cmd: 'deleteCmp [options]', desc: '删除线上自定义组件' },
599
+ { cmd: 'preview [options]', desc: '预览指定自定义组件(仅预览组件本身内容)' },
600
+ // { cmd: 'dev', desc: '开启本地调试模式' },
601
+ { cmd: 'linkDebug', desc: '开启外链调试模式(在线上页面设计器端调试)' },
602
+ // { cmd: 'build', desc: '构建生产环境代码' },
603
+ // { cmd: 'build2lib', desc: '构建 UMD 模块' },
604
+ // { cmd: 'build2esm', desc: '构建 ESM 模块' },
605
+ // { cmd: 'publish2oss [options]', desc: '发布到oss' },
606
+ { cmd: 'pushCmp [options]', desc: '构建并发布自定义组件到 NeoCRM 平台' },
607
+ // { cmd: 'inspect', desc: '输出当前配置文件' },
608
+ { cmd: 'open [options]', desc: '使用 Cursor 或 VSCode 打开项目' }
609
+ ];
610
+ commands.forEach(({ cmd, desc }) => {
611
+ console.log(` ${chalk.cyan(cmd.padEnd(25))} ${desc}`);
612
+ });
613
+ console.log('');
614
+ console.log(`使用 ${chalk.cyan('neo <command> --help')} 查看具体命令的帮助信息。`);
615
+ console.log('');
616
+ process.exit(1);
617
+ })
586
618
  .help()
587
619
  .updateStrings({
588
620
  'Usage:': titleTip('Usage:'),
@@ -4,6 +4,7 @@ const fs = require('fs');
4
4
  const { getCurWebpackConfig } = require('akfun'); // 用于获取当前webpack配置的方法
5
5
  const curConfig = require('../config/index');
6
6
  const { consoleTag } = require('../utils/neoParams'); // 输出标记
7
+ const { errorLog, successLog } = require('../utils/common');
7
8
 
8
9
  // 根据当前配置文件内容创建指定名称的文件
9
10
  const createConfigJs = function (fileName, fileCont) {
@@ -24,17 +25,17 @@ module.exports = (type) => {
24
25
  if (type === 'dev') {
25
26
  const devConfig = getCurWebpackConfig(type, curConfig);
26
27
  createConfigJs('current-neo-dev-config.js', devConfig);
27
- spinner.succeed(`${consoleTag}当前配置数据已输出至 current-neo-dev-config.js中。`);
28
+ successLog(`当前配置数据已输出至 current-neo-dev-config.js中。`, spinner);
28
29
  } else if (type === 'lib') {
29
30
  const libraryConfig = getCurWebpackConfig(type, curConfig);
30
31
  createConfigJs('current-neo-build2lib-config.js', libraryConfig);
31
- spinner.succeed(`${consoleTag}当前配置数据已输出至 current-neo-build2lib-config.js中。`);
32
+ successLog(`当前配置数据已输出至 current-neo-build2lib-config.js中。`, spinner);
32
33
  } else if (type === 'build') {
33
34
  const prodConfig = getCurWebpackConfig(type, curConfig);
34
35
  // 默认输出生产环境的配置文件
35
36
  createConfigJs('current-neo-build-config.js', prodConfig);
36
- spinner.succeed(`${consoleTag}当前配置数据已输出至 current-neo-build-config.js。`);
37
+ successLog(`当前配置数据已输出至 current-neo-build-config.js。`, spinner);
37
38
  } else {
38
- spinner.fail(`type 不能为空。`);
39
+ errorLog(`type 不能为空。`, spinner);
39
40
  }
40
41
  };
@@ -18,7 +18,7 @@ const createCmpByTemplate = require('../utils/cmpUtils/createCmpByTemplate');
18
18
  const createCmpProjectByTemplate = require('../utils/projectUtils/createCmpProjectByTemplate');
19
19
  const pullCmp = require('../utils/cmpUtils/pullCmp');
20
20
  const deleteCmp = require('../utils/cmpUtils/deleteCmp');
21
- const openNeoProject = require('../utils/projectUtils/openNeoProject');
21
+ const openProject = require('../utils/projectUtils/openProject');
22
22
 
23
23
  const getValue = (originValue, defaultValue) => {
24
24
  return originValue !== undefined ? originValue : defaultValue;
@@ -271,5 +271,5 @@ module.exports = {
271
271
  },
272
272
  build2esm: (fileName) => akfun.build2esm(fileName, curConfig, consoleTag), // 构建esm输出模块
273
273
  // 打开编辑器(Cursor 或 VSCode)
274
- openEditor: openNeoProject
274
+ openEditor: openProject
275
275
  };
@@ -6,7 +6,7 @@ const ora = require('ora');
6
6
  const _ = require('lodash');
7
7
  const { resolve } = require('akfun');
8
8
  const updatePublishLog = require('../utils/projectUtils/updatePublishLog');
9
- const { getFramework } = require('../utils/common');
9
+ const { getFramework, errorLog, successLog } = require('../utils/common');
10
10
 
11
11
  // NeoCRM 平台默认 API 配置
12
12
  const NeoCrmAPI = {
@@ -123,7 +123,7 @@ class NeoService {
123
123
  const spinner = ora('获取 token...').start();
124
124
  // 检查缓存是否有效
125
125
  if (!this.isTokenExpired()) {
126
- spinner.succeed('使用缓存的 token。');
126
+ successLog('使用缓存的 token。', spinner);
127
127
  return this.tokenCache.token;
128
128
  }
129
129
 
@@ -147,7 +147,7 @@ class NeoService {
147
147
  const { access_token, expires_in } = response.data || {};
148
148
 
149
149
  if (!access_token) {
150
- spinner.fail('获取 token 失败(授权配置错误):响应中未包含 access_token,', response.data);
150
+ errorLog('获取 token 失败(授权配置错误):响应中未包含 access_token,' + JSON.stringify(response.data), spinner);
151
151
  process.exit(1);
152
152
  }
153
153
 
@@ -161,12 +161,12 @@ class NeoService {
161
161
  spinner.stop();
162
162
  return access_token;
163
163
  } catch (error) {
164
- spinner.fail('获取 token 失败');
165
- console.error('\n获取 token 失败:', error.message);
166
- console.error('\ntoken 授权地址:', tokenUrl);
167
- console.error('\ntoken 请求参数:', formData);
164
+ errorLog('获取 token 失败', spinner);
165
+ errorLog(`\n获取 token 失败: ${error.message}`);
166
+ errorLog(`\ntoken 授权地址: ${tokenUrl}`);
167
+ errorLog(`\ntoken 请求参数: ${formData}`);
168
168
  if (error.response) {
169
- console.error('响应数据:', error.response.data);
169
+ errorLog(`响应数据: ${JSON.stringify(error.response.data)}`);
170
170
  }
171
171
  process.exit(1);
172
172
  }
@@ -197,10 +197,10 @@ class NeoService {
197
197
  const spinner = ora('token 已过期,正在刷新...').start();
198
198
  try {
199
199
  const token = await this.refreshToken();
200
- spinner.succeed('token 刷新成功。');
200
+ successLog('token 刷新成功。', spinner);
201
201
  return token;
202
202
  } catch (error) {
203
- spinner.fail('token 刷新失败。');
203
+ errorLog('token 刷新失败。', spinner);
204
204
  throw error;
205
205
  }
206
206
  }
@@ -334,10 +334,10 @@ class NeoService {
334
334
  } else if (resultData && typeof resultData === 'object' && resultData.url) {
335
335
  fileUrl = resultData.url;
336
336
  }
337
- spinner.succeed(`文件上传成功: ${fileName} -> ${fileUrl}`);
337
+ successLog(`文件上传成功: ${fileName} -> ${fileUrl}`, spinner);
338
338
  return fileUrl;
339
339
  } catch (error) {
340
- spinner.fail(`上传文件失败: ${error.message}, 文件路径: ${filePath}`);
340
+ errorLog(`上传文件失败: ${error.message}, 文件路径: ${filePath}`, spinner);
341
341
 
342
342
  // 输出详细的错误信息
343
343
  if (error.response) {
@@ -346,11 +346,11 @@ class NeoService {
346
346
  const responseData = error.response.data;
347
347
  const requestUrl = error.config?.url || this.uploadAPI();
348
348
 
349
- console.error(`\n========== 上传请求详情 ==========`);
350
- console.error(`请求 URL: ${requestUrl}`);
351
- console.error(`HTTP 状态码: ${status} ${statusText}`);
352
- console.error(`响应数据:`, responseData);
353
- console.error(`==================================\n`);
349
+ errorLog(`\n========== 上传请求详情 ==========`);
350
+ errorLog(`请求 URL: ${requestUrl}`);
351
+ errorLog(`HTTP 状态码: ${status} ${statusText}`);
352
+ errorLog(`响应数据: ${JSON.stringify(responseData)}`);
353
+ errorLog(`==================================\n`);
354
354
 
355
355
  if (status === 404) {
356
356
  throw new Error(
@@ -360,7 +360,7 @@ class NeoService {
360
360
  );
361
361
  }
362
362
  } else if (error.request) {
363
- console.error('请求已发送但未收到响应,请检查网络连接或代理配置。');
363
+ errorLog('请求已发送但未收到响应,请检查网络连接或代理配置。');
364
364
  }
365
365
 
366
366
  throw error;
@@ -375,11 +375,11 @@ class NeoService {
375
375
  */
376
376
  async publish2oss(cmpType, fileExtensions = ['.js', '.css', '.zip']) {
377
377
  if (!cmpType) {
378
- console.error(`自定义组件名称不能为空: ${cmpType}`);
378
+ errorLog(`自定义组件名称不能为空: ${cmpType}`);
379
379
  return;
380
380
  }
381
381
  if (!fs.existsSync(this.assetsRoot)) {
382
- console.error(`未找到自定义组件资源目录: ${this.assetsRoot}`);
382
+ errorLog(`未找到自定义组件资源目录: ${this.assetsRoot}`);
383
383
  return;
384
384
  }
385
385
 
@@ -419,7 +419,7 @@ class NeoService {
419
419
  curCmpInfo.asset = fileUrl;
420
420
  }
421
421
  } catch (error) {
422
- console.error(`文件上传失败(${file}):\n`);
422
+ errorLog(`文件上传失败(${file}):\n`);
423
423
  process.exit(1);
424
424
  }
425
425
  }
@@ -468,11 +468,11 @@ class NeoService {
468
468
  spinner.clear();
469
469
  spinner.stop();
470
470
  } catch (error) {
471
- spinner.fail('更新组件失败。');
471
+ errorLog('更新组件失败。', spinner);
472
472
  if (error.message) {
473
- console.error('更新组件失败:', error.message);
473
+ errorLog(`更新组件失败: ${error.message}`);
474
474
  } else {
475
- console.error('响应数据:', error);
475
+ errorLog(`响应数据: ${JSON.stringify(error)}`);
476
476
  }
477
477
  process.exit(1);
478
478
  }
@@ -518,9 +518,9 @@ class NeoService {
518
518
  this.updateCustomCmpList(response.data.data || []);
519
519
  } catch (error) {
520
520
  if (error.message) {
521
- console.error('获取自定义组件列表失败:', error.message);
521
+ errorLog(`获取自定义组件列表失败: ${error.message}`);
522
522
  } else {
523
- console.error('响应数据:', error);
523
+ errorLog(`响应数据: ${JSON.stringify(error)}`);
524
524
  }
525
525
  process.exit(1);
526
526
  }
@@ -624,9 +624,9 @@ class NeoService {
624
624
 
625
625
  return response.data;
626
626
  } catch (error) {
627
- console.error(`请求失败 [${method} ${api}]:`, error.message);
627
+ errorLog(`请求失败 [${method} ${api}]: ${error.message}`);
628
628
  if (error.response) {
629
- console.error('响应数据:', error.response.data);
629
+ errorLog(`响应数据: ${JSON.stringify(error.response.data)}`);
630
630
  }
631
631
  throw error;
632
632
  }
@@ -6,6 +6,7 @@ const ora = require('ora');
6
6
  const { catchCurPackageJson } = require('../utils/pathUtils');
7
7
  const getConfigObj = require('../utils/getConfigObj');
8
8
  const updatePublishLog = require('../utils/projectUtils/updatePublishLog');
9
+ const { errorLog, warningLog, successLog } = require('../utils/common');
9
10
 
10
11
  // 获取当前项目的package文件
11
12
  const currentPackageJsonDir = catchCurPackageJson();
@@ -185,7 +186,7 @@ async function uploadSingleFile(bosClient, filePath, objectKey, ossType, ossConf
185
186
  // 上传文件
186
187
  const result = await bosClient.upload(objectKey, filePath);
187
188
  const ossPath = getFilePath(ossType, ossConfig.bucket, objectKey);
188
- spinner.succeed(`文件上传成功: ${fileName} -> ${ossPath}`);
189
+ successLog(`文件上传成功: ${fileName} -> ${ossPath}`, spinner);
189
190
 
190
191
  return {
191
192
  success: true,
@@ -197,17 +198,17 @@ async function uploadSingleFile(bosClient, filePath, objectKey, ossType, ossConf
197
198
  resultMsg: result
198
199
  };
199
200
  } catch (error) {
200
- spinner.fail(`文件上传失败: ${fileName}`);
201
+ errorLog(`文件上传失败: ${fileName}`, spinner);
201
202
 
202
203
  // 输出详细的错误信息
203
- console.error(`\n========== 上传文件详情 ==========`);
204
- console.error(`文件路径: ${filePath}`);
205
- console.error(`OSS 对象键: ${objectKey}`);
206
- console.error(`错误信息: ${error.message}`);
204
+ errorLog(`\n========== 上传文件详情 ==========`);
205
+ errorLog(`文件路径: ${filePath}`);
206
+ errorLog(`OSS 对象键: ${objectKey}`);
207
+ errorLog(`错误信息: ${error.message}`);
207
208
  if (error.stack) {
208
- console.error(`错误堆栈:`, error.stack);
209
+ errorLog(`错误堆栈: ${error.stack}`);
209
210
  }
210
- console.error(`==================================\n`);
211
+ errorLog(`==================================\n`);
211
212
 
212
213
  return {
213
214
  success: false,
@@ -231,44 +232,44 @@ async function uploadSingleFile(bosClient, filePath, objectKey, ossType, ossConf
231
232
  const publish2oss = async (ossType, ossConfig, assetsRoot, fileExtensions = ['.js', '.css']) => {
232
233
  // 参数验证
233
234
  if (ossType !== 'baidu' && ossType !== 'ali') {
234
- console.error(`不支持的oss类型: ${ossType}`);
235
+ errorLog(`不支持的oss类型: ${ossType}`);
235
236
  return;
236
237
  }
237
238
 
238
239
  if (!ossConfig) {
239
- console.error('ossConfig 不能为空');
240
+ errorLog('ossConfig 不能为空');
240
241
  return;
241
242
  }
242
243
 
243
244
  if (!assetsRoot) {
244
- console.error('assetsRoot 不能为空');
245
+ errorLog('assetsRoot 不能为空');
245
246
  return;
246
247
  }
247
248
 
248
249
  // 检查目录是否存在
249
250
  if (!fs.existsSync(assetsRoot)) {
250
- console.error(`assetsRoot 不存在: ${assetsRoot}`);
251
+ errorLog(`assetsRoot 不存在: ${assetsRoot}`);
251
252
  return;
252
253
  }
253
254
 
254
255
  // 检查目录是否为目录
255
256
  const assetsRootStat = fs.statSync(assetsRoot);
256
257
  if (!assetsRootStat.isDirectory()) {
257
- console.error(`assetsRoot 不是目录: ${assetsRoot}`);
258
+ errorLog(`assetsRoot 不是目录: ${assetsRoot}`);
258
259
  return;
259
260
  }
260
261
 
261
262
  // 创建 OSS 客户端
262
263
  const bosClient = getBosClient(ossType, ossConfig);
263
264
  if (!bosClient) {
264
- console.error(`无法创建 OSS 客户端,请检查 ossType 和 ossConfig 配置`);
265
+ errorLog(`无法创建 OSS 客户端,请检查 ossType 和 ossConfig 配置`);
265
266
  return;
266
267
  }
267
268
 
268
269
  // 读取构建目录下的所有文件
269
270
  const files = fs.readdirSync(assetsRoot);
270
271
  if (files.length === 0) {
271
- console.warn(`构建目录为空: ${assetsRoot}`);
272
+ warningLog(`构建目录为空: ${assetsRoot}`);
272
273
  return;
273
274
  }
274
275
 
@@ -286,7 +287,7 @@ const publish2oss = async (ossType, ossConfig, assetsRoot, fileExtensions = ['.j
286
287
  const fileInfo = path.parse(filePath);
287
288
  return fileExtensions.includes(fileInfo.ext);
288
289
  } catch (error) {
289
- console.warn(`无法读取文件状态: ${filePath}`, error.message);
290
+ warningLog(`无法读取文件状态: ${filePath} - ${error.message}`);
290
291
  return false;
291
292
  }
292
293
  });
@@ -296,7 +297,7 @@ const publish2oss = async (ossType, ossConfig, assetsRoot, fileExtensions = ['.j
296
297
  return;
297
298
  }
298
299
 
299
- spinner.succeed(`找到 ${filesToUpload.length} 个文件需要上传`);
300
+ successLog(`找到 ${filesToUpload.length} 个文件需要上传`, spinner);
300
301
 
301
302
  // 并行上传所有指定类型的文件
302
303
  const uploadPromises = filesToUpload.map(async (file) => {
@@ -320,7 +321,7 @@ const publish2oss = async (ossType, ossConfig, assetsRoot, fileExtensions = ['.j
320
321
  // 更新发布日志
321
322
  updatePublishLog(widgetFilesMap);
322
323
  } else {
323
- console.warn('未生成有效的文件上传结果');
324
+ warningLog('未生成有效的文件上传结果');
324
325
  }
325
326
 
326
327
  // 统计上传结果
@@ -328,18 +329,18 @@ const publish2oss = async (ossType, ossConfig, assetsRoot, fileExtensions = ['.j
328
329
  const failCount = validResults.filter((r) => r && !r.success).length;
329
330
 
330
331
  if (failCount > 0) {
331
- console.warn(`\n上传完成:成功 ${succeedCount} 个,失败 ${failCount} 个`);
332
+ warningLog(`\n上传完成:成功 ${succeedCount} 个,失败 ${failCount} 个`);
332
333
  } else {
333
334
  console.info(`\n✅ 所有文件上传成功!共 ${succeedCount} 个文件`);
334
335
  }
335
336
  } catch (error) {
336
- spinner.fail('批量上传文件异常');
337
- console.error('\n========== 批量上传异常 ==========');
338
- console.error('错误信息:', error.message);
337
+ errorLog('批量上传文件异常', spinner);
338
+ errorLog('\n========== 批量上传异常 ==========');
339
+ errorLog(`错误信息: ${error.message}`);
339
340
  if (error.stack) {
340
- console.error('错误堆栈:', error.stack);
341
+ errorLog(`错误堆栈: ${error.stack}`);
341
342
  }
342
- console.error('==================================\n');
343
+ errorLog('==================================\n');
343
344
  throw error;
344
345
  }
345
346
  };
@@ -48,7 +48,7 @@
48
48
  "@commitlint/config-conventional": "^9.1.1",
49
49
  "@types/react": "^16.9.11",
50
50
  "@types/react-dom": "^16.9.15",
51
- "neo-cmp-cli": "^1.6.2",
51
+ "neo-cmp-cli": "^1.6.3",
52
52
  "husky": "^4.2.5",
53
53
  "lint-staged": "^10.2.9",
54
54
  "prettier": "^2.0.5"
@@ -48,7 +48,7 @@
48
48
  "@commitlint/config-conventional": "^9.1.1",
49
49
  "@types/react": "^16.9.11",
50
50
  "@types/react-dom": "^16.9.15",
51
- "neo-cmp-cli": "^1.6.2",
51
+ "neo-cmp-cli": "^1.6.3",
52
52
  "husky": "^4.2.5",
53
53
  "lint-staged": "^10.2.9",
54
54
  "prettier": "^2.0.5",
@@ -46,7 +46,7 @@
46
46
  "@commitlint/config-conventional": "^9.1.1",
47
47
  "@types/react": "^16.9.11",
48
48
  "@types/react-dom": "^16.9.15",
49
- "neo-cmp-cli": "^1.6.2",
49
+ "neo-cmp-cli": "^1.6.3",
50
50
  "husky": "^4.2.5",
51
51
  "lint-staged": "^10.2.9",
52
52
  "prettier": "^2.0.5"
@@ -52,7 +52,7 @@
52
52
  "@types/react": "^16.9.11",
53
53
  "@types/react-dom": "^16.9.15",
54
54
  "@types/axios": "^0.14.0",
55
- "neo-cmp-cli": "^1.6.2",
55
+ "neo-cmp-cli": "^1.6.3",
56
56
  "husky": "^4.2.5",
57
57
  "lint-staged": "^10.2.9",
58
58
  "prettier": "^2.0.5"
@@ -45,7 +45,7 @@
45
45
  "devDependencies": {
46
46
  "@commitlint/cli": "^8.3.5",
47
47
  "@commitlint/config-conventional": "^9.1.1",
48
- "neo-cmp-cli": "^1.6.2",
48
+ "neo-cmp-cli": "^1.6.3",
49
49
  "husky": "^4.2.5",
50
50
  "lint-staged": "^10.2.9",
51
51
  "prettier": "^2.0.5"
@@ -47,7 +47,7 @@
47
47
  "@commitlint/config-conventional": "^9.1.1",
48
48
  "@types/react": "^16.9.11",
49
49
  "@types/react-dom": "^16.9.15",
50
- "neo-cmp-cli": "^1.6.2",
50
+ "neo-cmp-cli": "^1.6.3",
51
51
  "husky": "^4.2.5",
52
52
  "lint-staged": "^10.2.9",
53
53
  "prettier": "^2.0.5"
@@ -45,7 +45,7 @@
45
45
  "devDependencies": {
46
46
  "@commitlint/cli": "^8.3.5",
47
47
  "@commitlint/config-conventional": "^9.1.1",
48
- "neo-cmp-cli": "^1.6.2",
48
+ "neo-cmp-cli": "^1.6.3",
49
49
  "husky": "^4.2.5",
50
50
  "lint-staged": "^10.2.9",
51
51
  "prettier": "^2.0.5",
@@ -1,5 +1,6 @@
1
1
  const path = require('path');
2
2
  const fs = require('fs');
3
+ const openProject = require('./projectUtils/openProject');
3
4
 
4
5
  /**
5
6
  * 自动进入指定项目的根目录
@@ -71,7 +72,7 @@ module.exports = function (projectPath, options = {}) {
71
72
  console.log(` 您需要手动执行上述命令才能进入刚创建的自定义组件项目(${projectName})。\n`);
72
73
 
73
74
  // 自动打开 IDE编辑器
74
- openNeoProject('auto', projectName);
75
+ openProject('auto', projectName);
75
76
  }
76
77
 
77
78
  return success;
@@ -7,6 +7,7 @@ const _ = require('lodash');
7
7
  const { consoleTag } = require('../neoParams'); // 输出标记
8
8
  const hasCmpTypeByDir = require('./hasCmpTypeByDir');
9
9
  const hasNeoProject = require('../projectUtils/hasNeoProject');
10
+ const { errorLog, warningLog, successLog, parseTsConfigWithTypeScript } = require('../common');
10
11
 
11
12
  /**
12
13
  * 检查对象键名是否需要加引号
@@ -117,14 +118,14 @@ module.exports = async function (cmpZipUrl, cmpName, componentBaseDir = './src/c
117
118
  const finalCmpName = cmpName;
118
119
 
119
120
  if (!hasNeoProject()) {
120
- console.error(
121
- `${consoleTag}当前(${process.cwd()})还不是自定义组件项目,请先创建一个自定义组件项目(neo init / neo createProject)。`
121
+ errorLog(
122
+ `当前(${process.cwd()})还不是自定义组件项目,请先创建一个自定义组件项目(neo init / neo createProject)。`
122
123
  );
123
124
  process.exit(1);
124
125
  }
125
126
 
126
127
  if (hasCmpTypeByDir(finalCmpName)) {
127
- console.error(`${consoleTag}当前项目已经存在${finalCmpName}自定义组件。`);
128
+ errorLog(`当前项目已经存在${finalCmpName}自定义组件。`);
128
129
  process.exit(1);
129
130
  }
130
131
 
@@ -156,7 +157,7 @@ module.exports = async function (cmpZipUrl, cmpName, componentBaseDir = './src/c
156
157
  maxBodyLength: Infinity
157
158
  });
158
159
  } catch (axiosError) {
159
- spinner.fail(`${consoleTag}下载文件失败:`, axiosError.message);
160
+ errorLog(`下载文件失败: ${axiosError.message}`, spinner);
160
161
  throw axiosError;
161
162
  }
162
163
 
@@ -180,7 +181,7 @@ module.exports = async function (cmpZipUrl, cmpName, componentBaseDir = './src/c
180
181
 
181
182
  await fs.writeFile(zipFilePath, buffer);
182
183
  } catch (writeError) {
183
- spinner.fail(`${consoleTag}读取组件源码文件失败:`, writeError.message);
184
+ errorLog(`读取组件源码文件失败: ${writeError.message}`, spinner);
184
185
  throw writeError;
185
186
  }
186
187
 
@@ -196,7 +197,7 @@ module.exports = async function (cmpZipUrl, cmpName, componentBaseDir = './src/c
196
197
  const cmpSourcePath = path.join(extractPath, componentBaseDir, finalCmpName);
197
198
 
198
199
  if (!fs.existsSync(cmpSourcePath)) {
199
- spinner.fail(`${consoleTag}解压后的 zip 包中未找到 ${finalCmpName} 组件源码目录。`);
200
+ errorLog(`解压后的 zip 包中未找到 ${finalCmpName} 组件源码目录。`, spinner);
200
201
  // 只删除解压目录,保留 zip 源文件
201
202
  await fs.remove(extractPath);
202
203
  return false;
@@ -210,7 +211,7 @@ module.exports = async function (cmpZipUrl, cmpName, componentBaseDir = './src/c
210
211
  try {
211
212
  await fs.copy(cmpSourcePath, targetComponentsDir);
212
213
  } catch (err) {
213
- spinner.fail(`${consoleTag}自定义组件模板下载失败:${err.message || err}`);
214
+ errorLog(`自定义组件模板下载失败:${err.message || err}`, spinner);
214
215
  // 只删除解压目录,保留 zip 源文件
215
216
  await fs.remove(extractPath);
216
217
  return false;
@@ -271,13 +272,13 @@ module.exports = async function (cmpZipUrl, cmpName, componentBaseDir = './src/c
271
272
  );
272
273
  const newDeps = Object.keys(newPackageJsonDeps);
273
274
  if (newDeps.length > 0) {
274
- console.warn(
275
- `${consoleTag}检测到 package.json 中新增了 ${
275
+ warningLog(
276
+ `检测到 package.json 中新增了 ${
276
277
  newDeps.length
277
278
  } 个依赖包:${newDeps.join(', ')}`
278
279
  );
279
- console.warn(
280
- `${consoleTag}为确保组件正常运行,请执行以下命令安装依赖:npm install 或 yarn install`
280
+ warningLog(
281
+ `为确保组件正常运行,请执行以下命令安装依赖:npm install 或 yarn install`
281
282
  );
282
283
  }
283
284
  // 合并 package.json:将源文件的配置合并到目标文件中
@@ -344,10 +345,10 @@ module.exports = async function (cmpZipUrl, cmpName, componentBaseDir = './src/c
344
345
  } else if (fileName === 'tsconfig.json') {
345
346
  // 处理 tsconfig.json 文件(当目标文件已存在时)
346
347
  try {
347
- const sourceTsconfigJson = await fs.readJson(sourcePath);
348
+ const sourceTsconfigJson = parseTsConfigWithTypeScript(sourcePath);
348
349
  // 先判断 targetPath 是否存在,如果存在则合并,否则直接写入
349
350
  if (await fs.pathExists(targetPath)) {
350
- const targetTsconfigJson = await fs.readJson(targetPath);
351
+ const targetTsconfigJson = parseTsConfigWithTypeScript(targetPath);
351
352
  // 合并配置:源配置合并到目标配置(目标配置优先级更高)
352
353
  const mergedTsconfigJson = _.merge({}, sourceTsconfigJson, targetTsconfigJson);
353
354
  // 使用 writeJson 写入,确保 JSON 格式正确(所有键名都会被正确序列化)
@@ -374,11 +375,11 @@ module.exports = async function (cmpZipUrl, cmpName, componentBaseDir = './src/c
374
375
 
375
376
  // 清理解压目录,保留 zip 源文件
376
377
  await fs.remove(extractPath);
377
- spinner.succeed(`${consoleTag}已成功从 zip 包解析自定义组件(${finalCmpName})!`);
378
+ successLog(`已成功从 zip 包解析自定义组件(${finalCmpName})!`, spinner);
378
379
 
379
380
  return true;
380
381
  } catch (error) {
381
- spinner.fail(`${consoleTag}从 zip 包创建自定义组件失败(${finalCmpName}):`, error);
382
+ errorLog(`从 zip 包创建自定义组件失败(${finalCmpName}):${error.message || error}`, spinner);
382
383
  // 清理解压目录,保留 zip 源文件
383
384
  const extractPath = path.join(tempDir, finalCmpName);
384
385
  if (await fs.pathExists(extractPath)) {
@@ -1,5 +1,6 @@
1
1
  const ora = require('ora');
2
2
  const NeoService = require('../../neo/neoService');
3
+ const { errorLog, successLog } = require('../common');
3
4
 
4
5
  /**
5
6
  * 从 NeoCRM 删除自定义组件
@@ -14,7 +15,7 @@ const NeoService = require('../../neo/neoService');
14
15
  */
15
16
  const deleteCmp = async (cmpType, authConfig, _neoService) => {
16
17
  if (!authConfig) {
17
- console.error('未找到 NeoCRM 平台授权配置(neo.config.js / authConfig)。');
18
+ errorLog('未找到 NeoCRM 平台授权配置(neo.config.js / authConfig)。');
18
19
  return;
19
20
  }
20
21
 
@@ -38,23 +39,23 @@ const deleteCmp = async (cmpType, authConfig, _neoService) => {
38
39
  }
39
40
 
40
41
  if (cmpList.length === 0) {
41
- spinner.fail('删除失败,当前租户暂无任何自定义组件。');
42
+ errorLog('删除失败,当前租户暂无任何自定义组件。', spinner);
42
43
  process.exit(1);
43
44
  }
44
45
 
45
46
  // 获取自定义组件信息
46
47
  cmpInfo = neoService.getCmpInfoByCmpType(cmpType);
47
48
  if (!cmpInfo) {
48
- spinner.fail(`删除失败,当前租户不存在${cmpType}自定义组件。`);
49
+ errorLog(`删除失败,当前租户不存在${cmpType}自定义组件。`, spinner);
49
50
  process.exit(1);
50
51
  }
51
52
 
52
53
  // 调用删除 API
53
54
  spinner.info(`正在删除${cmpType}自定义组件...`);
54
55
  await neoService.deleteCmp(cmpType);
55
- spinner.succeed(`已成功删除${cmpType}自定义组件!\n`);
56
+ successLog(`已成功删除${cmpType}自定义组件!\n`, spinner);
56
57
  } catch (error) {
57
- spinner.fail(`删除自定义组件失败: ${error.message}`);
58
+ errorLog(`删除自定义组件失败: ${error.message}`, spinner);
58
59
  process.exit(1);
59
60
  }
60
61
  };
@@ -3,7 +3,7 @@ const { catchCurPackageJson } = require('../pathUtils');
3
3
  const getConfigObj = require('../getConfigObj');
4
4
  const ora = require('ora');
5
5
  const NeoService = require('../../neo/neoService');
6
- const { getFramework } = require('../common');
6
+ const { getFramework, errorLog, successLog } = require('../common');
7
7
  const getCmpTypeByDir = require('./getCmpTypeByDir.js');
8
8
  const createCmpByZip = require('./createCmpByZip.js');
9
9
 
@@ -27,13 +27,13 @@ const framework = getFramework(currentPackageJson.framework);
27
27
  */
28
28
  const pullCmp = async (cmpType, authConfig, _neoService) => {
29
29
  if (!authConfig) {
30
- console.error('未找到 NeoCRM 平台授权配置(neo.config.js / authConfig)。');
30
+ errorLog('未找到 NeoCRM 平台授权配置(neo.config.js / authConfig)。');
31
31
  return;
32
32
  }
33
33
 
34
34
  const cmpTypes = getCmpTypeByDir(); // 获取当前项目目录中已存在的自定义组件类型
35
35
  if (cmpTypes.indexOf(cmpType) > -1) {
36
- console.error(`当前项目目录中已存在${cmpType}自定义组件。(./src/components 目录下)`);
36
+ errorLog(`当前项目目录中已存在${cmpType}自定义组件。(./src/components 目录下)`);
37
37
  process.exit(1);
38
38
  }
39
39
 
@@ -60,26 +60,26 @@ const pullCmp = async (cmpType, authConfig, _neoService) => {
60
60
  }
61
61
 
62
62
  if (cmpList.length === 0) {
63
- spinner.fail('拉取失败,当前租户暂无任何自定义组件。');
63
+ errorLog('拉取失败,当前租户暂无任何自定义组件。', spinner);
64
64
  process.exit(1);
65
65
  }
66
66
 
67
67
  // 获取自定义组件信息
68
68
  cmpInfo = neoService.getCmpInfoByCmpType(cmpType);
69
69
  if (!cmpInfo) {
70
- spinner.fail(`拉取失败,当前租户不存在${cmpType}自定义组件。`);
70
+ errorLog(`拉取失败,当前租户不存在${cmpType}自定义组件。`, spinner);
71
71
  process.exit(1);
72
72
  }
73
73
 
74
74
  // 判断拉取的组件和当前项目是否为同一技术栈
75
75
  if (cmpInfo.framework !== framework) {
76
- spinner.fail(`拉取失败,${cmpType}自定义组件与当前项目技术栈不一致。`);
76
+ errorLog(`拉取失败,${cmpType}自定义组件与当前项目技术栈不一致。`, spinner);
77
77
  process.exit(1);
78
78
  }
79
79
 
80
80
  // 获取当前源码
81
81
  if (!cmpInfo.codeLib) {
82
- spinner.fail(`拉取失败,${cmpType}自定义组件未记录对应的源码文件。`);
82
+ errorLog(`拉取失败,${cmpType}自定义组件未记录对应的源码文件。`, spinner);
83
83
  process.exit(1);
84
84
  }
85
85
 
@@ -89,13 +89,13 @@ const pullCmp = async (cmpType, authConfig, _neoService) => {
89
89
  // 将zip 包里面的自定义组件源码解析到 src/components 目录下
90
90
  const cmpResult = await createCmpByZip(codeLib, cmpType, './src/components');
91
91
  if (!cmpResult) {
92
- spinner.fail(`拉取失败,${cmpType}自定义组件源码解析失败,请检查源码文件是否正确。`);
92
+ errorLog(`拉取失败,${cmpType}自定义组件源码解析失败,请检查源码文件是否正确。`, spinner);
93
93
  process.exit(1);
94
94
  }
95
95
 
96
- spinner.succeed(`已成功拉取${cmpType}自定义组件!\n`);
96
+ successLog(`已成功拉取${cmpType}自定义组件!\n`, spinner);
97
97
  } catch (error) {
98
- spinner.fail(`拉取自定义组件失败: ${error.message}`);
98
+ errorLog(`拉取自定义组件失败: ${error.message}`, spinner);
99
99
  throw error;
100
100
  }
101
101
  };
@@ -5,7 +5,7 @@ const { catchCurPackageJson } = require('../pathUtils');
5
5
  const getConfigObj = require('../getConfigObj');
6
6
  const ora = require('ora');
7
7
  const NeoService = require('../../neo/neoService');
8
- const { getFramework } = require('../common');
8
+ const { getFramework, errorLog, successLog } = require('../common');
9
9
  const createCmpProjectZip = require('../projectUtils/createCmpProjectZip');
10
10
 
11
11
  // 获取当前项目的package文件
@@ -20,14 +20,14 @@ const currentPackageJson = getConfigObj(currentPackageJsonDir);
20
20
  */
21
21
  const buildComponentData = async (assetsRoot, cmpInfo) => {
22
22
  if (!cmpInfo || !cmpInfo.cmpType) {
23
- console.error('自定义组件信息或组件名称不能为空');
23
+ errorLog('自定义组件信息或组件名称不能为空');
24
24
  return null;
25
25
  }
26
26
 
27
27
  const { cmpType } = cmpInfo;
28
28
 
29
29
  if (!assetsRoot || !fs.existsSync(assetsRoot)) {
30
- console.error(`未找到自定义组件目录: ${assetsRoot}`);
30
+ errorLog(`未找到自定义组件目录: ${assetsRoot}`);
31
31
  return null;
32
32
  }
33
33
  const widgetName = _.camelCase(cmpType);
@@ -53,11 +53,11 @@ const buildComponentData = async (assetsRoot, cmpInfo) => {
53
53
  // 获取导出的模型类(可能是 default 导出或命名导出)
54
54
  // const CatchCustomCmpModelClass = modelModule.default || modelModule;
55
55
  } else {
56
- console.error(`未找到自定义组件模型文件,请检查以下路径是否存在:`, modelFile);
56
+ errorLog(`未找到自定义组件模型文件,请检查以下路径是否存在:${modelFile}`);
57
57
  return null;
58
58
  }
59
59
  if (!globalThis.window || !globalThis.window.NEOEditorCustomModels) {
60
- console.error(
60
+ errorLog(
61
61
  `模型文件未导出有效模型方法(CatchCustomCmpModelClass),模型文件地址: ${modelFile} `
62
62
  );
63
63
  return null;
@@ -65,14 +65,14 @@ const buildComponentData = async (assetsRoot, cmpInfo) => {
65
65
 
66
66
  const ModelClass = globalThis.window.NEOEditorCustomModels[cmpType];
67
67
  if (!ModelClass) {
68
- console.error(`未找到自定义组件模型类(${cmpType}),模型文件地址: ${modelFile} `);
68
+ errorLog(`未找到自定义组件模型类(${cmpType}),模型文件地址: ${modelFile} `);
69
69
  return null;
70
70
  }
71
71
  // 实例化模型类
72
72
  const modelInstance = new ModelClass();
73
73
 
74
74
  if (!modelInstance) {
75
- console.error(`未找到自定义组件模型信息(${cmpType}),模型文件地址: ${modelFile} `);
75
+ errorLog(`未找到自定义组件模型信息(${cmpType}),模型文件地址: ${modelFile} `);
76
76
  return null;
77
77
  }
78
78
 
@@ -104,8 +104,8 @@ const buildComponentData = async (assetsRoot, cmpInfo) => {
104
104
  console.log(`自定义组件模型信息(${cmpType}):`, curCmpInfo);
105
105
  return curCmpInfo;
106
106
  } catch (error) {
107
- console.error(`自定义组件模型文件解析失败 (${modelFile || '未知路径'}):`, error.message);
108
- console.error(error.stack);
107
+ errorLog(`自定义组件模型文件解析失败 (${modelFile || '未知路径'}): ${error.message}`);
108
+ errorLog(error.stack);
109
109
  return null;
110
110
  } finally {
111
111
  // 恢复原始的 window 对象(如果之前存在)
@@ -132,7 +132,7 @@ const pushCmp = async (config, cmpType) => {
132
132
  const { auth: credentials } = config;
133
133
 
134
134
  if (!credentials) {
135
- console.error('未找到 NeoCRM 平台授权配置(neo.config.js / neoConfig)');
135
+ errorLog('未找到 NeoCRM 平台授权配置(neo.config.js / neoConfig)');
136
136
  return;
137
137
  }
138
138
 
@@ -150,12 +150,12 @@ const pushCmp = async (config, cmpType) => {
150
150
  try {
151
151
  zipPath = createCmpProjectZip(cmpType, process.cwd(), config.assetsRoot);
152
152
  if (!zipPath) {
153
- spinner.fail('[1/4] 源码文件打包失败,未返回 zip 文件路径。');
153
+ errorLog('[1/4] 源码文件打包失败,未返回 zip 文件路径。', spinner);
154
154
  } else {
155
- spinner.succeed(`[1/4] 源码文件打包完成: ${path.basename(zipPath)}。`);
155
+ successLog(`[1/4] 源码文件打包完成: ${path.basename(zipPath)}。`, spinner);
156
156
  }
157
157
  } catch (error) {
158
- spinner.fail(`[1/4] 源码文件打包失败。`);
158
+ errorLog(`[1/4] 源码文件打包失败。`, spinner);
159
159
  }
160
160
 
161
161
  // 步骤 3: 上传构建后资源文件
@@ -164,12 +164,12 @@ const pushCmp = async (config, cmpType) => {
164
164
  try {
165
165
  cmpInfo = await neoService.publish2oss(cmpType);
166
166
  if (!cmpInfo || !cmpInfo.cmpType) {
167
- spinner.fail('[2/4] 上传构建产物失败,未获取到组件信息。');
167
+ errorLog('[2/4] 上传构建产物失败,未获取到组件信息。', spinner);
168
168
  } else {
169
- spinner.succeed(`[2/4] 构建产物上传完成。`);
169
+ successLog(`[2/4] 构建产物上传完成。`, spinner);
170
170
  }
171
171
  } catch (error) {
172
- spinner.fail(`[2/4] 构建产物上传失败。`);
172
+ errorLog(`[2/4] 构建产物上传失败。`, spinner);
173
173
  }
174
174
 
175
175
  // 步骤 4: 构建组件数据
@@ -178,21 +178,21 @@ const pushCmp = async (config, cmpType) => {
178
178
  try {
179
179
  componentInfo = await buildComponentData(config.assetsRoot, cmpInfo);
180
180
  if (!componentInfo) {
181
- spinner.fail(`[3/4] 未获取到自定义组件模型信息(${cmpType})。`);
181
+ errorLog(`[3/4] 未获取到自定义组件模型信息(${cmpType})。`, spinner);
182
182
  } else {
183
- spinner.succeed(`[3/4] 组件数据构建完成。`);
183
+ successLog(`[3/4] 组件数据构建完成。`, spinner);
184
184
  }
185
185
  } catch (error) {
186
- spinner.fail(`[3/4] 组件数据构建失败: `, error.message);
186
+ errorLog(`[3/4] 组件数据构建失败: ${error.message}`, spinner);
187
187
  }
188
188
 
189
189
  // 步骤 5: 保存组件信息
190
190
  spinner.start(`[4/4] 保存组件信息到 NeoCRM 平台...`);
191
191
  try {
192
192
  await neoService.updateCustomComponent(componentInfo);
193
- spinner.succeed(`[4/4] 组件信息保存成功`);
193
+ successLog(`[4/4] 组件信息保存成功`, spinner);
194
194
  } catch (error) {
195
- spinner.fail(`[4/4] 组件信息保存失败`);
195
+ errorLog(`[4/4] 组件信息保存失败`, spinner);
196
196
  }
197
197
 
198
198
  // 最终成功提示
@@ -203,11 +203,11 @@ const pushCmp = async (config, cmpType) => {
203
203
  try {
204
204
  // ora 的 spinner 对象可能没有 isSpinning 属性,使用 try-catch 安全访问
205
205
  if (spinner && spinner.isSpinning) {
206
- spinner.fail(`❌ 自定义组件发布失败: ${error.message}`);
206
+ errorLog(`❌ 自定义组件发布失败: ${error.message}`, spinner);
207
207
  }
208
208
  } catch {
209
209
  // 如果访问失败或 spinner 已停止,直接输出错误信息
210
- console.error(`\n❌ 自定义组件发布失败: ${error.message}`);
210
+ errorLog(`\n❌ 自定义组件发布失败: ${error.message}`);
211
211
  }
212
212
  throw error;
213
213
  }
@@ -1,4 +1,7 @@
1
+ const chalk = require('chalk');
2
+ const ts = require('typescript');
1
3
  const { consoleTag } = require('./neoParams');
4
+
2
5
  /**
3
6
  * 获取技术栈标识
4
7
  * 目的:兼容用户非标准写法
@@ -27,10 +30,10 @@ function getFramework(_framework) {
27
30
  case 'vue3.0':
28
31
  case 'vue 3.0':
29
32
  curFramework = 3;
30
- console.error(`${consoleTag} 暂不支持 vue3.0 技术栈。`);
33
+ errorLog('暂不支持 vue3.0 技术栈。');
31
34
  break;
32
35
  case 'react-js':
33
- console.error(`${consoleTag} 暂不支持 react-js 技术栈。`);
36
+ errorLog('暂不支持 react-js 技术栈。');
34
37
  curFramework = 0;
35
38
  break;
36
39
  case 'react':
@@ -43,6 +46,62 @@ function getFramework(_framework) {
43
46
  return curFramework;
44
47
  }
45
48
 
49
+ // 输出红色字体的错误日志
50
+ function errorLog(message, spinner) {
51
+ const errorMessage = `${consoleTag} ${chalk.red(message)}`;
52
+ if (spinner) {
53
+ spinner.fail(errorMessage);
54
+ } else {
55
+ console.error(errorMessage);
56
+ }
57
+ }
58
+
59
+ // 输出黄色字体的警告日志
60
+ function warningLog(message) {
61
+ const warningMessage = `${consoleTag} ${chalk.yellow(message)}`;
62
+ if (spinner) {
63
+ spinner.warn(warningMessage);
64
+ } else {
65
+ console.warn(warningMessage);
66
+ }
67
+ }
68
+
69
+ // 输出绿色字体的成功日志
70
+ function successLog(message) {
71
+ const successMessage = `${consoleTag} ${chalk.green(message)}`;
72
+ if (spinner) {
73
+ spinner.succeed(successMessage);
74
+ } else {
75
+ console.log(successMessage);
76
+ }
77
+ }
78
+
79
+ /**
80
+ * 使用 TypeScript 官方 API 解析 tsconfig.json(推荐)
81
+ * 需要安装: npm install typescript --save-dev
82
+ * 优点: 官方支持,能正确处理 extends、注释等所有特性
83
+ */
84
+ function parseTsConfigWithTypeScript(configPath) {
85
+ try {
86
+ const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
87
+
88
+ if (configFile.error) {
89
+ throw new Error(`解析 tsconfig.json 失败: ${configFile.error.messageText}`);
90
+ }
91
+
92
+ return configFile.config;
93
+ } catch (error) {
94
+ if (error.code === 'MODULE_NOT_FOUND') {
95
+ throw new Error('请先安装 typescript: npm install typescript --save-dev');
96
+ }
97
+ throw error;
98
+ }
99
+ }
100
+
46
101
  module.exports = {
47
- getFramework
102
+ getFramework,
103
+ errorLog,
104
+ warningLog,
105
+ successLog,
106
+ parseTsConfigWithTypeScript
48
107
  };
@@ -1,6 +1,8 @@
1
1
  const path = require('path');
2
2
  const { exec } = require('child_process');
3
3
  const ora = require('ora');
4
+ const { consoleTag } = require('../neoParams');
5
+ const { errorLog } = require('../common');
4
6
 
5
7
  /**
6
8
  * 打开自定义组件项目
@@ -45,7 +47,7 @@ module.exports = function (editorType, targetPath) {
45
47
  }
46
48
 
47
49
  if (commands.length === 0) {
48
- console.error(`${consoleTag}不支持的操作系统: ${process.platform}`);
50
+ errorLog(`不支持的操作系统: ${process.platform}`);
49
51
  process.exit(1);
50
52
  }
51
53
 
@@ -54,14 +56,10 @@ module.exports = function (editorType, targetPath) {
54
56
  // 尝试执行命令列表中的第一个可用命令
55
57
  const tryCommand = (index) => {
56
58
  if (index >= commands.length) {
57
- spinner.fail(
58
- `${consoleTag}无法打开编辑器,已尝试所有可用方式。\n 请确保已安装 Cursor 或 Visual Studio Code 并将其添加到系统 PATH 中。`
59
+ errorLog(
60
+ `无法打开编辑器,已尝试所有可用方式。\n 请确保已安装 Cursor 或 Visual Studio Code 并将其添加到系统 PATH 中。`,
61
+ spinner
59
62
  );
60
- if (isMac) {
61
- console.error(
62
- `${consoleTag}macOS 提示: 如果已安装编辑器,请确保在编辑器中通过 Command+Shift+P 执行 "Shell Command: Install 'code' command in PATH" 或类似命令。`
63
- );
64
- }
65
63
  process.exit(1);
66
64
  }
67
65
 
package/test/demo3.js CHANGED
@@ -1,3 +1,3 @@
1
1
  const openEditor = require('../src/module/main').openEditor;
2
2
 
3
- openEditor('cursor', '/Users/liudan/neo-custom-widget/neo-cmp-cli/src/template/antd-custom-cmp-template');
3
+ openEditor('auto', 'src');
@@ -0,0 +1,30 @@
1
+ const { execSync } = require('child_process');
2
+
3
+ // 所有需要废弃的版本(1.6.2 之前的所有版本)
4
+ const versionsToDeprecate = ["1.6.2-beta.5"];
5
+
6
+ const packageName = 'neo-cmp-cli';
7
+ const deprecateMessage = '此版本为开发中版本(存在 bug),请升级到最新版本。';
8
+
9
+ console.log(`开始标记 ${versionsToDeprecate.length} 个版本为废弃状态...\n`);
10
+
11
+ let successCount = 0;
12
+ let failCount = 0;
13
+
14
+ versionsToDeprecate.forEach((version, index) => {
15
+ try {
16
+ const command = `npm deprecate ${packageName}@${version} "${deprecateMessage}"`;
17
+ console.log(`[${index + 1}/${versionsToDeprecate.length}] 正在标记 ${version}...`);
18
+ execSync(command, { stdio: 'inherit' });
19
+ successCount++;
20
+ console.log(`✓ ${version} 已成功标记\n`);
21
+ } catch (error) {
22
+ failCount++;
23
+ console.error(`✗ ${version} 标记失败: ${error.message}\n`);
24
+ }
25
+ });
26
+
27
+ console.log('\n========================================');
28
+ console.log(`完成!成功: ${successCount}, 失败: ${failCount}`);
29
+ console.log('========================================');
30
+