neo-cmp-cli 1.6.1-beta.1 → 1.6.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo-cmp-cli",
3
- "version": "1.6.1-beta.1",
3
+ "version": "1.6.2",
4
4
  "description": "前端脚手架:自定义组件开发工具,支持react 和 vue2.0技术栈。",
5
5
  "keywords": [
6
6
  "neo-cli",
@@ -5,7 +5,7 @@
5
5
  <meta name="format-detection" content="telephone=no"/>
6
6
  <meta name="viewport" content="initial-scale=1.0,user-scalable=no,width=device-width,viewport-fit=cover">
7
7
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
8
- <title>neo-widget Demo</title>
8
+ <title>自定义组件预览页</title>
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
@@ -25,19 +25,30 @@ module.exports = {
25
25
  $public: resolve('public')
26
26
  }
27
27
  },
28
- // sassResources中的sass文件会自动注入每一个sass文件中
28
+ // sassResources 中的 sass 文件会自动注入项目中每一个 sass 文件中
29
29
  sassResources: [
30
30
  resolve('./src/assets/css/common.scss'),
31
31
  resolve('./src/assets/css/mixin.scss')
32
32
  ],
33
33
  // createDeclaration: true, // 打包时是否创建ts声明文件
34
- ignoreNodeModules: false, // 打包时是否忽略 node_modules
35
- allowList: [], // ignoreNodeModules为true时生效
36
- projectDir: ['src']
34
+ ignoreNodeModules: false // 打包时是否忽略 node_modules
35
+ // allowList: [], // ignoreNodeModules true 时生效
36
+ // projectDir: ['src'],
37
37
  // template: resolve('./public/template.html'), // 自定义html模板
38
38
  // plugins: [],
39
39
  // babelPlugins: [],
40
40
  },
41
+ // 用于添加 Neo 共享依赖模块的配置信息
42
+ /*
43
+ neoCommonModule: {
44
+ // neoExports: ['xxModule'], // 自定义组件 共享出来的模块,支持数组和对象形式
45
+ neoExports: { // 对象写法
46
+ 'xx-module': path.resolve('./src/components/xx-module'), // 导出 xx组件 或 xx模块
47
+ },
48
+ // remoteDeps: ['xxCmpType'], // 远程依赖组件,表示当前自定义组件会用到的依赖组件,需要和 neoExternals 配合使用
49
+ // neoExternals: ['xxModule'], // 自定义组件中需要剔除的模块,仅支持数组写法
50
+ },
51
+ */
41
52
  preview: {
42
53
  // 用于开启本地预览模式的相关配置信息
43
54
  /*
@@ -67,12 +78,13 @@ module.exports = {
67
78
  entry: { // 根据 src/components 目录下的文件自动生成 entry 相关配置
68
79
  // 外链调试(在线上页面设计器端预览自定义组件)
69
80
  index: [
70
- './src/components/info-card/register.ts',
71
- './src/components/info-card/model.ts',
81
+ './src/components/xxCmp/register.ts',
82
+ './src/components/xxCmp/model.ts',
72
83
  ],
73
84
  },
74
85
  NODE_ENV: 'development',
75
86
  port: 80, // 设置基础端口,如果被占用则自动寻找可用端口
87
+ closeHotReload: true, // 是否关闭热更新
76
88
  assetsPublicPath: '/', // 设置静态资源的引用路径(根域名+路径)
77
89
  assetsSubDirectory: '',
78
90
  hostname: 'localhost',
@@ -85,23 +97,32 @@ module.exports = {
85
97
  }
86
98
  */
87
99
  },
