neo-cmp-cli 1.8.6-beta.6 → 1.8.7

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 (158) hide show
  1. package/bin/index.js +2 -2
  2. package/package.json +3 -3
  3. package/src/config/auth.config.js +27 -0
  4. package/src/config/default.config.js +176 -0
  5. package/src/config/index.js +9 -0
  6. package/src/initData/defaultTemplate.html +13 -0
  7. package/src/initData/neo.config.js +138 -0
  8. package/src/main.js +221 -0
  9. package/src/module/inspect.js +41 -0
  10. package/src/module/neoInit.js +55 -0
  11. package/src/module/neoInitByCopy.js +61 -0
  12. package/src/neo/NeoUMDContent.js +30 -0
  13. package/src/neo/neoLogin.js +565 -0
  14. package/src/neo/neoRequire.js +125 -0
  15. package/src/neo/neoService.js +874 -0
  16. package/src/neo/webpack.mf.js +60 -0
  17. package/src/neo/wrapperContent.js +16 -0
  18. package/src/oss/publish2oss.js +348 -0
  19. package/src/plugins/AddNeoRequirePlugin-v1.js +47 -0
  20. package/src/plugins/AddNeoRequirePlugin.js +179 -0
  21. package/src/plugins/README.md +109 -0
  22. package/src/utils/autoEntryRootDir.js +85 -0
  23. package/src/utils/cmpUtils/createCmpByTemplate.js +60 -0
  24. package/src/utils/cmpUtils/createCmpByZip.js +408 -0
  25. package/src/utils/cmpUtils/createCommonModulesCode.js +121 -0
  26. package/src/utils/cmpUtils/deleteCmp.js +63 -0
  27. package/src/utils/cmpUtils/getCmpModelRegisterCode.js +31 -0
  28. package/src/utils/cmpUtils/getCmpPreviewCode.js +43 -0
  29. package/src/utils/cmpUtils/getCmpRegisterCode.js +31 -0
  30. package/src/utils/cmpUtils/getCmpTypeByDir.js +41 -0
  31. package/src/utils/cmpUtils/hasCmpTypeByDir.js +11 -0
  32. package/src/utils/cmpUtils/previewCmp.js +55 -0
  33. package/src/utils/cmpUtils/pullCmp.js +104 -0
  34. package/src/utils/cmpUtils/pushCmp.js +230 -0
  35. package/src/utils/common.js +107 -0
  36. package/src/utils/configureNeoBuild.js +109 -0
  37. package/src/utils/generateEntries.js +63 -0
  38. package/src/utils/neoConfigInit.js +13 -0
  39. package/src/utils/neoParams.js +12 -0
  40. package/src/utils/pathUtils.js +23 -0
  41. package/src/utils/projectNameValidator.js +76 -0
  42. package/src/utils/projectUtils/createCmpProjectByTemplate.js +59 -0
  43. package/src/utils/projectUtils/createCmpProjectZip.js +120 -0
  44. package/src/utils/projectUtils/getEntries.js +80 -0
  45. package/src/utils/projectUtils/getEntriesWithAutoRegister.js +108 -0
  46. package/src/utils/projectUtils/hasNeoProject.js +17 -0
  47. package/src/utils/projectUtils/openProject.js +96 -0
  48. package/src/utils/projectUtils/updatePublishLog.js +30 -0
  49. package/src/utils/replaceInFiles.js +47 -0
  50. package/src/utils/replaceInFilesByMap.js +54 -0
  51. package/src/utils/replaceInPackage.js +134 -0
  52. package/src/utils/resetPackageVersion.js +115 -0
  53. package/test/deprecate-versions.js +1 -1
  54. package/test/neo.config.js +1 -25
  55. package/dist/_virtual/AddNeoRequirePlugin.js +0 -8
  56. package/dist/_virtual/OverloadYield.js +0 -5
  57. package/dist/_virtual/_commonjsHelpers.js +0 -40
  58. package/dist/_virtual/array-set.js +0 -5
  59. package/dist/_virtual/base64-vlq.js +0 -5
  60. package/dist/_virtual/base64.js +0 -5
  61. package/dist/_virtual/binary-search.js +0 -5
  62. package/dist/_virtual/createCmpByZip.js +0 -8
  63. package/dist/_virtual/deleteCmp.js +0 -8
  64. package/dist/_virtual/index.js +0 -9
  65. package/dist/_virtual/mapping-list.js +0 -5
  66. package/dist/_virtual/neoLogin.js +0 -8
  67. package/dist/_virtual/neoService.js +0 -8
  68. package/dist/_virtual/openProject.js +0 -8
  69. package/dist/_virtual/publish2oss.js +0 -8
  70. package/dist/_virtual/pullCmp.js +0 -8
  71. package/dist/_virtual/pushCmp.js +0 -8
  72. package/dist/_virtual/quick-sort.js +0 -5
  73. package/dist/_virtual/regenerator.js +0 -5
  74. package/dist/_virtual/regeneratorAsync.js +0 -5
  75. package/dist/_virtual/regeneratorAsyncGen.js +0 -5
  76. package/dist/_virtual/regeneratorAsyncIterator.js +0 -5
  77. package/dist/_virtual/regeneratorDefine.js +0 -5
  78. package/dist/_virtual/regeneratorKeys.js +0 -5
  79. package/dist/_virtual/regeneratorRuntime.js +0 -5
  80. package/dist/_virtual/regeneratorValues.js +0 -5
  81. package/dist/_virtual/source-map-consumer.js +0 -5
  82. package/dist/_virtual/source-map-generator.js +0 -5
  83. package/dist/_virtual/source-map-support.js +0 -5
  84. package/dist/_virtual/source-map.js +0 -5
  85. package/dist/_virtual/source-node.js +0 -5
  86. package/dist/_virtual/typeof.js +0 -5
  87. package/dist/_virtual/typescript.js +0 -5
  88. package/dist/_virtual/util.js +0 -5
  89. package/dist/config/auth.config.js +0 -50
  90. package/dist/config/default.config.js +0 -225
  91. package/dist/config/index.js +0 -27
  92. package/dist/main.js +0 -9
  93. package/dist/main2.js +0 -261
  94. package/dist/module/inspect.js +0 -64
  95. package/dist/module/neoInit.js +0 -69
  96. package/dist/module/neoInitByCopy.js +0 -81
  97. package/dist/neo/neoLogin.js +0 -663
  98. package/dist/neo/neoRequire.js +0 -118
  99. package/dist/neo/neoService.js +0 -1246
  100. package/dist/node_modules/@babel/runtime/helpers/OverloadYield.js +0 -19
  101. package/dist/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js +0 -29
  102. package/dist/node_modules/@babel/runtime/helpers/esm/extends.js +0 -13
  103. package/dist/node_modules/@babel/runtime/helpers/regenerator.js +0 -105
  104. package/dist/node_modules/@babel/runtime/helpers/regeneratorAsync.js +0 -24
  105. package/dist/node_modules/@babel/runtime/helpers/regeneratorAsyncGen.js +0 -23
  106. package/dist/node_modules/@babel/runtime/helpers/regeneratorAsyncIterator.js +0 -50
  107. package/dist/node_modules/@babel/runtime/helpers/regeneratorDefine.js +0 -37
  108. package/dist/node_modules/@babel/runtime/helpers/regeneratorKeys.js +0 -25
  109. package/dist/node_modules/@babel/runtime/helpers/regeneratorRuntime.js +0 -98
  110. package/dist/node_modules/@babel/runtime/helpers/regeneratorValues.js +0 -35
  111. package/dist/node_modules/@babel/runtime/helpers/typeof.js +0 -25
  112. package/dist/node_modules/@babel/runtime/regenerator/index.js +0 -29
  113. package/dist/node_modules/buffer-from/index.js +0 -57
  114. package/dist/node_modules/source-map/lib/array-set.js +0 -134
  115. package/dist/node_modules/source-map/lib/base64-vlq.js +0 -144
  116. package/dist/node_modules/source-map/lib/base64.js +0 -81
  117. package/dist/node_modules/source-map/lib/binary-search.js +0 -122
  118. package/dist/node_modules/source-map/lib/mapping-list.js +0 -94
  119. package/dist/node_modules/source-map/lib/quick-sort.js +0 -126
  120. package/dist/node_modules/source-map/lib/source-map-consumer.js +0 -1018
  121. package/dist/node_modules/source-map/lib/source-map-generator.js +0 -385
  122. package/dist/node_modules/source-map/lib/source-node.js +0 -400
  123. package/dist/node_modules/source-map/lib/util.js +0 -449
  124. package/dist/node_modules/source-map/source-map.js +0 -25
  125. package/dist/node_modules/source-map-support/source-map-support.js +0 -610
  126. package/dist/node_modules/typescript/lib/typescript.js +0 -22376
  127. package/dist/oss/publish2oss.js +0 -378
  128. package/dist/plugins/AddNeoRequirePlugin.js +0 -178
  129. package/dist/utils/autoEntryRootDir.js +0 -98
  130. package/dist/utils/cmpUtils/createCmpByTemplate.js +0 -73
  131. package/dist/utils/cmpUtils/createCmpByZip.js +0 -530
  132. package/dist/utils/cmpUtils/createCommonModulesCode.js +0 -84
  133. package/dist/utils/cmpUtils/deleteCmp.js +0 -98
  134. package/dist/utils/cmpUtils/getCmpModelRegisterCode.js +0 -38
  135. package/dist/utils/cmpUtils/getCmpPreviewCode.js +0 -37
  136. package/dist/utils/cmpUtils/getCmpRegisterCode.js +0 -38
  137. package/dist/utils/cmpUtils/getCmpTypeByDir.js +0 -58
  138. package/dist/utils/cmpUtils/hasCmpTypeByDir.js +0 -25
  139. package/dist/utils/cmpUtils/previewCmp.js +0 -74
  140. package/dist/utils/cmpUtils/pullCmp.js +0 -144
  141. package/dist/utils/cmpUtils/pushCmp.js +0 -290
  142. package/dist/utils/common.js +0 -121
  143. package/dist/utils/configureNeoBuild.js +0 -153
  144. package/dist/utils/generateEntries.js +0 -73
  145. package/dist/utils/neoConfigInit.js +0 -25
  146. package/dist/utils/neoParams.js +0 -23
  147. package/dist/utils/pathUtils.js +0 -48
  148. package/dist/utils/projectNameValidator.js +0 -89
  149. package/dist/utils/projectUtils/createCmpProjectByTemplate.js +0 -74
  150. package/dist/utils/projectUtils/createCmpProjectZip.js +0 -135
  151. package/dist/utils/projectUtils/getEntries.js +0 -99
  152. package/dist/utils/projectUtils/getEntriesWithAutoRegister.js +0 -127
  153. package/dist/utils/projectUtils/hasNeoProject.js +0 -31
  154. package/dist/utils/projectUtils/openProject.js +0 -169
  155. package/dist/utils/projectUtils/updatePublishLog.js +0 -45
  156. package/dist/utils/replaceInFilesByMap.js +0 -70
  157. package/dist/utils/replaceInPackage.js +0 -151
  158. package/dist/utils/resetPackageVersion.js +0 -134
