@iflow-ai/iflow-cli 0.4.16 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/entry.js +57 -57
- package/bundle/iflow-cli-vscode-ide-companion-0.2.9.vsix +0 -0
- package/bundle/iflow.js +2120 -1617
- package/package.json +6 -1
- package/scripts/postinstall-idea-plugin.js +88 -63
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iflow-ai/iflow-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=20.0.0"
|
|
6
6
|
},
|
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
"LICENSE"
|
|
64
64
|
],
|
|
65
65
|
"devDependencies": {
|
|
66
|
+
"@types/jsdom": "^27.0.0",
|
|
66
67
|
"@types/marked": "^5.0.2",
|
|
67
68
|
"@types/micromatch": "^4.0.9",
|
|
68
69
|
"@types/mime-types": "^3.0.1",
|
|
@@ -118,7 +119,11 @@
|
|
|
118
119
|
"access": "public"
|
|
119
120
|
},
|
|
120
121
|
"dependencies": {
|
|
122
|
+
"asciify-image": "^0.1.10",
|
|
123
|
+
"gifuct-js": "^2.1.2",
|
|
121
124
|
"ink": "^6.5.0",
|
|
125
|
+
"ink-picture": "^1.3.3",
|
|
126
|
+
"is-unicode-supported": "^2.1.0",
|
|
122
127
|
"react-devtools-core": "^6.1.5",
|
|
123
128
|
"shell-quote": "^1.8.3"
|
|
124
129
|
}
|
|
@@ -4,8 +4,17 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
|
|
7
|
+
import {
|
|
8
|
+
existsSync,
|
|
9
|
+
mkdirSync,
|
|
10
|
+
createWriteStream,
|
|
11
|
+
statSync,
|
|
12
|
+
readdirSync,
|
|
13
|
+
createReadStream,
|
|
14
|
+
unlinkSync,
|
|
15
|
+
rmSync,
|
|
16
|
+
} from 'fs';
|
|
17
|
+
import { join } from 'path';
|
|
9
18
|
import { fileURLToPath } from 'url';
|
|
10
19
|
import os from 'os';
|
|
11
20
|
import https from 'https';
|
|
@@ -15,48 +24,29 @@ import { pipeline } from 'stream/promises';
|
|
|
15
24
|
import { Extract } from 'unzipper';
|
|
16
25
|
|
|
17
26
|
// 常量定义
|
|
18
|
-
const PLUGIN_URL =
|
|
27
|
+
const PLUGIN_URL =
|
|
28
|
+
'https://cloud.iflow.cn/iflow-cli/idea-plugin/iflow-idea-0.0.5.zip';
|
|
19
29
|
const PLUGIN_DIR_NAME = 'iflow-idea';
|
|
20
30
|
const TEMP_DIR_NAME = 'tstar-cli-idea-plugin';
|
|
21
31
|
const LOG_PREFIX = '[JetBrains Extension]';
|
|
22
32
|
// 扩展支持的JetBrains IDE产品
|
|
23
33
|
const IDE_PATTERNS = [
|
|
24
|
-
'IntelliJIdea',
|
|
25
|
-
'
|
|
26
|
-
'
|
|
27
|
-
'
|
|
28
|
-
'
|
|
29
|
-
'
|
|
30
|
-
'
|
|
31
|
-
'
|
|
32
|
-
'
|
|
33
|
-
'
|
|
34
|
+
'IntelliJIdea',
|
|
35
|
+
'IdeaIC', // IntelliJ IDEA
|
|
36
|
+
'PyCharm',
|
|
37
|
+
'PyCharmCE', // PyCharm
|
|
38
|
+
'GoLand', // GoLand
|
|
39
|
+
'WebStorm', // WebStorm
|
|
40
|
+
'PhpStorm', // PhpStorm
|
|
41
|
+
'CLion', // CLion
|
|
42
|
+
'RubyMine', // RubyMine
|
|
43
|
+
'DataGrip', // DataGrip
|
|
44
|
+
'Rider', // Rider
|
|
45
|
+
'AndroidStudio', // Android Studio
|
|
34
46
|
];
|
|
35
47
|
|
|
36
48
|
// 获取当前脚本的目录
|
|
37
49
|
const __filename = fileURLToPath(import.meta.url);
|
|
38
|
-
const __dirname = dirname(__filename);
|
|
39
|
-
|
|
40
|
-
// 验证路径是否安全
|
|
41
|
-
function validatePath(path) {
|
|
42
|
-
if (!path || typeof path !== 'string') {
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// 防止路径遍历攻击
|
|
47
|
-
const normalizedPath = resolve(path);
|
|
48
|
-
return !normalizedPath.includes('..');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// 检查文件是否存在且可执行
|
|
52
|
-
function isExecutable(filePath) {
|
|
53
|
-
try {
|
|
54
|
-
const stats = statSync(filePath);
|
|
55
|
-
return stats.isFile() && (stats.mode & parseInt('111', 8)) !== 0;
|
|
56
|
-
} catch {
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
50
|
|
|
61
51
|
// 获取 JetBrains IDE 插件目录的跨平台函数
|
|
62
52
|
function getJetBrainsPluginsDirectory() {
|
|
@@ -87,14 +77,17 @@ function findLatestJetBrainsDirectories() {
|
|
|
87
77
|
try {
|
|
88
78
|
// 获取所有匹配的IDE目录,并按修改时间排序
|
|
89
79
|
const dirs = readdirSync(jetbrainsDir)
|
|
90
|
-
.filter(dir => IDE_PATTERNS.some(pattern => dir.startsWith(pattern)))
|
|
91
|
-
.map(dir => {
|
|
80
|
+
.filter((dir) => IDE_PATTERNS.some((pattern) => dir.startsWith(pattern)))
|
|
81
|
+
.map((dir) => {
|
|
92
82
|
const fullPath = join(jetbrainsDir, dir);
|
|
93
83
|
try {
|
|
94
84
|
const stats = statSync(fullPath);
|
|
95
85
|
return { path: fullPath, mtime: stats.mtime, name: dir };
|
|
96
86
|
} catch (error) {
|
|
97
|
-
console.warn(
|
|
87
|
+
console.warn(
|
|
88
|
+
`${LOG_PREFIX} Cannot access directory ${fullPath}:`,
|
|
89
|
+
error.message,
|
|
90
|
+
);
|
|
98
91
|
return null;
|
|
99
92
|
}
|
|
100
93
|
})
|
|
@@ -108,8 +101,10 @@ function findLatestJetBrainsDirectories() {
|
|
|
108
101
|
|
|
109
102
|
// 按IDE类型分组,每种IDE只保留最新版本
|
|
110
103
|
const latestByType = {};
|
|
111
|
-
dirs.forEach(dir => {
|
|
112
|
-
const ideType = IDE_PATTERNS.find(pattern =>
|
|
104
|
+
dirs.forEach((dir) => {
|
|
105
|
+
const ideType = IDE_PATTERNS.find((pattern) =>
|
|
106
|
+
dir.name.startsWith(pattern),
|
|
107
|
+
);
|
|
113
108
|
if (ideType && !latestByType[ideType]) {
|
|
114
109
|
latestByType[ideType] = dir;
|
|
115
110
|
}
|
|
@@ -117,7 +112,10 @@ function findLatestJetBrainsDirectories() {
|
|
|
117
112
|
|
|
118
113
|
return Object.values(latestByType);
|
|
119
114
|
} catch (error) {
|
|
120
|
-
console.error(
|
|
115
|
+
console.error(
|
|
116
|
+
`${LOG_PREFIX} Error finding JetBrains IDE directories:`,
|
|
117
|
+
error.message,
|
|
118
|
+
);
|
|
121
119
|
return [];
|
|
122
120
|
}
|
|
123
121
|
}
|
|
@@ -130,18 +128,22 @@ async function downloadPlugin(url, destPath) {
|
|
|
130
128
|
// 根据URL协议选择适当的模块
|
|
131
129
|
const protocol = url.startsWith('https:') ? https : http;
|
|
132
130
|
|
|
133
|
-
protocol
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
131
|
+
protocol
|
|
132
|
+
.get(url, (response) => {
|
|
133
|
+
if (response.statusCode !== 200) {
|
|
134
|
+
reject(
|
|
135
|
+
new Error(`Failed to download plugin: ${response.statusCode}`),
|
|
136
|
+
);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
138
139
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
140
|
+
pipeline(response, file)
|
|
141
|
+
.then(() => resolve())
|
|
142
|
+
.catch(reject);
|
|
143
|
+
})
|
|
144
|
+
.on('error', (err) => {
|
|
145
|
+
reject(err);
|
|
146
|
+
});
|
|
145
147
|
});
|
|
146
148
|
}
|
|
147
149
|
|
|
@@ -177,7 +179,9 @@ async function installJetBrainsExtension() {
|
|
|
177
179
|
// 查找所有支持的 JetBrains IDE 目录
|
|
178
180
|
const ideDirs = findLatestJetBrainsDirectories();
|
|
179
181
|
if (ideDirs.length === 0) {
|
|
180
|
-
console.warn(
|
|
182
|
+
console.warn(
|
|
183
|
+
`${LOG_PREFIX} Could not find any JetBrains IDE installation, skipping plugin installation`,
|
|
184
|
+
);
|
|
181
185
|
return;
|
|
182
186
|
}
|
|
183
187
|
|
|
@@ -187,7 +191,10 @@ async function installJetBrainsExtension() {
|
|
|
187
191
|
try {
|
|
188
192
|
mkdirSync(tempDir, { recursive: true });
|
|
189
193
|
} catch (error) {
|
|
190
|
-
console.error(
|
|
194
|
+
console.error(
|
|
195
|
+
`${LOG_PREFIX} Failed to create temporary directory: ${tempDir}`,
|
|
196
|
+
error.message,
|
|
197
|
+
);
|
|
191
198
|
return;
|
|
192
199
|
}
|
|
193
200
|
}
|
|
@@ -217,7 +224,10 @@ async function installJetBrainsExtension() {
|
|
|
217
224
|
try {
|
|
218
225
|
mkdirSync(pluginsDir, { recursive: true });
|
|
219
226
|
} catch (error) {
|
|
220
|
-
console.error(
|
|
227
|
+
console.error(
|
|
228
|
+
`${LOG_PREFIX} Failed to create plugins directory: ${pluginsDir}`,
|
|
229
|
+
error.message,
|
|
230
|
+
);
|
|
221
231
|
continue; // 跳过此IDE,继续下一个
|
|
222
232
|
}
|
|
223
233
|
}
|
|
@@ -226,10 +236,15 @@ async function installJetBrainsExtension() {
|
|
|
226
236
|
const existingPluginDir = join(pluginsDir, PLUGIN_DIR_NAME);
|
|
227
237
|
if (existsSync(existingPluginDir)) {
|
|
228
238
|
try {
|
|
229
|
-
console.info(
|
|
239
|
+
console.info(
|
|
240
|
+
`${LOG_PREFIX} Removing existing plugin directory: ${existingPluginDir}`,
|
|
241
|
+
);
|
|
230
242
|
rmSync(existingPluginDir, { recursive: true, force: true });
|
|
231
243
|
} catch (error) {
|
|
232
|
-
console.error(
|
|
244
|
+
console.error(
|
|
245
|
+
`${LOG_PREFIX} Failed to remove existing plugin directory: ${existingPluginDir}`,
|
|
246
|
+
error.message,
|
|
247
|
+
);
|
|
233
248
|
// 继续安装,即使删除失败
|
|
234
249
|
}
|
|
235
250
|
}
|
|
@@ -240,9 +255,14 @@ async function installJetBrainsExtension() {
|
|
|
240
255
|
try {
|
|
241
256
|
// 直接解压到插件目录,不创建额外的子目录
|
|
242
257
|
await extractPlugin(pluginFilePath, pluginsDir);
|
|
243
|
-
console.info(
|
|
258
|
+
console.info(
|
|
259
|
+
`${LOG_PREFIX} ✔ Plugin installed successfully to: ${pluginsDir}`,
|
|
260
|
+
);
|
|
244
261
|
} catch (error) {
|
|
245
|
-
console.error(
|
|
262
|
+
console.error(
|
|
263
|
+
`${LOG_PREFIX} Failed to install plugin for ${ideDir.name}:`,
|
|
264
|
+
error.message,
|
|
265
|
+
);
|
|
246
266
|
}
|
|
247
267
|
}
|
|
248
268
|
|
|
@@ -250,22 +270,27 @@ async function installJetBrainsExtension() {
|
|
|
250
270
|
try {
|
|
251
271
|
unlinkSync(pluginFilePath);
|
|
252
272
|
} catch (error) {
|
|
253
|
-
console.warn(
|
|
273
|
+
console.warn(
|
|
274
|
+
`${LOG_PREFIX} Failed to clean up temporary file: ${pluginFilePath}`,
|
|
275
|
+
error.message,
|
|
276
|
+
);
|
|
254
277
|
}
|
|
255
|
-
|
|
256
278
|
} catch (error) {
|
|
257
279
|
console.error(`${LOG_PREFIX} Failed to install plugin:`, error.message);
|
|
258
280
|
console.debug(`${LOG_PREFIX} Stack trace:`, error.stack);
|
|
259
281
|
}
|
|
260
282
|
} catch (error) {
|
|
261
|
-
console.error(
|
|
283
|
+
console.error(
|
|
284
|
+
`${LOG_PREFIX} Unexpected error during JetBrains extension installation:`,
|
|
285
|
+
error.message,
|
|
286
|
+
);
|
|
262
287
|
console.debug(`${LOG_PREFIX} Stack trace:`, error.stack);
|
|
263
288
|
}
|
|
264
289
|
}
|
|
265
290
|
|
|
266
291
|
// 只在非 CI 环境执行
|
|
267
292
|
if (!process.env.CI) {
|
|
268
|
-
installJetBrainsExtension().catch(error => {
|
|
293
|
+
installJetBrainsExtension().catch((error) => {
|
|
269
294
|
console.error(`${LOG_PREFIX} Installation failed:`, error.message);
|
|
270
295
|
});
|
|
271
296
|
}
|