88
- publish2oss: {
89
- // 用于构建并发布至 OSS 的相关配置
100
+ // NeoCRM 平台配置
101
+ neoConfig: {
102
+ neoBaseURL: 'https://crm-cd.xiaoshouyi.com', // 平台根地址(默认:https://crm.xiaoshouyi.com)
103
+ tokenAPI: 'https://login-cd.xiaoshouyi.com/auc/oauth2/token', // Token 获取接口地址(默认:https://login.xiaoshouyi.com/auc/oauth2/token)
104
+ // NeoCRM 授权配置
105
+ auth: {
106
+ client_id: 'xx', // 客户端 ID,从创建连接器的客户端信息中获取(Client_Id)
107
+ client_secret: 'xxx', // 客户端秘钥,从创建连接器的客户端信息中获取(Client_Secret)
108
+ username: 'xx', // 用户在销售易系统中的用户名
109
+ /**
110
+ * password 为 用户在销售易系统中的账号密码加上 8 位安全令牌。
111
+ * 例如,用户密码为 123456,安全令牌为 ABCDEFGH,则 password 的值应为 123456ABCDEFGH。
112
+ */
113
+ password: 'xx xx' // 用户账户密码 + 8 位安全令牌
114
+ }
115
+ },
116
+ pushCmp: {
117
+ // 用于构建并发布至 NeoCRM 的相关配置
90
118
  /*
91
119
  【特别说明】以下配置项都自带默认值,非必填。如需自定义请自行配置。
92
120
  NODE_ENV: 'production',
93
121
  entry: { // 根据 src/components 目录下的文件自动生成 entry 相关配置
94
- InfoCardModel: './src/components/info-card/model.ts',
95
- infoCard: './src/components/info-card/register.ts'
122
+ InfoCardModel: './src/components/xxCmp/model.ts',
123
+ infoCard: './src/components/xxCmp/register.ts'
96
124
  },
97
125
  cssExtract: false, // 不额外提取css文件
98
- ossType: 'ali', // oss类型:ali、baidu
99
- ossConfig: {
100
- endpoint: 'https://oss-cn-beijing.aliyuncs.com',
101
- AccessKeyId: 'xxx',
102
- AccessKeySecret: 'xx',
103
- bucket: 'neo-widgets' // 存储桶名称
104
- },
105
126
  assetsRoot: resolve('dist') // 上传指定目录下的脚本文件
106
127
  */
107
128
  }
@@ -12,7 +12,8 @@ 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
-
15
+ const hasNeoProject = require('../utils/hasNeoProject.js');
16
+ const consoleTag = require('../utils/neoParams').consoleTag;
16
17
  // neo 的 package 文件
17
18
  const neoPackage = require('../../package.json');
18
19
 
@@ -30,7 +31,7 @@ console.log(chalk.green(`当前版本:v${neoPackage.version}.\n`));
30
31
  yargs
31
32
  .command(
32
33
  'init [options]',
33
- '创建一个自定义组件',
34
+ '根据模板创建一个自定义组件',
34
35
  (yargs) => {
35
36
  yargs
36
37
  .reset()
@@ -55,6 +56,12 @@ yargs
55
56
  },
56
57
  (argv) => {
57
58
  if (argv.type && argv.name) {
59
+ if (hasNeoProject()) {
60
+ console.error(
61
+ `${consoleTag}创建自定义组件失败,当前目录(${process.cwd()})已经是一个自定义组件项目,请勿重复创建。`
62
+ );
63
+ process.exit(1);
64
+ }
58
65
  if (argv.mode === 'github') {
59
66
  neoInit(argv.type, argv.name);
60
67
  } else {
@@ -143,7 +150,7 @@ yargs
143
150
  )
144
151
  .command(
145
152
  'config init',
146
- '初始化 neo 配置文件',
153
+ '创建 neo.config.js 配置文件',
147
154
  (yargs) => {
148
155
  yargs
149
156
  .reset()
@@ -377,7 +384,7 @@ yargs
377
384
  )
378
385
  .command(
379
386
  'dev',
380
- '开启组件预览模式',
387
+ '开启本地调试模式',
381
388
  (yargs) => {
382
389
  yargs
383
390
  .reset()
@@ -416,7 +423,7 @@ yargs
416
423
  )
417
424
  .command(
418
425
  'build2lib',
419
- '构建lib库',
426
+ '构建 UMD 模块',
420
427
  (yargs) => {
421
428
  yargs
422
429
  .reset()
@@ -473,7 +480,7 @@ yargs
473
480
  )
474
481
  .command(
475
482
  'pushCmp [options]',
476
- '发布组件到 NeoCRM 平台',
483
+ '构建并发布自定义组件到 NeoCRM 平台',
477
484
  (yargs) => {
478
485
  yargs
479
486
  .reset()
@@ -517,7 +524,7 @@ yargs
517
524
  )
518
525
  .command(
519
526
  'build2esm',
520
- '构建esm模块',
527
+ '构建 ESM 模块',
521
528
  (yargs) => {
522
529
  yargs
523
530
  .reset()
@@ -551,6 +558,29 @@ yargs
551
558
  inspect(argv.type);
552
559
  }
553
560
  )
561
+ .command(
562
+ 'open [options]',
563
+ '使用 Cursor 或 VSCode 打开项目',
564
+ (yargs) => {
565
+ yargs
566
+ .reset()
567
+ .usage(titleTip('Usage') + ': $0 open [options]')
568
+ .option('editor', {
569
+ alias: 'e',
570
+ describe: '编辑器类型(cursor/vscode/auto),默认为 auto(自动检测)',
571
+ default: 'auto',
572
+ choices: ['cursor', 'vscode', 'code', 'auto']
573
+ })
574
+ .option('path', {
575
+ alias: 'p',
576
+ describe: '要打开的项目路径,默认为当前目录'
577
+ })
578
+ .alias('h', 'help');
579
+ },
580
+ (argv) => {
581
+ mainAction.openEditor(argv.editor, argv.path);
582
+ }
583
+ )
554
584
  .alias('h', 'help')
555
585
  .alias('v', 'version')
556
586
  .help()
@@ -18,6 +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
22
 
22
23
  const getValue = (originValue, defaultValue) => {
23
24
  return originValue !== undefined ? originValue : defaultValue;
@@ -268,5 +269,7 @@ module.exports = {
268
269
  deleteCmp: (cmpType, neoService) => {
269
270
  deleteCmp(cmpType, curConfig.neoConfig, neoService);
270
271
  },
271
- build2esm: (fileName) => akfun.build2esm(fileName, curConfig, consoleTag) // 构建esm输出模块
272
+ build2esm: (fileName) => akfun.build2esm(fileName, curConfig, consoleTag), // 构建esm输出模块
273
+ // 打开编辑器(Cursor 或 VSCode)
274
+ openEditor: openNeoProject
272
275
  };
@@ -16,8 +16,7 @@ const NeoCrmAPI = {
16
16
  delete: '/rest/metadata/v3.0/ui/customComponents',
17
17
  query: '/rest/metadata/v3.0/ui/customComponents/actions/queryCustomComponents', // 带分页
18
18
  queryAll: '/rest/metadata/v3.0/ui/customComponents/actions/queryAllCustomComponents', // 不带分页
19
- saveAPI: '/rest/metadata/v3.0/ui/customComponents/actions/saveOrUpdateComponent', // 创建或者保存接口地址
20
- deleteAPI: '/rest/metadata/v3.0/ui/customComponents'
19
+ saveAPI: '/rest/metadata/v3.0/ui/customComponents/actions/saveOrUpdateComponent' // 创建或者保存接口地址
21
20
  };
22
21
 
23
22
  const cmpFields = [
@@ -528,13 +527,13 @@ class NeoService {
528
527
 
529
528
  return this.cmpList || [];
530
529
  }
531
-
530
+
532
531
  /**
533
532
  * 删除自定义组件
534
533
  * @param {*} cmpType 自定义组件类型
535
534
  * @returns {Promise<object>} 删除结果
536
535
  */
537
- async deleteCustomComponent(cmpType) {
536
+ async deleteCmp(cmpType) {
538
537
  // 确保 token 有效
539
538
  const token = await this.ensureValidToken();
540
539
 
@@ -542,9 +541,9 @@ class NeoService {
542
541
  throw new Error('自定义组件名称不能为空。');
543
542
  }
544
543
 
545
- let fullDeleteAPI = this.buildFullUrl(NeoCrmAPI.deleteAPI);
546
- fullDeleteAPI += `?cmpType=${cmpType}`;
547
-
544
+ let fullDeleteAPI = this.buildFullUrl(NeoCrmAPI.delete);
545
+ fullDeleteAPI += `/${cmpType}`;
546
+
548
547
  const response = await axios.delete(fullDeleteAPI, {
549
548
  headers: {
550
549
  Authorization: `Bearer ${token}`,
@@ -78,8 +78,8 @@ module.exports = {
78
78
  entry: { // 根据 src/components 目录下的文件自动生成 entry 相关配置
79
79
  // 外链调试(在线上页面设计器端预览自定义组件)
80
80
  index: [
81
- './src/components/info-card/register.ts',
82
- './src/components/info-card/model.ts',
81
+ './src/components/xxCmp/register.ts',
82
+ './src/components/xxCmp/model.ts',
83
83
  ],
84
84
  },
85
85
  NODE_ENV: 'development',
@@ -119,8 +119,8 @@ module.exports = {
119
119
  【特别说明】以下配置项都自带默认值,非必填。如需自定义请自行配置。
120
120
  NODE_ENV: 'production',
121
121
  entry: { // 根据 src/components 目录下的文件自动生成 entry 相关配置
122
- InfoCardModel: './src/components/entity-form/model.ts',
123
- infoCard: './src/components/entity-form/register.ts'
122
+ InfoCardModel: './src/components/xxCmp/model.ts',
123
+ infoCard: './src/components/xxCmp/register.ts'
124
124
  },
125
125
  cssExtract: false, // 不额外提取css文件
126
126
  assetsRoot: resolve('dist') // 上传指定目录下的脚本文件
@@ -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.1",
51
+ "neo-cmp-cli": "^1.6.2",
52
52
  "husky": "^4.2.5",
53
53
  "lint-staged": "^10.2.9",
54
54
  "prettier": "^2.0.5"
@@ -80,8 +80,8 @@ module.exports = {
80
80
  entry: { // 根据 src/components 目录下的文件自动生成 entry 相关配置
81
81
  // 外链调试(在线上页面设计器端预览自定义组件)
82
82
  index: [
83
- './src/components/info-card/register.ts',
84
- './src/components/info-card/model.ts',
83
+ './src/components/xxCmp/register.ts',
84
+ './src/components/xxCmp/model.ts',
85
85
  ],
86
86
  },
87
87
  NODE_ENV: 'development',
@@ -121,8 +121,8 @@ module.exports = {
121
121
  【特别说明】以下配置项都自带默认值,非必填。如需自定义请自行配置。
122
122
  NODE_ENV: 'production',
123
123
  entry: { // 根据 src/components 目录下的文件自动生成 entry 相关配置
124
- InfoCardModel: './src/components/entity-form/model.ts',
125
- infoCard: './src/components/entity-form/register.ts'
124
+ InfoCardModel: './src/components/xxCmp/model.ts',
125
+ infoCard: './src/components/xxCmp/register.ts'
126
126
  },
127
127
  cssExtract: false, // 不额外提取css文件
128
128
  assetsRoot: resolve('dist') // 上传指定目录下的脚本文件
@@ -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.1",
51
+ "neo-cmp-cli": "^1.6.2",
52
52
  "husky": "^4.2.5",
53
53
  "lint-staged": "^10.2.9",
54
54
  "prettier": "^2.0.5",
@@ -119,8 +119,8 @@ module.exports = {
119
119
  【特别说明】以下配置项都自带默认值,非必填。如需自定义请自行配置。
120
120
  NODE_ENV: 'production',
121
121
  entry: { // 根据 src/components 目录下的文件自动生成 entry 相关配置
122
- InfoCardModel: './src/components/entity-form/model.ts',
123
- infoCard: './src/components/entity-form/register.ts'
122
+ InfoCardModel: './src/components/xxCmp/model.ts',
123
+ infoCard: './src/components/xxCmp/register.ts'
124
124
  },
125
125
  cssExtract: false, // 不额外提取css文件
126
126
  assetsRoot: resolve('dist') // 上传指定目录下的脚本文件
@@ -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.1",
49
+ "neo-cmp-cli": "^1.6.2",
50
50
  "husky": "^4.2.5",
51
51
  "lint-staged": "^10.2.9",
52
52
  "prettier": "^2.0.5"
@@ -86,8 +86,8 @@ module.exports = {
86
86
  entry: { // 根据 src/components 目录下的文件自动生成 entry 相关配置
87
87
  // 外链调试(在线上页面设计器端预览自定义组件)
88
88
  index: [
89
- './src/components/entity-form/register.ts',
90
- './src/components/entity-form/model.ts',
89
+ './src/components/xxCmp/register.ts',
90
+ './src/components/xxCmp/model.ts',
91
91
  ],
92
92
  },
93
93
  NODE_ENV: 'development',
@@ -127,8 +127,8 @@ module.exports = {
127
127
  【特别说明】以下配置项都自带默认值,非必填。如需自定义请自行配置。
128
128
  NODE_ENV: 'production',
129
129
  entry: { // 根据 src/components 目录下的文件自动生成 entry 相关配置
130
- InfoCardModel: './src/components/entity-form/model.ts',
131
- infoCard: './src/components/entity-form/register.ts'
130
+ InfoCardModel: './src/components/xxCmp/model.ts',
131
+ infoCard: './src/components/xxCmp/register.ts'
132
132
  },
133
133
  cssExtract: false, // 不额外提取css文件
134
134
  assetsRoot: resolve('dist') // 上传指定目录下的脚本文件
@@ -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.5.0-beta.5",
55
+ "neo-cmp-cli": "^1.6.2",
56
56
  "husky": "^4.2.5",
57
57
  "lint-staged": "^10.2.9",
58
58
  "prettier": "^2.0.5"
@@ -78,8 +78,8 @@ module.exports = {
78
78
  entry: { // entry 会根据 src/components 目录下的文件自动生成
79
79
  // 外链调试(在线上页面设计器端预览自定义组件)
80
80
  index: [
81
- './src/components/info-card/register.js',
82
- './src/components/info-card/model.js',
81
+ './src/components/xxCmp/register.js',
82
+ './src/components/xxCmp/model.js',
83
83
  ],
84
84
  },
85
85
  NODE_ENV: 'development',
@@ -118,8 +118,8 @@ module.exports = {
118
118
  【特别说明】以下配置项都自带默认值,非必填。如需自定义请自行配置。
119
119
  NODE_ENV: 'production',
120
120
  entry: { // 根据 src/components 目录下的文件自动生成 entry 相关配置
121
- InfoCardModel: './src/components/entity-form/model.ts',
122
- infoCard: './src/components/entity-form/register.ts'
121
+ InfoCardModel: './src/components/xxCmp/model.ts',
122
+ infoCard: './src/components/xxCmp/register.ts'
123
123
  },
124
124
  cssExtract: false, // 不额外提取css文件
125
125
  assetsRoot: resolve('dist') // 上传指定目录下的脚本文件
@@ -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.1",
48
+ "neo-cmp-cli": "^1.6.2",
49
49
  "husky": "^4.2.5",
50
50
  "lint-staged": "^10.2.9",
51
51
  "prettier": "^2.0.5"
@@ -78,8 +78,8 @@ module.exports = {
78
78
  entry: { // 根据 src/components 目录下的文件自动生成 entry 相关配置
79
79
  // 外链调试(在线上页面设计器端预览自定义组件)
80
80
  index: [
81
- './src/components/list-widget/register.ts',
82
- './src/components/list-widget/model.ts',
81
+ './src/components/xxCmp/register.ts',
82
+ './src/components/xxCmp/model.ts',
83
83
  ],
84
84
  },
85
85
  NODE_ENV: 'development',
@@ -119,8 +119,8 @@ module.exports = {
119
119
  【特别说明】以下配置项都自带默认值,非必填。如需自定义请自行配置。
120
120
  NODE_ENV: 'production',
121
121
  entry: { // 根据 src/components 目录下的文件自动生成 entry 相关配置
122
- InfoCardModel: './src/components/entity-form/model.ts',
123
- infoCard: './src/components/entity-form/register.ts'
122
+ InfoCardModel: './src/components/xxCmp/model.ts',
123
+ infoCard: './src/components/xxCmp/register.ts'
124
124
  },
125
125
  cssExtract: false, // 不额外提取css文件
126
126
  assetsRoot: resolve('dist') // 上传指定目录下的脚本文件
@@ -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.1",
50
+ "neo-cmp-cli": "^1.6.2",
51
51
  "husky": "^4.2.5",
52
52
  "lint-staged": "^10.2.9",
53
53
  "prettier": "^2.0.5"
@@ -84,8 +84,8 @@ module.exports = {
84
84
  entry: { // entry 未配置时,cli 会根据 src/components 目录下的文件自动生成对应的 entry
85
85
  // 外链调试(在线上页面设计器端预览自定义组件)
86
86
  index: [
87
- './src/components/vue-info-card/register.js',
88
- './src/components/vue-info-card/model.js',
87
+ './src/components/xxCmp/register.js',
88
+ './src/components/xxCmp/model.js',
89
89
  ],
90
90
  },
91
91
  NODE_ENV: 'development',
@@ -127,8 +127,8 @@ module.exports = {
127
127
  【特别说明】以下配置项都自带默认值,非必填。如需自定义请自行配置。
128
128
  NODE_ENV: 'production',
129
129
  entry: { // 根据 src/components 目录下的文件自动生成 entry 相关配置
130
- InfoCardModel: './src/components/entity-form/model.ts',
131
- infoCard: './src/components/entity-form/register.ts'
130
+ InfoCardModel: './src/components/xxCmp/model.ts',
131
+ infoCard: './src/components/xxCmp/register.ts'
132
132
  },
133
133
  cssExtract: false, // 不额外提取css文件
134
134
  assetsRoot: resolve('dist') // 上传指定目录下的脚本文件
@@ -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.1",
48
+ "neo-cmp-cli": "^1.6.2",
49
49
  "husky": "^4.2.5",
50
50
  "lint-staged": "^10.2.9",
51
51
  "prettier": "^2.0.5",
@@ -69,6 +69,9 @@ module.exports = function (projectPath, options = {}) {
69
69
  console.log('='.repeat(60));
70
70
  console.log('\n📝 说明:组件开发工具(neo-cmp-cli)无法直接改变当前命令窗口工作目录,');
71
71
  console.log(` 您需要手动执行上述命令才能进入刚创建的自定义组件项目(${projectName})。\n`);
72
+
73
+ // 自动打开 IDE编辑器
74
+ openNeoProject('auto', projectName);
72
75
  }
73
76
 
74
77
  return success;
@@ -8,6 +8,30 @@ const { consoleTag } = require('../neoParams'); // 输出标记
8
8
  const hasCmpTypeByDir = require('./hasCmpTypeByDir');
9
9
  const hasNeoProject = require('../projectUtils/hasNeoProject');
10
10
 
11
+ /**
12
+ * 检查对象键名是否需要加引号
13
+ * @param {string} key 键名
14
+ * @returns {boolean} 是否需要加引号
15
+ */
16
+ function needsQuotes(key) {
17
+ // 如果键名包含特殊字符(如 @、-、空格等)或不是有效的 JavaScript 标识符,需要加引号
18
+ // 有效的 JavaScript 标识符:以字母、$、_ 开头,后续可以是字母、数字、$、_
19
+ const validIdentifierRegex = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
20
+ return !validIdentifierRegex.test(key);
21
+ }
22
+
23
+ /**
24
+ * 格式化对象键名,如果需要则加引号
25
+ * @param {string} key 键名
26
+ * @returns {string} 格式化后的键名
27
+ */
28
+ function formatKey(key) {
29
+ if (needsQuotes(key)) {
30
+ return JSON.stringify(key);
31
+ }
32
+ return key;
33
+ }
34
+
11
35
  /**
12
36
  * 将配置对象格式化为 JavaScript 代码字符串
13
37
  * @param {*} obj 配置对象
@@ -74,7 +98,7 @@ function formatConfigObject(obj, indent = 0, fileDir = '') {
74
98
  const items = keys.map((key) => {
75
99
  const value = obj[key];
76
100
  const formattedValue = formatConfigObject(value, indent + 1, fileDir);
77
- return nextIndentStr + key + ': ' + formattedValue;
101
+ return nextIndentStr + formatKey(key) + ': ' + formattedValue;
78
102
  });
79
103
  return '{\n' + items.join(',\n') + '\n' + indentStr + '}';
80
104
  }
@@ -243,7 +267,7 @@ module.exports = async function (cmpZipUrl, cmpName, componentBaseDir = './src/c
243
267
 
244
268
  const newPackageJsonDeps = _.omit(
245
269
  sourcePackageJson.dependencies,
246
- targetPackageJson.dependencies
270
+ Object.keys(targetPackageJson.dependencies)
247
271
  );
248
272
  const newDeps = Object.keys(newPackageJsonDeps);
249
273
  if (newDeps.length > 0) {
@@ -281,7 +305,9 @@ module.exports = async function (cmpZipUrl, cmpName, componentBaseDir = './src/c
281
305
  const mergedConfig = _.merge({}, sourceConfig, targetConfig);
282
306
 
283
307
  // 提取目标文件的头部(module.exports 之前的内容)
284
- const moduleExportMatch = targetContent.match(/^([\s\S]*?)(module\.exports\s*=\s*\{[\s\S]*\};?\s*)$/);
308
+ const moduleExportMatch = targetContent.match(
309
+ /^([\s\S]*?)(module\.exports\s*=\s*\{[\s\S]*\};?\s*)$/
310
+ );
285
311
  let fileHeader = '';
286
312
  if (moduleExportMatch) {
287
313
  fileHeader = moduleExportMatch[1];
@@ -292,7 +318,8 @@ module.exports = async function (cmpZipUrl, cmpName, componentBaseDir = './src/c
292
318
  fileHeader = targetContent.substring(0, lastBraceIndex);
293
319
  } else {
294
320
  // 如果都没有找到,使用默认头部
295
- fileHeader = "'use strict';\nconst path = require('path');\n\n// 统一路径解析\nfunction resolve(dir) {\n return path.resolve(__dirname, dir);\n}\n\n";
321
+ fileHeader =
322
+ "'use strict';\nconst path = require('path');\n\n// 统一路径解析\nfunction resolve(dir) {\n return path.resolve(__dirname, dir);\n}\n\n";
296
323
  }
297
324
  }
298
325
 
@@ -309,18 +336,31 @@ module.exports = async function (cmpZipUrl, cmpName, componentBaseDir = './src/c
309
336
  await fs.writeFile(targetPath, mergedContent, 'utf8');
310
337
  } catch (configError) {
311
338
  spinner.warn(
312
- `${consoleTag}合并 neo.config.js 配置文件时出现警告:${configError.message || configError}`
339
+ `${consoleTag}合并 neo.config.js 配置文件时出现警告:${
340
+ configError.message || configError
341
+ }`
313
342
  );
314
343
  }
315
344
  } else if (fileName === 'tsconfig.json') {
316
345
  // 处理 tsconfig.json 文件(当目标文件已存在时)
317
- const sourceTsconfigJson = await fs.readJson(sourcePath);
318
- // 先判断 targetPath 是否存在,如果存在则合并,否则直接写入
319
- if (await fs.pathExists(targetPath)) {
320
- const targetTsconfigJson = _.merge({}, sourceTsconfigJson, targetTsconfigJson);
321
- await fs.writeJson(targetPath, targetTsconfigJson, { spaces: 2 });
322
- } else {
323
- await fs.writeJson(targetPath, sourceTsconfigJson, { spaces: 2 });
346
+ try {
347
+ const sourceTsconfigJson = await fs.readJson(sourcePath);
348
+ // 先判断 targetPath 是否存在,如果存在则合并,否则直接写入
349
+ if (await fs.pathExists(targetPath)) {
350
+ const targetTsconfigJson = await fs.readJson(targetPath);
351
+ // 合并配置:源配置合并到目标配置(目标配置优先级更高)
352
+ const mergedTsconfigJson = _.merge({}, sourceTsconfigJson, targetTsconfigJson);
353
+ // 使用 writeJson 写入,确保 JSON 格式正确(所有键名都会被正确序列化)
354
+ await fs.writeJson(targetPath, mergedTsconfigJson, { spaces: 2 });
355
+ } else {
356
+ await fs.writeJson(targetPath, sourceTsconfigJson, { spaces: 2 });
357
+ }
358
+ } catch (tsconfigError) {
359
+ spinner.warn(
360
+ `${consoleTag}合并 tsconfig.json 配置文件时出现警告:${
361
+ tsconfigError.message || tsconfigError
362
+ }`
363
+ );
324
364
  }
325
365
  }
326
366
  }
@@ -51,7 +51,7 @@ const deleteCmp = async (cmpType, authConfig, _neoService) => {
51
51
 
52
52
  // 调用删除 API
53
53
  spinner.info(`正在删除${cmpType}自定义组件...`);
54
- await neoService.deleteCustomComponent(cmpType);
54
+ await neoService.deleteCmp(cmpType);
55
55
  spinner.succeed(`已成功删除${cmpType}自定义组件!\n`);
56
56
  } catch (error) {
57
57
  spinner.fail(`删除自定义组件失败: ${error.message}`);
@@ -60,4 +60,3 @@ const deleteCmp = async (cmpType, authConfig, _neoService) => {
60
60
  };
61
61
 
62
62
  module.exports = deleteCmp;
63
-
@@ -0,0 +1,83 @@
1
+ const path = require('path');
2
+ const { exec } = require('child_process');
3
+ const ora = require('ora');
4
+
5
+ /**
6
+ * 打开自定义组件项目
7
+ */
8
+ module.exports = function (editorType, targetPath) {
9
+ const targetDir = targetPath ? path.resolve(targetPath) : process.cwd();
10
+ const isMac = process.platform === 'darwin';
11
+ const isWindows = process.platform === 'win32';
12
+ const isLinux = process.platform === 'linux';
13
+
14
+ // 构建命令列表(按优先级排序)
15
+ let commands = [];
16
+ let editorName = '编辑器';
17
+
18
+ // 根据编辑器类型和平台构建命令列表
19
+ if (editorType === 'cursor') {
20
+ editorName = 'Cursor';
21
+ if (isMac) {
22
+ commands = [`cursor "${targetDir}"`, `open -a "Cursor" "${targetDir}"`];
23
+ } else if (isWindows || isLinux) {
24
+ commands = [`cursor "${targetDir}"`];
25
+ }
26
+ } else if (editorType === 'vscode' || editorType === 'code') {
27
+ editorName = 'Visual Studio Code';
28
+ if (isMac) {
29
+ commands = [`code "${targetDir}"`, `open -a "Visual Studio Code" "${targetDir}"`];
30
+ } else if (isWindows || isLinux) {
31
+ commands = [`code "${targetDir}"`];
32
+ }
33
+ } else {
34
+ // 自动检测:优先尝试 Cursor,如果失败则尝试 VSCode
35
+ if (isMac) {
36
+ commands = [
37
+ `cursor "${targetDir}"`,
38
+ `code "${targetDir}"`,
39
+ `open -a "Cursor" "${targetDir}"`,
40
+ `open -a "Visual Studio Code" "${targetDir}"`
41
+ ];
42
+ } else if (isWindows || isLinux) {
43
+ commands = [`cursor "${targetDir}"`, `code "${targetDir}"`];
44
+ }
45
+ }
46
+
47
+ if (commands.length === 0) {
48
+ console.error(`${consoleTag}不支持的操作系统: ${process.platform}`);
49
+ process.exit(1);
50
+ }
51
+
52
+ const spinner = ora(`${consoleTag}正在尝试使用 ${editorName} 打开项目: ${targetDir}`).start();
53
+
54
+ // 尝试执行命令列表中的第一个可用命令
55
+ const tryCommand = (index) => {
56
+ if (index >= commands.length) {
57
+ spinner.fail(
58
+ `${consoleTag}无法打开编辑器,已尝试所有可用方式。\n 请确保已安装 Cursor 或 Visual Studio Code 并将其添加到系统 PATH 中。`
59
+ );
60
+ if (isMac) {
61
+ console.error(
62
+ `${consoleTag}macOS 提示: 如果已安装编辑器,请确保在编辑器中通过 Command+Shift+P 执行 "Shell Command: Install 'code' command in PATH" 或类似命令。`
63
+ );
64
+ }
65
+ process.exit(1);
66
+ }
67
+
68
+ const command = commands[index];
69
+ // 使用 exec 配合 shell 执行命令,这样可以更好地处理路径中的空格和特殊字符
70
+ exec(command, { shell: true }, (error, stdout, stderr) => {
71
+ if (error) {
72
+ // 如果当前命令失败,尝试下一个
73
+ tryCommand(index + 1);
74
+ } else {
75
+ // 命令执行成功,不需要继续尝试
76
+ // 编辑器命令通常会立即返回,即使编辑器窗口已经打开
77
+ }
78
+ });
79
+ };
80
+
81
+ tryCommand(0);
82
+ spinner.stop();
83
+ };
package/test/demo3.js ADDED
@@ -0,0 +1,3 @@
1
+ const openEditor = require('../src/module/main').openEditor;
2
+
3
+ openEditor('cursor', '/Users/liudan/neo-custom-widget/neo-cmp-cli/src/template/antd-custom-cmp-template');