@@ -0,0 +1,120 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const AdmZip = require('adm-zip');
4
+ const _ = require('lodash');
5
+ const { consoleTag } = require('../neoParams'); // 输出标记
6
+ const hasNeoProject = require('./hasNeoProject');
7
+
8
+ /**
9
+ * 创建自定义组件源码 zip 包
10
+ * @param {*} cmpType 自定义组件名称
11
+ * @returns {string} zip 文件路径
12
+ */
13
+ module.exports = function (cmpType, _projectPath, assetsRoot) {
14
+ const projectRoot = _projectPath || process.cwd();
15
+ const finalAssetsRoot = assetsRoot || path.join(projectRoot, 'dist');
16
+
17
+ if (!hasNeoProject(_projectPath)) {
18
+ console.error(`${consoleTag}当前目录不是自定义组件项目,请在自定义组件项目目录下执行。`);
19
+ process.exit(1);
20
+ }
21
+
22
+ if (!cmpType) {
23
+ console.error(`${consoleTag}自定义组件名称不能为空`);
24
+ process.exit(1);
25
+ }
26
+
27
+ const zip = new AdmZip();
28
+
29
+ // 需要排除的目录和文件
30
+ const excludeDirs = ['node_modules', '.neo-cli', 'dist'];
31
+ const excludeFiles = ['.eslintcache', 'auth.config.js'];
32
+
33
+ /**
34
+ * 判断文件/目录是否应该被排除
35
+ * @param {string} filePath 文件路径
36
+ * @param {string} relativePath 相对路径
37
+ * @returns {boolean} 是否应该排除
38
+ */
39
+ const shouldExclude = (filePath, relativePath) => {
40
+ const name = path.basename(filePath);
41
+ const stat = fs.statSync(filePath);
42
+
43
+ // 排除指定的目录
44
+ if (stat.isDirectory() && excludeDirs.includes(name)) {
45
+ return true;
46
+ }
47
+
48
+ // 排除指定的文件
49
+ if (stat.isFile() && excludeFiles.includes(name)) {
50
+ return true;
51
+ }
52
+
53
+ // 对于 src/components 目录,只包含 cmpType 子目录
54
+ // 处理逻辑:如果路径是 src/components/xxx,且 xxx 不是 cmpType,则排除
55
+ if (relativePath.startsWith('src/components')) {
56
+ const relativeToComponents = path.relative('src/components', relativePath);
57
+ // 如果相对路径不为空,说明已经在 components 的子目录中
58
+ if (relativeToComponents && relativeToComponents !== '.') {
59
+ const firstPart = relativeToComponents.split(path.sep)[0];
60
+ // 如果第一个部分不是 cmpType,则排除
61
+ if (firstPart !== cmpType) {
62
+ return true;
63
+ }
64
+ }
65
+ }
66
+
67
+ return false;
68
+ };
69
+
70
+ /**
71
+ * 递归遍历目录并添加到 zip
72
+ * @param {string} dirPath 目录路径
73
+ * @param {string} relativePath 相对路径(用于 zip 中的路径)
74
+ */
75
+ const addDirectoryToZip = (dirPath, relativePath = '') => {
76
+ try {
77
+ const items = fs.readdirSync(dirPath);
78
+
79
+ items.forEach((item) => {
80
+ const itemPath = path.join(dirPath, item);
81
+ const itemRelativePath = relativePath ? path.join(relativePath, item) : item;
82
+
83
+ // 检查是否应该排除
84
+ if (shouldExclude(itemPath, itemRelativePath)) {
85
+ return;
86
+ }
87
+
88
+ const stat = fs.statSync(itemPath);
89
+
90
+ if (stat.isDirectory()) {
91
+ // 递归处理子目录
92
+ addDirectoryToZip(itemPath, itemRelativePath);
93
+ } else if (stat.isFile()) {
94
+ // 添加文件到 zip,保持相对路径结构
95
+ const fileContent = fs.readFileSync(itemPath);
96
+ zip.addFile(itemRelativePath, fileContent);
97
+ }
98
+ });
99
+ } catch (error) {
100
+ console.error(`${consoleTag}遍历目录失败 (${dirPath}):`, error.message);
101
+ }
102
+ };
103
+
104
+ // 开始遍历项目根目录
105
+ addDirectoryToZip(projectRoot);
106
+
107
+ // 生成 zip 文件名
108
+ const zipFileName = `${_.camelCase(cmpType)}Source.zip`;
109
+ const zipPath = path.join(finalAssetsRoot, zipFileName);
110
+
111
+ // 如果已存在同名 zip 文件,先删除
112
+ if (fs.existsSync(zipPath)) {
113
+ fs.removeSync(zipPath);
114
+ }
115
+
116
+ // 写入 zip 文件
117
+ zip.writeZip(zipPath);
118
+
119
+ return zipPath;
120
+ };
@@ -0,0 +1,80 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const _ = require('lodash');
4
+ const { resolveToCurrentRoot } = require('../pathUtils');
5
+
6
+ /**
7
+ * 从指定目录获取组件入口文件
8
+ * @param {*} defaultComponentsDir 默认组件目录
9
+ * @returns 组件入口文件
10
+ */
11
+ module.exports = (defaultComponentsDir = './src/components', cmpType) => {
12
+ const widgetEntries = {};
13
+ const linkDebugEntries = {
14
+ index: []
15
+ };
16
+ const cmpTypes = []; // 用于记录组件名称
17
+ const defaultExports = {}; // 用于记录默认导出
18
+ const componentsBaseDir = resolveToCurrentRoot(defaultComponentsDir);
19
+ if (!fs.existsSync(componentsBaseDir)) {
20
+ console.error(`未找到组件目录,请检查 ${defaultComponentsDir} 目录是否存在`);
21
+
22
+ // 退出进程
23
+ process.exit(1);
24
+ }
25
+
26
+ try {
27
+ // 读取指定目录下的所有文件
28
+ let widgetDirs = [];
29
+ if (cmpType) {
30
+ // 如果传入了 cmpType,则只读取指定组件目录
31
+ widgetDirs = [cmpType];
32
+ } else {
33
+ widgetDirs = fs.readdirSync(componentsBaseDir);
34
+ }
35
+
36
+ // 遍历所有目录
37
+ widgetDirs.forEach((dir) => {
38
+ const filePath = path.join(componentsBaseDir, dir);
39
+ // 获取文件状态
40
+ const stat = fs.statSync(filePath);
41
+ // 如果文件是目录,则递归处理子目录
42
+ if (stat.isDirectory() && !dir.startsWith('.') && dir !== 'node_modules') {
43
+ const curCmpPath = path.join(componentsBaseDir, dir);
44
+ const curCmpName = dir; // _.camelCase(dir);
45
+ const cmpNameKey = _.camelCase(curCmpName);
46
+
47
+ // 记录组件类型
48
+ cmpTypes.push(curCmpName);
49
+
50
+ fs.readdirSync(curCmpPath)
51
+ .filter((file) => file.match(/[index|register|model]\.(tsx?|jsx?|vue)$/))
52
+ .map((file) => path.join(defaultComponentsDir, curCmpName, file))
53
+ .forEach((filePath) => {
54
+ const curPath = `./${filePath}`;
55
+ if (filePath.match(/register\.[tj]sx?$/)) {
56
+ widgetEntries[cmpNameKey] = curPath;
57
+ } else if (filePath.match(/model\.[tj]sx?$/)) {
58
+ widgetEntries[`${cmpNameKey}Model`] = curPath;
59
+ } else if (filePath.match(/index\.(tsx?|jsx?|vue)$/)) {
60
+ // 组件内容文件
61
+ defaultExports[cmpNameKey] = path.resolve(filePath); // 记录默认导出
62
+ }
63
+ linkDebugEntries.index.push(curPath);
64
+ });
65
+ }
66
+ });
67
+ } catch (error) {
68
+ console.error('获取自定义组件入口文件失败(getEntries):', error);
69
+
70
+ // 退出进程
71
+ process.exit(1);
72
+ }
73
+
74
+ return {
75
+ widgetEntries,
76
+ linkDebugEntries,
77
+ cmpTypes,
78
+ defaultExports
79
+ };
80
+ };
@@ -0,0 +1,108 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const _ = require('lodash');
4
+ const { resolveToCurrentRoot } = require('../pathUtils');
5
+ const getCmpRegisterCode = require('../cmpUtils/getCmpRegisterCode');
6
+ const getCmpModelRegisterCode = require('../cmpUtils/getCmpModelRegisterCode');
7
+ /**
8
+ * 从指定目录获取组件入口文件,并自动创建对应的注册文件
9
+ * @param {*} defaultComponentsDir 默认组件目录
10
+ * @returns 组件入口文件
11
+ */
12
+ module.exports = (defaultComponentsDir = './src/components', cmpType) => {
13
+ const widgetEntries = {};
14
+ const linkDebugEntries = {
15
+ index: []
16
+ };
17
+ const cmpTypes = []; // 用于记录组件名称
18
+ const defaultExports = {}; // 用于记录默认导出
19
+ const componentsBaseDir = resolveToCurrentRoot(defaultComponentsDir);
20
+ if (!fs.existsSync(componentsBaseDir)) {
21
+ console.error(`未找到组件目录,请检查 ${defaultComponentsDir} 目录是否存在`);
22
+
23
+ // 退出进程
24
+ process.exit(1);
25
+ }
26
+
27
+ // 创建存放 cli 的临时目录
28
+ const cliTempDir = resolveToCurrentRoot('./.neo-cli');
29
+ if (!fs.existsSync(cliTempDir)) {
30
+ fs.mkdirSync(cliTempDir);
31
+ }
32
+
33
+ try {
34
+ // 读取指定目录下的所有文件
35
+ let widgetDirs = [];
36
+ if (cmpType) {
37
+ // 如果传入了 cmpType,则只读取指定组件目录
38
+ widgetDirs = [cmpType];
39
+ } else {
40
+ widgetDirs = fs.readdirSync(componentsBaseDir);
41
+ }
42
+
43
+ // 遍历所有目录
44
+ widgetDirs.forEach((dir) => {
45
+ // 当前自定义组件目录
46
+ const widgetPath = path.join(componentsBaseDir, dir);
47
+ // 获取文件状态
48
+ const stat = fs.statSync(widgetPath);
49
+ // 如果文件是目录,则递归处理子目录
50
+ if (stat.isDirectory() && !dir.startsWith('.') && dir !== 'node_modules') {
51
+ // 当前自定义组件名称
52
+ const curCmpName = dir; // _.camelCase(dir);
53
+ const cmpNameKey = _.camelCase(curCmpName);
54
+
55
+ // 记录组件类型
56
+ cmpTypes.push(curCmpName);
57
+
58
+ // 当前自定义组件临时目录
59
+ const cmpTempDir = `${cliTempDir}/${curCmpName}`;
60
+ if (!fs.existsSync(cmpTempDir)) {
61
+ fs.mkdirSync(cmpTempDir);
62
+ }
63
+
64
+ fs.readdirSync(widgetPath)
65
+ .filter((file) => file.match(/(index|model)\.(tsx?|jsx?|vue)$/))
66
+ .map((file) => path.join(defaultComponentsDir, curCmpName, file))
67
+ .forEach((filePath) => {
68
+ if (filePath.match(/index\.(tsx?|jsx?|vue)$/)) {
69
+ // 记录默认导出
70
+ defaultExports[cmpNameKey] = path.resolve(filePath);
71
+
72
+ // 自动创建对应的注册文件
73
+ const registerContent = getCmpRegisterCode(componentsBaseDir, curCmpName);
74
+ const registerDir = `${cmpTempDir}/register.js`;
75
+
76
+ // 写入注册文件
77
+ fs.writeFileSync(registerDir, registerContent);
78
+
79
+ widgetEntries[cmpNameKey] = registerDir;
80
+ linkDebugEntries.index.push(registerDir);
81
+ } else if (filePath.match(/model\.[tj]sx?$/)) {
82
+ // 自动创建对应的模型注册文件
83
+ const modelRegisterContent = getCmpModelRegisterCode(componentsBaseDir, curCmpName);
84
+ const modelRegisterDir = `${cmpTempDir}/model.js`;
85
+
86
+ // 写入模型注册文件
87
+ fs.writeFileSync(modelRegisterDir, modelRegisterContent);
88
+
89
+ widgetEntries[`${cmpNameKey}Model`] = modelRegisterDir;
90
+ linkDebugEntries.index.push(modelRegisterDir);
91
+ }
92
+ });
93
+ }
94
+ });
95
+ } catch (error) {
96
+ console.error('获取自定义组件入口文件失败(getEntriesWithAutoRegister):', error);
97
+
98
+ // 退出进程
99
+ process.exit(1);
100
+ }
101
+
102
+ return {
103
+ widgetEntries,
104
+ linkDebugEntries,
105
+ cmpTypes,
106
+ defaultExports
107
+ };
108
+ };
@@ -0,0 +1,17 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+
4
+ /**
5
+ * 判断当前是否存在 自定义组件项目
6
+ * 备注:neo.config.js 和 package.json 必须同时存在才算作 自定义组件项目
7
+ */
8
+ module.exports = function (_projectPath) {
9
+ const projectPath = _projectPath || process.cwd();
10
+ const neoConfigPath = path.resolve(projectPath, 'neo.config.js');
11
+ const packagePath = path.resolve(projectPath, 'package.json');
12
+
13
+ if (fs.existsSync(neoConfigPath) && fs.existsSync(packagePath)) {
14
+ return true;
15
+ }
16
+ return false;
17
+ };
@@ -0,0 +1,96 @@
1
+ const path = require('path');
2
+ const fs = require('fs');
3
+ const open = require('open');
4
+ const ora = require('ora');
5
+ const { consoleTag } = require('../neoParams');
6
+ const { errorLog } = require('../common');
7
+
8
+ /**
9
+ * 打开自定义组件项目
10
+ */
11
+ const openProject = async function (editorType, targetPath) {
12
+ const targetDir = targetPath ? path.resolve(targetPath) : process.cwd();
13
+
14
+ // 检查目录是否存在
15
+ if (!fs.existsSync(targetDir)) {
16
+ errorLog(`目录不存在: ${targetDir}`);
17
+ process.exit(1);
18
+ }
19
+
20
+ // 检查是否为目录
21
+ const stats = fs.statSync(targetDir);
22
+ if (!stats.isDirectory()) {
23
+ errorLog(`路径不是目录: ${targetDir}`);
24
+ process.exit(1);
25
+ }
26
+
27
+ const isMac = process.platform === 'darwin';
28
+ const isWindows = process.platform === 'win32';
29
+ const isLinux = process.platform === 'linux';
30
+
31
+ // 构建编辑器配置列表(按优先级排序)
32
+ let editorConfigs = [];
33
+ let editorName = '编辑器';
34
+
35
+ // 根据编辑器类型和平台构建配置列表
36
+ if (editorType === 'cursor') {
37
+ editorName = 'Cursor';
38
+ // macOS 可以使用应用名称或命令名称
39
+ if (isMac) {
40
+ editorConfigs = [{ app: { name: 'cursor' } }, { app: { name: 'Cursor' } }];
41
+ } else if (isWindows || isLinux) {
42
+ editorConfigs = [{ app: { name: 'cursor' } }];
43
+ }
44
+ } else if (editorType === 'vscode' || editorType === 'code') {
45
+ editorName = 'Visual Studio Code';
46
+ if (isMac) {
47
+ editorConfigs = [{ app: { name: 'code' } }, { app: { name: 'Visual Studio Code' } }];
48
+ } else if (isWindows || isLinux) {
49
+ editorConfigs = [{ app: { name: 'code' } }];
50
+ }
51
+ } else {
52
+ // 自动检测:优先尝试 Cursor,如果失败则尝试 VSCode
53
+ if (isMac) {
54
+ editorConfigs = [
55
+ { app: { name: 'cursor' } },
56
+ { app: { name: 'Cursor' } },
57
+ { app: { name: 'code' } },
58
+ { app: { name: 'Visual Studio Code' } }
59
+ ];
60
+ } else if (isWindows || isLinux) {
61
+ editorConfigs = [{ app: { name: 'cursor' } }, { app: { name: 'code' } }];
62
+ }
63
+ }
64
+
65
+ if (editorConfigs.length === 0) {
66
+ errorLog(`不支持的操作系统: ${process.platform}`);
67
+ process.exit(1);
68
+ }
69
+
70
+ const spinner = ora(`${consoleTag}正在尝试使用 ${editorName} 打开项目: ${targetDir}`).start();
71
+
72
+ // 尝试打开编辑器
73
+ const tryOpenEditor = async (index) => {
74
+ if (index >= editorConfigs.length) {
75
+ errorLog(
76
+ `无法打开编辑器,已尝试所有可用方式。\n 请确保已安装 Cursor 或 Visual Studio Code 并将其添加到系统 PATH 中。`,
77
+ spinner
78
+ );
79
+ process.exit(1);
80
+ }
81
+
82
+ const config = editorConfigs[index];
83
+ try {
84
+ await open(targetDir, config);
85
+ spinner.stop();
86
+ // 成功打开,不需要继续尝试
87
+ } catch (error) {
88
+ // 如果当前配置失败,尝试下一个
89
+ await tryOpenEditor(index + 1);
90
+ }
91
+ };
92
+
93
+ await tryOpenEditor(0);
94
+ };
95
+
96
+ module.exports = openProject;
@@ -0,0 +1,30 @@
1
+ const fs = require('fs');
2
+ const _ = require('lodash');
3
+ const { resolveToCurrentRoot } = require('../pathUtils');
4
+ /**
5
+ * 更新发布日志
6
+ */
7
+ module.exports = function (curHistoryData) {
8
+ // 创建存放 cli 的临时目录
9
+ const cliTempDir = resolveToCurrentRoot('./.neo-cli');
10
+ if (!fs.existsSync(cliTempDir)) {
11
+ fs.mkdirSync(cliTempDir);
12
+ }
13
+
14
+ const historyFile = `${cliTempDir}/history.json`;
15
+ let historyData = {};
16
+ if (fs.existsSync(historyFile)) {
17
+ // 读取历史文件
18
+ try {
19
+ historyData = JSON.parse(fs.readFileSync(historyFile, 'utf8'));
20
+ } catch (error) {
21
+ console.error('读取历史文件失败:', error);
22
+ historyData = {};
23
+ }
24
+ }
25
+ const historyKey = new Date().toString();
26
+ historyData[historyKey] = curHistoryData;
27
+
28
+ // 更新历史文件
29
+ fs.writeFileSync(historyFile, JSON.stringify(historyData, null, 2));
30
+ };
@@ -0,0 +1,47 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+
4
+ /**
5
+ * 全局替换项目中的指定字符串
6
+ * @param dir 项目目录
7
+ * @param oldStr 旧字符串
8
+ * @param newStr 新字符串
9
+ * @param fileExtensions 文件扩展名
10
+ */
11
+ function replaceInFiles(
12
+ dir,
13
+ oldStr,
14
+ newStr,
15
+ fileExtensions = ['.js', '.jsx', '.ts', '.tsx', '.vue', '.html', '.css', '.scss', '.json']
16
+ ) {
17
+ try {
18
+ // 读取指定目录下的所有文件
19
+ const files = fs.readdirSync(dir);
20
+
21
+ // 遍历所有文件
22
+ files.forEach((file) => {
23
+ const filePath = path.join(dir, file);
24
+ // 获取文件状态
25
+ const stat = fs.statSync(filePath);
26
+ // 如果文件是目录,则递归处理子目录
27
+ if (stat.isDirectory() && !file.startsWith('.') && file !== 'node_modules') {
28
+ // 递归处理子目录
29
+ replaceInFiles(filePath, oldStr, newStr, fileExtensions);
30
+ } else if (stat.isFile()) {
31
+ // 检查文件扩展名
32
+ const ext = path.extname(file);
33
+ if (fileExtensions.includes(ext)) {
34
+ let content = fs.readFileSync(filePath, 'utf8');
35
+ if (content.includes(oldStr)) {
36
+ content = content.replace(new RegExp(oldStr, 'g'), newStr); // 全局替换
37
+ fs.writeFileSync(filePath, content, 'utf8');
38
+ }
39
+ }
40
+ }
41
+ });
42
+ } catch (error) {
43
+ console.error('replaceInFiles 运行失败:', error);
44
+ }
45
+ }
46
+
47
+ module.exports = replaceInFiles;
@@ -0,0 +1,54 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+
4
+ /**
5
+ * 全局替换项目中的指定字符串
6
+ * @param dir 项目目录
7
+ * @param needReplaceStrMap {
8
+ * [oldStr]: newStr
9
+ * }
10
+ * @param fileExtensions 文件扩展名
11
+ */
12
+ function replaceInFilesByMap(
13
+ dir,
14
+ needReplaceStrMap = {},
15
+ fileExtensions = ['.js', '.jsx', '.ts', '.tsx', '.vue', '.html', '.css', '.scss', '.json']
16
+ ) {
17
+ try {
18
+ // 读取指定目录下的所有文件
19
+ const files = fs.readdirSync(dir);
20
+
21
+ // 遍历所有文件
22
+ files.forEach((file) => {
23
+ const filePath = path.join(dir, file);
24
+ // 获取文件状态
25
+ const stat = fs.statSync(filePath);
26
+ // 如果文件是目录,则递归处理子目录
27
+ if (stat.isDirectory() && !file.startsWith('.') && file !== 'node_modules') {
28
+ // 递归处理子目录
29
+ replaceInFilesByMap(filePath, needReplaceStrMap, fileExtensions);
30
+ } else if (stat.isFile()) {
31
+ // 检查文件扩展名
32
+ const ext = path.extname(file);
33
+ if (fileExtensions.includes(ext)) {
34
+ if (needReplaceStrMap &&Object.keys(needReplaceStrMap).length > 0) {
35
+ let content = fs.readFileSync(filePath, 'utf8');
36
+ Object.keys(needReplaceStrMap).forEach((key) => {
37
+ const oldStr = key;
38
+ const newStr = needReplaceStrMap[key];
39
+ if (content.includes(oldStr)) {
40
+ content = content.replace(new RegExp(oldStr, 'g'), newStr); // 全局替换
41
+ }
42
+ });
43
+ // 写入文件(更新文件内容)
44
+ fs.writeFileSync(filePath, content, 'utf8');
45
+ }
46
+ }
47
+ }
48
+ });
49
+ } catch (error) {
50
+ console.error('replaceInFiles 运行失败:', error);
51
+ }
52
+ }
53
+
54
+ module.exports = replaceInFilesByMap;
@@ -0,0 +1,134 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+
4
+ /**
5
+ * package.json文件中替换指定字符串
6
+ * @param dir 项目目录
7
+ * @param oldStr 旧字符串
8
+ * @param newStr 新字符串
9
+ * @returns 替换结果对象: { success: boolean, message: string, filePath?: string, replaced?: boolean }
10
+ */
11
+ function replaceInPackage(dir, oldStr, newStr) {
12
+ try {
13
+ // 检查目录是否存在
14
+ if (!fs.existsSync(dir)) {
15
+ return {
16
+ success: false,
17
+ message: `目录不存在: ${dir}`
18
+ };
19
+ }
20
+
21
+ // 检查是否为目录
22
+ const stat = fs.statSync(dir);
23
+ if (!stat.isDirectory()) {
24
+ return {
25
+ success: false,
26
+ message: `指定路径不是目录: ${dir}`
27
+ };
28
+ }
29
+
30
+ // 构建package.json的完整路径
31
+ const packageJsonPath = path.join(dir, 'package.json');
32
+
33
+ // 检查package.json文件是否存在
34
+ if (!fs.existsSync(packageJsonPath)) {
35
+ return {
36
+ success: false,
37
+ message: `package.json文件不存在: ${packageJsonPath}`
38
+ };
39
+ }
40
+
41
+ // 读取package.json文件内容
42
+ let content = fs.readFileSync(packageJsonPath, 'utf8');
43
+
44
+ // 检查是否包含要替换的字符串
45
+ if (!content.includes(oldStr)) {
46
+ return {
47
+ success: true,
48
+ message: `package.json中未找到要替换的字符串: ${oldStr}`,
49
+ filePath: packageJsonPath,
50
+ replaced: false
51
+ };
52
+ }
53
+
54
+ // 执行全局替换
55
+ const newContent = content.replace(new RegExp(oldStr, 'g'), newStr);
56
+
57
+ // 检查是否有实际变化
58
+ if (content === newContent) {
59
+ return {
60
+ success: true,
61
+ message: '替换后内容无变化',
62
+ filePath: packageJsonPath,
63
+ replaced: false
64
+ };
65
+ }
66
+
67
+ // 写入替换后的内容
68
+ fs.writeFileSync(packageJsonPath, newContent, 'utf8');
69
+
70
+ // 统计替换次数
71
+ const matches = content.match(new RegExp(oldStr, 'g'));
72
+ const replaceCount = matches ? matches.length : 0;
73
+
74
+ return {
75
+ success: true,
76
+ message: `成功替换 ${replaceCount} 处字符串`,
77
+ filePath: packageJsonPath,
78
+ replaced: true
79
+ };
80
+ } catch (error) {
81
+ return {
82
+ success: false,
83
+ message: `replaceInPackage 运行失败: ${error.message}`
84
+ };
85
+ }
86
+ }
87
+
88
+ /**
89
+ * 批量替换多个目录中的package.json文件
90
+ * @param dirs 目录数组
91
+ * @param oldStr 旧字符串
92
+ * @param newStr 新字符串
93
+ * @returns 批量替换结果
94
+ */
95
+ function replaceInMultiplePackages(dirs, oldStr, newStr) {
96
+ const results = dirs.map((dir) => ({
97
+ dir,
98
+ result: replaceInPackage(dir, oldStr, newStr)
99
+ }));
100
+
101
+ const success = results.filter((r) => r.result.success).length;
102
+ const failed = results.length - success;
103
+
104
+ return {
105
+ total: dirs.length,
106
+ success,
107
+ failed,
108
+ results
109
+ };
110
+ }
111
+
112
+ /**
113
+ * 验证package.json文件格式是否正确
114
+ * @param filePath package.json文件路径
115
+ * @returns 验证结果: { valid: boolean, error?: string }
116
+ */
117
+ function validatePackageJson(filePath) {
118
+ try {
119
+ const content = fs.readFileSync(filePath, 'utf8');
120
+ JSON.parse(content);
121
+ return { valid: true };
122
+ } catch (error) {
123
+ return {
124
+ valid: false,
125
+ error: `JSON格式错误: ${error.message}`
126
+ };
127
+ }
128
+ }
129
+
130
+ module.exports = {
131
+ replaceInPackage,
132
+ replaceInMultiplePackages,
133
+ validatePackageJson
134
+ };