edgeone-cli 1.0.13 → 1.0.14
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/dist/api/client.js +1 -210
- package/dist/commands/config.js +1 -312
- package/dist/commands/edgeone.js +1 -414
- package/dist/constants/index.js +1 -60
- package/dist/index.js +1 -37
- package/dist/repl/config-menu.js +1 -264
- package/dist/repl/index.js +1 -95
- package/dist/repl/prefetch-menu.js +1 -192
- package/dist/repl/purge-menu.js +1 -228
- package/dist/repl/ui.js +1 -29
- package/dist/repl/zone-menu.js +1 -219
- package/dist/types/index.js +1 -5
- package/dist/utils/crypto.js +1 -85
- package/dist/utils/date.js +1 -52
- package/dist/utils/display.js +1 -72
- package/dist/utils/signature.js +1 -49
- package/package.json +1 -1
package/dist/commands/edgeone.js
CHANGED
|
@@ -1,414 +1 @@
|
|
|
1
|
-
import chalk from "chalk";
|
|
2
|
-
import Table from "cli-table3";
|
|
3
|
-
import { Command } from "commander";
|
|
4
|
-
import inquirer from "inquirer";
|
|
5
|
-
import { EdgeOneClient } from "../api/client.js";
|
|
6
|
-
import { utcToBeijingTime } from "../utils/date.js";
|
|
7
|
-
import { truncateText, getStatusSymbol, getPurgeTypeName } from "../utils/display.js";
|
|
8
|
-
import { DEFAULT_ZONE_ID, TABLE_CHARS } from "../constants/index.js";
|
|
9
|
-
import { readConfig } from "./config.js";
|
|
10
|
-
// ============================================================================
|
|
11
|
-
// 清除缓存命令
|
|
12
|
-
// ============================================================================
|
|
13
|
-
/**
|
|
14
|
-
* 创建清除缓存命令
|
|
15
|
-
*/
|
|
16
|
-
export function createPurgeCommand() {
|
|
17
|
-
const purgeCmd = new Command("purge")
|
|
18
|
-
.description("清除缓存任务")
|
|
19
|
-
.option("-a, --all", "清除全部缓存")
|
|
20
|
-
.option("-d, --dir <path>", "清除指定目录缓存")
|
|
21
|
-
.option("-u, --url <urls...>", "清除指定URL地址(可多个)")
|
|
22
|
-
.option("-z, --zone <zoneId>", "Zone ID(默认: *)")
|
|
23
|
-
.action(async (options) => {
|
|
24
|
-
const { all, dir, url, zone = DEFAULT_ZONE_ID } = options;
|
|
25
|
-
let type = "purge_all";
|
|
26
|
-
let targets = [];
|
|
27
|
-
if (all) {
|
|
28
|
-
type = "purge_all";
|
|
29
|
-
targets = [];
|
|
30
|
-
}
|
|
31
|
-
else if (dir) {
|
|
32
|
-
type = "purge_prefix";
|
|
33
|
-
targets = [dir];
|
|
34
|
-
}
|
|
35
|
-
else if (url && url.length > 0) {
|
|
36
|
-
type = "purge_url";
|
|
37
|
-
targets = url;
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
console.log(chalk.yellow("⚠ 请指定清除模式:\n"));
|
|
41
|
-
console.log(chalk.gray(" 清除全部缓存: edgeone-cli purge --all"));
|
|
42
|
-
console.log(chalk.gray(" 清除目录缓存: edgeone-cli purge --dir /path/to/dir"));
|
|
43
|
-
console.log(chalk.gray(" 清除URL缓存: edgeone-cli purge --url https://example.com/a.png"));
|
|
44
|
-
console.log(chalk.gray(" edgeone-cli purge -u https://a.png https://b.png"));
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
// 从配置文件读取凭证
|
|
48
|
-
const config = readConfig();
|
|
49
|
-
if (!config || !config.secretId || !config.secretKey) {
|
|
50
|
-
console.log(chalk.red('\n❌ 配置不完整,请先运行 "edgeone-cli config init" 初始化配置'));
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
const { secretId, secretKey, endpoint = "teo.tencentcloudapi.com", mode } = config;
|
|
54
|
-
const isDebug = mode === "debug";
|
|
55
|
-
if (isDebug) {
|
|
56
|
-
console.log(chalk.cyan("\n🔄 清除缓存任务\n"));
|
|
57
|
-
if (all) {
|
|
58
|
-
console.log(chalk.gray("清除模式:"), chalk.yellow("全部缓存"));
|
|
59
|
-
}
|
|
60
|
-
else if (dir) {
|
|
61
|
-
console.log(chalk.gray("清除模式:"), chalk.yellow("指定目录"));
|
|
62
|
-
console.log(chalk.gray("目录路径:"), chalk.yellow(dir));
|
|
63
|
-
}
|
|
64
|
-
else if (url && url.length > 0) {
|
|
65
|
-
console.log(chalk.gray("清除模式:"), chalk.yellow("指定URL"));
|
|
66
|
-
console.log(chalk.gray("URL列表:"));
|
|
67
|
-
url.forEach((u) => console.log(` - ${chalk.yellow(u)}`));
|
|
68
|
-
}
|
|
69
|
-
console.log(chalk.gray("\n发送请求...\n"));
|
|
70
|
-
}
|
|
71
|
-
try {
|
|
72
|
-
// 创建客户端并发送请求
|
|
73
|
-
const client = new EdgeOneClient(secretId, secretKey, endpoint, "ap-guangzhou", mode);
|
|
74
|
-
const result = await client.createPurgeTask({
|
|
75
|
-
zoneId: zone,
|
|
76
|
-
type,
|
|
77
|
-
targets,
|
|
78
|
-
});
|
|
79
|
-
// 检查是否有错误
|
|
80
|
-
if ("Error" in result.Response) {
|
|
81
|
-
const error = result.Response.Error;
|
|
82
|
-
console.log(chalk.red("\n❌ 请求失败:"));
|
|
83
|
-
console.log(` 错误码: ${chalk.yellow(error.Code)}`);
|
|
84
|
-
console.log(` 错误信息: ${chalk.yellow(error.Message)}`);
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
console.log(chalk.green("\n✅ 请求成功!"));
|
|
88
|
-
console.log(` RequestId: ${chalk.yellow(result.Response.RequestId)}`);
|
|
89
|
-
if (result.Response.JobId) {
|
|
90
|
-
console.log(` JobId: ${chalk.yellow(result.Response.JobId)}`);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
catch (error) {
|
|
95
|
-
const errMsg = error instanceof Error ? error.message : String(error);
|
|
96
|
-
console.log(chalk.red("\n❌ 请求异常:"));
|
|
97
|
-
console.log(` ${errMsg}`);
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
return purgeCmd;
|
|
101
|
-
}
|
|
102
|
-
// ============================================================================
|
|
103
|
-
// 预热命令
|
|
104
|
-
// ============================================================================
|
|
105
|
-
/**
|
|
106
|
-
* 创建预热命令
|
|
107
|
-
*/
|
|
108
|
-
export function createPrefetchCommand() {
|
|
109
|
-
const prefetchCmd = new Command("prefetch")
|
|
110
|
-
.description("预热任务")
|
|
111
|
-
.argument("[urls...]", "要预热的URL地址列表")
|
|
112
|
-
.option("-z, --zone <zoneId>", "Zone ID(默认: *)")
|
|
113
|
-
.action(async (urls, options) => {
|
|
114
|
-
if (!urls || urls.length === 0) {
|
|
115
|
-
console.log(chalk.yellow("⚠ 请指定要预热的URL:\n"));
|
|
116
|
-
console.log(chalk.gray(" 预热URL: edgeone-cli prefetch https://example.com/a.png --zone <zoneId>"));
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
// 从配置文件读取凭证
|
|
120
|
-
const config = readConfig();
|
|
121
|
-
if (!config || !config.secretId || !config.secretKey) {
|
|
122
|
-
console.log(chalk.red('\n❌ 配置不完整,请先运行 "edgeone-cli config init" 初始化配置'));
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
const { secretId, secretKey, endpoint = "teo.tencentcloudapi.com", mode } = config;
|
|
126
|
-
const zone = options.zone || "*";
|
|
127
|
-
try {
|
|
128
|
-
// 创建客户端并发送请求
|
|
129
|
-
const client = new EdgeOneClient(secretId, secretKey, endpoint, "ap-guangzhou", mode);
|
|
130
|
-
const result = await client.createPrefetchTask({
|
|
131
|
-
zoneId: zone,
|
|
132
|
-
urls,
|
|
133
|
-
});
|
|
134
|
-
// 检查是否有错误
|
|
135
|
-
if ("Error" in result.Response) {
|
|
136
|
-
const error = result.Response.Error;
|
|
137
|
-
console.log(chalk.red("\n❌ 请求失败:"));
|
|
138
|
-
console.log(` 错误码: ${chalk.yellow(error.Code)}`);
|
|
139
|
-
console.log(` 错误信息: ${chalk.yellow(error.Message)}`);
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
console.log(chalk.green("\n✅ 预热任务已提交!"));
|
|
143
|
-
console.log(` RequestId: ${chalk.yellow(result.Response.RequestId)}`);
|
|
144
|
-
if (result.Response.JobId) {
|
|
145
|
-
console.log(` JobId: ${chalk.yellow(result.Response.JobId)}`);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
catch (error) {
|
|
150
|
-
const errMsg = error instanceof Error ? error.message : String(error);
|
|
151
|
-
console.log(chalk.red("\n❌ 请求异常:"));
|
|
152
|
-
console.log(` ${errMsg}`);
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
return prefetchCmd;
|
|
156
|
-
}
|
|
157
|
-
// ============================================================================
|
|
158
|
-
// 历史记录命令
|
|
159
|
-
// ============================================================================
|
|
160
|
-
/**
|
|
161
|
-
* 创建历史记录命令
|
|
162
|
-
*/
|
|
163
|
-
export function createHistoryCommand() {
|
|
164
|
-
const historyCmd = new Command("history").description("查询历史记录").on("--help", () => {
|
|
165
|
-
console.log("");
|
|
166
|
-
console.log("示例:");
|
|
167
|
-
console.log(" $ edgeone-cli history purge # 查询清除缓存历史");
|
|
168
|
-
console.log(" $ edgeone-cli history prefetch # 查询预热任务历史");
|
|
169
|
-
console.log(" $ edgeone-cli history purge --zone zone-123 # 指定 Zone ID 查询清除缓存历史");
|
|
170
|
-
console.log(" $ edgeone-cli history prefetch --zone zone-123 # 指定 Zone ID 查询预热任务历史");
|
|
171
|
-
console.log("");
|
|
172
|
-
});
|
|
173
|
-
// 添加清除缓存历史子命令
|
|
174
|
-
const purgeHistoryCmd = new Command("purge")
|
|
175
|
-
.description("查询清除缓存历史记录")
|
|
176
|
-
.option("-z, --zone <zoneId>", "Zone ID")
|
|
177
|
-
.action(async (options) => {
|
|
178
|
-
const config = readConfig();
|
|
179
|
-
if (!config || !config.secretId || !config.secretKey) {
|
|
180
|
-
console.log(chalk.red('\n❌ 配置不完整,请先运行 "edgeone-cli config init" 初始化配置'));
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
const { secretId, secretKey, endpoint = "teo.tencentcloudapi.com", mode, domainIdList } = config;
|
|
184
|
-
const isDebug = mode === "debug";
|
|
185
|
-
let zoneIds = [];
|
|
186
|
-
// 如果没有传入 zone,从配置中的站点列表选择
|
|
187
|
-
if (!options.zone) {
|
|
188
|
-
if (domainIdList && domainIdList.length > 0) {
|
|
189
|
-
if (domainIdList.length === 1) {
|
|
190
|
-
zoneIds = [domainIdList[0].id];
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
// 多个站点,让用户多选
|
|
194
|
-
const zoneChoices = domainIdList.map(z => ({ name: z.name || z.id, value: z.id }));
|
|
195
|
-
const { zones } = await inquirer.prompt([
|
|
196
|
-
{
|
|
197
|
-
type: "checkbox",
|
|
198
|
-
name: "zones",
|
|
199
|
-
message: "请选择站点 (可多选):",
|
|
200
|
-
choices: zoneChoices,
|
|
201
|
-
validate: (input) => input.length > 0 || "请至少选择一个站点",
|
|
202
|
-
},
|
|
203
|
-
]);
|
|
204
|
-
zoneIds = zones;
|
|
205
|
-
}
|
|
206
|
-
if (isDebug) {
|
|
207
|
-
console.log(chalk.gray(`已选择站点: ${chalk.yellow(zoneIds.join(", "))}`));
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
else {
|
|
211
|
-
console.log(chalk.red("\n❌ 未指定 Zone ID,请使用 --zone 参数指定或在配置中添加站点列表"));
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
else {
|
|
216
|
-
zoneIds = [options.zone];
|
|
217
|
-
}
|
|
218
|
-
await queryPurgeHistory(secretId, secretKey, endpoint, mode, zoneIds, isDebug);
|
|
219
|
-
});
|
|
220
|
-
// 添加预热任务历史子命令
|
|
221
|
-
const prefetchHistoryCmd = new Command("prefetch")
|
|
222
|
-
.description("查询预热任务历史记录")
|
|
223
|
-
.option("-z, --zone <zoneId>", "Zone ID")
|
|
224
|
-
.action(async (options) => {
|
|
225
|
-
const config = readConfig();
|
|
226
|
-
if (!config || !config.secretId || !config.secretKey) {
|
|
227
|
-
console.log(chalk.red('\n❌ 配置不完整,请先运行 "edgeone-cli config init" 初始化配置'));
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
const { secretId, secretKey, endpoint = "teo.tencentcloudapi.com", mode, domainIdList } = config;
|
|
231
|
-
const isDebug = mode === "debug";
|
|
232
|
-
let zoneIds = [];
|
|
233
|
-
// 如果没有传入 zone,从配置中的站点列表选择
|
|
234
|
-
if (!options.zone) {
|
|
235
|
-
if (domainIdList && domainIdList.length > 0) {
|
|
236
|
-
if (domainIdList.length === 1) {
|
|
237
|
-
zoneIds = [domainIdList[0].id];
|
|
238
|
-
}
|
|
239
|
-
else {
|
|
240
|
-
// 多个站点,让用户多选
|
|
241
|
-
const zoneChoices = domainIdList.map(z => ({ name: z.name || z.id, value: z.id }));
|
|
242
|
-
const { zones } = await inquirer.prompt([
|
|
243
|
-
{
|
|
244
|
-
type: "checkbox",
|
|
245
|
-
name: "zones",
|
|
246
|
-
message: "请选择站点 (可多选):",
|
|
247
|
-
choices: zoneChoices,
|
|
248
|
-
validate: (input) => input.length > 0 || "请至少选择一个站点",
|
|
249
|
-
},
|
|
250
|
-
]);
|
|
251
|
-
zoneIds = zones;
|
|
252
|
-
}
|
|
253
|
-
if (isDebug) {
|
|
254
|
-
console.log(chalk.gray(`已选择站点: ${chalk.yellow(zoneIds.join(", "))}`));
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
else {
|
|
258
|
-
console.log(chalk.red("\n❌ 未指定 Zone ID,请使用 --zone 参数指定或在配置中添加站点列表"));
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
else {
|
|
263
|
-
zoneIds = [options.zone];
|
|
264
|
-
}
|
|
265
|
-
await queryPrefetchHistory(secretId, secretKey, endpoint, mode, zoneIds, isDebug);
|
|
266
|
-
});
|
|
267
|
-
// 添加子命令
|
|
268
|
-
historyCmd.addCommand(purgeHistoryCmd);
|
|
269
|
-
historyCmd.addCommand(prefetchHistoryCmd);
|
|
270
|
-
return historyCmd;
|
|
271
|
-
}
|
|
272
|
-
// ============================================================================
|
|
273
|
-
// 辅助函数
|
|
274
|
-
// ============================================================================
|
|
275
|
-
/**
|
|
276
|
-
* 查询清除缓存历史
|
|
277
|
-
*/
|
|
278
|
-
async function queryPurgeHistory(secretId, secretKey, endpoint, mode, zoneIds, isDebug) {
|
|
279
|
-
if (isDebug) {
|
|
280
|
-
console.log(chalk.cyan("\n📋 清除缓存历史记录\n"));
|
|
281
|
-
console.log(chalk.gray("API 参数:"));
|
|
282
|
-
console.log(` Action: ${chalk.green("DescribePurgeTasks")}`);
|
|
283
|
-
console.log(` Version: ${chalk.green("2022-09-01")}`);
|
|
284
|
-
console.log(` ZoneIds: ${chalk.yellow(zoneIds.join(", "))}`);
|
|
285
|
-
}
|
|
286
|
-
try {
|
|
287
|
-
// 创建客户端并发送请求
|
|
288
|
-
const client = new EdgeOneClient(secretId, secretKey, endpoint, "", mode);
|
|
289
|
-
const result = await client.describePurgeTasks(zoneIds);
|
|
290
|
-
if (isDebug) {
|
|
291
|
-
console.log(chalk.cyan("\n响应结果:"));
|
|
292
|
-
console.log(JSON.stringify(result, null, 2));
|
|
293
|
-
}
|
|
294
|
-
// 检查是否有错误
|
|
295
|
-
if ("Error" in result.Response) {
|
|
296
|
-
const error = result.Response.Error;
|
|
297
|
-
console.log(chalk.red("\n❌ 请求失败:"));
|
|
298
|
-
console.log(` 错误码: ${chalk.yellow(error.Code)}`);
|
|
299
|
-
console.log(` 错误信息: ${chalk.yellow(error.Message)}`);
|
|
300
|
-
}
|
|
301
|
-
else {
|
|
302
|
-
console.log(chalk.green("\n✅ 查询成功!"));
|
|
303
|
-
console.log(` RequestId: ${chalk.yellow(result.Response.RequestId)}`);
|
|
304
|
-
// 显示任务列表
|
|
305
|
-
const tasks = result.Response.Tasks || [];
|
|
306
|
-
if (tasks.length > 0) {
|
|
307
|
-
console.log(chalk.cyan("\n📋 清除缓存记录:\n"));
|
|
308
|
-
// 创建表格
|
|
309
|
-
const table = new Table({
|
|
310
|
-
head: [chalk.gray("状态"), chalk.gray("清除地址"), chalk.gray("时间"), chalk.gray("类型")],
|
|
311
|
-
colWidths: [8, 50, 30, 8],
|
|
312
|
-
chars: TABLE_CHARS,
|
|
313
|
-
});
|
|
314
|
-
// 任务行
|
|
315
|
-
tasks.forEach(task => {
|
|
316
|
-
const status = task.Status === "success" ? chalk.green("✓") : chalk.red("✗");
|
|
317
|
-
const target = task.Target || "all";
|
|
318
|
-
const type = getPurgeTypeName(task.Type);
|
|
319
|
-
const createTime = utcToBeijingTime(task.CreateTime);
|
|
320
|
-
// 截断过长的目标地址
|
|
321
|
-
const displayTarget = truncateText(target, 47);
|
|
322
|
-
table.push([status, chalk.yellow(displayTarget), chalk.gray(createTime), type]);
|
|
323
|
-
});
|
|
324
|
-
console.log(table.toString());
|
|
325
|
-
console.log(` 总计: ${chalk.yellow(result.Response.TotalCount || tasks.length)} 条记录`);
|
|
326
|
-
const successCount = tasks.filter(task => task.Status === "success").length;
|
|
327
|
-
console.log(` 成功: ${chalk.green(successCount)} 条记录`);
|
|
328
|
-
const failedCount = tasks.filter(task => task.Status === "failed").length;
|
|
329
|
-
console.log(` 失败: ${chalk.red(failedCount)} 条记录`);
|
|
330
|
-
}
|
|
331
|
-
else {
|
|
332
|
-
console.log(chalk.gray("\n 暂无清除记录\n"));
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
catch (error) {
|
|
337
|
-
const errMsg = error instanceof Error ? error.message : String(error);
|
|
338
|
-
console.log(chalk.red("\n❌ 请求异常:"));
|
|
339
|
-
console.log(` ${errMsg}`);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
/**
|
|
343
|
-
* 查询预热任务历史
|
|
344
|
-
*/
|
|
345
|
-
async function queryPrefetchHistory(secretId, secretKey, endpoint, mode, zoneIds, isDebug) {
|
|
346
|
-
if (isDebug) {
|
|
347
|
-
console.log(chalk.cyan("\n📋 预热任务历史记录\n"));
|
|
348
|
-
console.log(chalk.gray("API 参数:"));
|
|
349
|
-
console.log(` Action: ${chalk.green("DescribePrefetchTasks")}`);
|
|
350
|
-
console.log(` Version: ${chalk.green("2022-09-01")}`);
|
|
351
|
-
console.log(` ZoneIds: ${chalk.yellow(zoneIds.join(", "))}`);
|
|
352
|
-
}
|
|
353
|
-
try {
|
|
354
|
-
// 创建客户端并发送请求
|
|
355
|
-
const client = new EdgeOneClient(secretId, secretKey, endpoint, "", mode);
|
|
356
|
-
const result = await client.describePrefetchTasks(zoneIds);
|
|
357
|
-
if (isDebug) {
|
|
358
|
-
console.log(chalk.cyan("\n响应结果:"));
|
|
359
|
-
console.log(JSON.stringify(result, null, 2));
|
|
360
|
-
}
|
|
361
|
-
// 检查是否有错误
|
|
362
|
-
if ("Error" in result.Response) {
|
|
363
|
-
const error = result.Response.Error;
|
|
364
|
-
console.log(chalk.red("\n❌ 请求失败:"));
|
|
365
|
-
console.log(` 错误码: ${chalk.yellow(error.Code)}`);
|
|
366
|
-
console.log(` 错误信息: ${chalk.yellow(error.Message)}`);
|
|
367
|
-
}
|
|
368
|
-
else {
|
|
369
|
-
console.log(chalk.green("\n✅ 查询成功!"));
|
|
370
|
-
console.log(` RequestId: ${chalk.yellow(result.Response.RequestId)}`);
|
|
371
|
-
// 显示任务列表
|
|
372
|
-
const tasks = result.Response.PrefetchTasks || [];
|
|
373
|
-
if (tasks.length > 0) {
|
|
374
|
-
console.log(chalk.cyan("\n📋 预热任务记录:\n"));
|
|
375
|
-
// 创建表格
|
|
376
|
-
const table = new Table({
|
|
377
|
-
head: [chalk.gray("状态"), chalk.gray("预热地址"), chalk.gray("时间")],
|
|
378
|
-
colWidths: [8, 60, 30],
|
|
379
|
-
chars: TABLE_CHARS,
|
|
380
|
-
});
|
|
381
|
-
// 任务行
|
|
382
|
-
tasks.forEach(task => {
|
|
383
|
-
const statusSymbol = getStatusSymbol(task.Status);
|
|
384
|
-
const status = task.Status === "success"
|
|
385
|
-
? chalk.green(statusSymbol)
|
|
386
|
-
: task.Status === "processing"
|
|
387
|
-
? chalk.yellow(statusSymbol)
|
|
388
|
-
: chalk.red(statusSymbol);
|
|
389
|
-
const target = task.Target || "unknown";
|
|
390
|
-
const createTime = utcToBeijingTime(task.CreateTime);
|
|
391
|
-
// 截断过长的目标地址
|
|
392
|
-
const displayTarget = truncateText(target, 57);
|
|
393
|
-
table.push([status, chalk.yellow(displayTarget), chalk.gray(createTime)]);
|
|
394
|
-
});
|
|
395
|
-
console.log(table.toString());
|
|
396
|
-
console.log(` 总计: ${chalk.yellow(result.Response.TotalCount || tasks.length)} 条记录`);
|
|
397
|
-
const successCount = tasks.filter(task => task.Status === "success").length;
|
|
398
|
-
console.log(` 成功: ${chalk.green(successCount)} 条记录`);
|
|
399
|
-
const processingCount = tasks.filter(task => task.Status === "processing").length;
|
|
400
|
-
console.log(` 处理中: ${chalk.yellow(processingCount)} 条记录`);
|
|
401
|
-
const failedCount = tasks.filter(task => task.Status === "failed").length;
|
|
402
|
-
console.log(` 失败: ${chalk.red(failedCount)} 条记录`);
|
|
403
|
-
}
|
|
404
|
-
else {
|
|
405
|
-
console.log(chalk.gray("\n 暂无预热记录\n"));
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
catch (error) {
|
|
410
|
-
const errMsg = error instanceof Error ? error.message : String(error);
|
|
411
|
-
console.log(chalk.red("\n❌ 请求异常:"));
|
|
412
|
-
console.log(` ${errMsg}`);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
1
|
+
import chalk from"chalk";import Table from"cli-table3";import{Command}from"commander";import inquirer from"inquirer";import{EdgeOneClient}from"../api/client.js";import{utcToBeijingTime}from"../utils/date.js";import{truncateText,getStatusSymbol,getPurgeTypeName}from"../utils/display.js";import{DEFAULT_ZONE_ID,TABLE_CHARS}from"../constants/index.js";import{readConfig}from"./config.js";export function createPurgeCommand(){return new Command("purge").description("清除缓存任务").option("-a, --all","清除全部缓存").option("-d, --dir <path>","清除指定目录缓存").option("-u, --url <urls...>","清除指定URL地址(可多个)").option("-z, --zone <zoneId>","Zone ID(默认: *)").action(async options=>{const{all,dir,url,zone=DEFAULT_ZONE_ID}=options;let type="purge_all",targets=[];if(all)type="purge_all",targets=[];else if(dir)type="purge_prefix",targets=[dir];else{if(!(url&&url.length>0))return console.log(chalk.yellow("⚠ 请指定清除模式:\n")),console.log(chalk.gray(" 清除全部缓存: edgeone-cli purge --all")),console.log(chalk.gray(" 清除目录缓存: edgeone-cli purge --dir /path/to/dir")),console.log(chalk.gray(" 清除URL缓存: edgeone-cli purge --url https://example.com/a.png")),void console.log(chalk.gray(" edgeone-cli purge -u https://a.png https://b.png"));type="purge_url",targets=url}const config=readConfig();if(!config||!config.secretId||!config.secretKey)return void console.log(chalk.red('\n❌ 配置不完整,请先运行 "edgeone-cli config init" 初始化配置'));const{secretId,secretKey,endpoint="teo.tencentcloudapi.com",mode}=config;"debug"===mode&&(console.log(chalk.cyan("\n🔄 清除缓存任务\n")),all?console.log(chalk.gray("清除模式:"),chalk.yellow("全部缓存")):dir?(console.log(chalk.gray("清除模式:"),chalk.yellow("指定目录")),console.log(chalk.gray("目录路径:"),chalk.yellow(dir))):url&&url.length>0&&(console.log(chalk.gray("清除模式:"),chalk.yellow("指定URL")),console.log(chalk.gray("URL列表:")),url.forEach(u=>console.log(` - ${chalk.yellow(u)}`))),console.log(chalk.gray("\n发送请求...\n")));try{const client=new EdgeOneClient(secretId,secretKey,endpoint,"ap-guangzhou",mode),result=await client.createPurgeTask({zoneId:zone,type,targets});if("Error"in result.Response){const error=result.Response.Error;console.log(chalk.red("\n❌ 请求失败:")),console.log(` 错误码: ${chalk.yellow(error.Code)}`),console.log(` 错误信息: ${chalk.yellow(error.Message)}`)}else console.log(chalk.green("\n✅ 请求成功!")),console.log(` RequestId: ${chalk.yellow(result.Response.RequestId)}`),result.Response.JobId&&console.log(` JobId: ${chalk.yellow(result.Response.JobId)}`)}catch(error){const errMsg=error instanceof Error?error.message:String(error);console.log(chalk.red("\n❌ 请求异常:")),console.log(` ${errMsg}`)}})}export function createPrefetchCommand(){return new Command("prefetch").description("预热任务").argument("[urls...]","要预热的URL地址列表").option("-z, --zone <zoneId>","Zone ID(默认: *)").action(async(urls,options)=>{if(!urls||0===urls.length)return console.log(chalk.yellow("⚠ 请指定要预热的URL:\n")),void console.log(chalk.gray(" 预热URL: edgeone-cli prefetch https://example.com/a.png --zone <zoneId>"));const config=readConfig();if(!config||!config.secretId||!config.secretKey)return void console.log(chalk.red('\n❌ 配置不完整,请先运行 "edgeone-cli config init" 初始化配置'));const{secretId,secretKey,endpoint="teo.tencentcloudapi.com",mode}=config,zone=options.zone||"*";try{const client=new EdgeOneClient(secretId,secretKey,endpoint,"ap-guangzhou",mode),result=await client.createPrefetchTask({zoneId:zone,urls});if("Error"in result.Response){const error=result.Response.Error;console.log(chalk.red("\n❌ 请求失败:")),console.log(` 错误码: ${chalk.yellow(error.Code)}`),console.log(` 错误信息: ${chalk.yellow(error.Message)}`)}else console.log(chalk.green("\n✅ 预热任务已提交!")),console.log(` RequestId: ${chalk.yellow(result.Response.RequestId)}`),result.Response.JobId&&console.log(` JobId: ${chalk.yellow(result.Response.JobId)}`)}catch(error){const errMsg=error instanceof Error?error.message:String(error);console.log(chalk.red("\n❌ 请求异常:")),console.log(` ${errMsg}`)}})}export function createHistoryCommand(){const historyCmd=new Command("history").description("查询历史记录").on("--help",()=>{console.log(""),console.log("示例:"),console.log(" $ edgeone-cli history purge # 查询清除缓存历史"),console.log(" $ edgeone-cli history prefetch # 查询预热任务历史"),console.log(" $ edgeone-cli history purge --zone zone-123 # 指定 Zone ID 查询清除缓存历史"),console.log(" $ edgeone-cli history prefetch --zone zone-123 # 指定 Zone ID 查询预热任务历史"),console.log("")}),purgeHistoryCmd=new Command("purge").description("查询清除缓存历史记录").option("-z, --zone <zoneId>","Zone ID").action(async options=>{const config=readConfig();if(!config||!config.secretId||!config.secretKey)return void console.log(chalk.red('\n❌ 配置不完整,请先运行 "edgeone-cli config init" 初始化配置'));const{secretId,secretKey,endpoint="teo.tencentcloudapi.com",mode,domainIdList}=config,isDebug="debug"===mode;let zoneIds=[];if(options.zone)zoneIds=[options.zone];else{if(!(domainIdList&&domainIdList.length>0))return void console.log(chalk.red("\n❌ 未指定 Zone ID,请使用 --zone 参数指定或在配置中添加站点列表"));if(1===domainIdList.length)zoneIds=[domainIdList[0].id];else{const zoneChoices=domainIdList.map(z=>({name:z.name||z.id,value:z.id})),{zones}=await inquirer.prompt([{type:"checkbox",name:"zones",message:"请选择站点 (可多选):",choices:zoneChoices,validate:input=>input.length>0||"请至少选择一个站点"}]);zoneIds=zones}isDebug&&console.log(chalk.gray(`已选择站点: ${chalk.yellow(zoneIds.join(", "))}`))}await async function(secretId,secretKey,endpoint,mode,zoneIds,isDebug){isDebug&&(console.log(chalk.cyan("\n📋 清除缓存历史记录\n")),console.log(chalk.gray("API 参数:")),console.log(` Action: ${chalk.green("DescribePurgeTasks")}`),console.log(` Version: ${chalk.green("2022-09-01")}`),console.log(` ZoneIds: ${chalk.yellow(zoneIds.join(", "))}`));try{const client=new EdgeOneClient(secretId,secretKey,endpoint,"",mode),result=await client.describePurgeTasks(zoneIds);if(isDebug&&(console.log(chalk.cyan("\n响应结果:")),console.log(JSON.stringify(result,null,2))),"Error"in result.Response){const error=result.Response.Error;console.log(chalk.red("\n❌ 请求失败:")),console.log(` 错误码: ${chalk.yellow(error.Code)}`),console.log(` 错误信息: ${chalk.yellow(error.Message)}`)}else{console.log(chalk.green("\n✅ 查询成功!")),console.log(` RequestId: ${chalk.yellow(result.Response.RequestId)}`);const tasks=result.Response.Tasks||[];if(tasks.length>0){console.log(chalk.cyan("\n📋 清除缓存记录:\n"));const table=new Table({head:[chalk.gray("状态"),chalk.gray("清除地址"),chalk.gray("时间"),chalk.gray("类型")],colWidths:[8,50,30,8],chars:TABLE_CHARS});tasks.forEach(task=>{const status="success"===task.Status?chalk.green("✓"):chalk.red("✗"),target=task.Target||"all",type=getPurgeTypeName(task.Type),createTime=utcToBeijingTime(task.CreateTime),displayTarget=truncateText(target,47);table.push([status,chalk.yellow(displayTarget),chalk.gray(createTime),type])}),console.log(table.toString()),console.log(` 总计: ${chalk.yellow(result.Response.TotalCount||tasks.length)} 条记录`);const successCount=tasks.filter(task=>"success"===task.Status).length;console.log(` 成功: ${chalk.green(successCount)} 条记录`);const failedCount=tasks.filter(task=>"failed"===task.Status).length;console.log(` 失败: ${chalk.red(failedCount)} 条记录`)}else console.log(chalk.gray("\n 暂无清除记录\n"))}}catch(error){const errMsg=error instanceof Error?error.message:String(error);console.log(chalk.red("\n❌ 请求异常:")),console.log(` ${errMsg}`)}}(secretId,secretKey,endpoint,mode,zoneIds,isDebug)}),prefetchHistoryCmd=new Command("prefetch").description("查询预热任务历史记录").option("-z, --zone <zoneId>","Zone ID").action(async options=>{const config=readConfig();if(!config||!config.secretId||!config.secretKey)return void console.log(chalk.red('\n❌ 配置不完整,请先运行 "edgeone-cli config init" 初始化配置'));const{secretId,secretKey,endpoint="teo.tencentcloudapi.com",mode,domainIdList}=config,isDebug="debug"===mode;let zoneIds=[];if(options.zone)zoneIds=[options.zone];else{if(!(domainIdList&&domainIdList.length>0))return void console.log(chalk.red("\n❌ 未指定 Zone ID,请使用 --zone 参数指定或在配置中添加站点列表"));if(1===domainIdList.length)zoneIds=[domainIdList[0].id];else{const zoneChoices=domainIdList.map(z=>({name:z.name||z.id,value:z.id})),{zones}=await inquirer.prompt([{type:"checkbox",name:"zones",message:"请选择站点 (可多选):",choices:zoneChoices,validate:input=>input.length>0||"请至少选择一个站点"}]);zoneIds=zones}isDebug&&console.log(chalk.gray(`已选择站点: ${chalk.yellow(zoneIds.join(", "))}`))}await async function(secretId,secretKey,endpoint,mode,zoneIds,isDebug){isDebug&&(console.log(chalk.cyan("\n📋 预热任务历史记录\n")),console.log(chalk.gray("API 参数:")),console.log(` Action: ${chalk.green("DescribePrefetchTasks")}`),console.log(` Version: ${chalk.green("2022-09-01")}`),console.log(` ZoneIds: ${chalk.yellow(zoneIds.join(", "))}`));try{const client=new EdgeOneClient(secretId,secretKey,endpoint,"",mode),result=await client.describePrefetchTasks(zoneIds);if(isDebug&&(console.log(chalk.cyan("\n响应结果:")),console.log(JSON.stringify(result,null,2))),"Error"in result.Response){const error=result.Response.Error;console.log(chalk.red("\n❌ 请求失败:")),console.log(` 错误码: ${chalk.yellow(error.Code)}`),console.log(` 错误信息: ${chalk.yellow(error.Message)}`)}else{console.log(chalk.green("\n✅ 查询成功!")),console.log(` RequestId: ${chalk.yellow(result.Response.RequestId)}`);const tasks=result.Response.PrefetchTasks||[];if(tasks.length>0){console.log(chalk.cyan("\n📋 预热任务记录:\n"));const table=new Table({head:[chalk.gray("状态"),chalk.gray("预热地址"),chalk.gray("时间")],colWidths:[8,60,30],chars:TABLE_CHARS});tasks.forEach(task=>{const statusSymbol=getStatusSymbol(task.Status),status="success"===task.Status?chalk.green(statusSymbol):"processing"===task.Status?chalk.yellow(statusSymbol):chalk.red(statusSymbol),target=task.Target||"unknown",createTime=utcToBeijingTime(task.CreateTime),displayTarget=truncateText(target,57);table.push([status,chalk.yellow(displayTarget),chalk.gray(createTime)])}),console.log(table.toString()),console.log(` 总计: ${chalk.yellow(result.Response.TotalCount||tasks.length)} 条记录`);const successCount=tasks.filter(task=>"success"===task.Status).length;console.log(` 成功: ${chalk.green(successCount)} 条记录`);const processingCount=tasks.filter(task=>"processing"===task.Status).length;console.log(` 处理中: ${chalk.yellow(processingCount)} 条记录`);const failedCount=tasks.filter(task=>"failed"===task.Status).length;console.log(` 失败: ${chalk.red(failedCount)} 条记录`)}else console.log(chalk.gray("\n 暂无预热记录\n"))}}catch(error){const errMsg=error instanceof Error?error.message:String(error);console.log(chalk.red("\n❌ 请求异常:")),console.log(` ${errMsg}`)}}(secretId,secretKey,endpoint,mode,zoneIds,isDebug)});return historyCmd.addCommand(purgeHistoryCmd),historyCmd.addCommand(prefetchHistoryCmd),historyCmd}
|
package/dist/constants/index.js
CHANGED
|
@@ -1,60 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* 常量配置
|
|
3
|
-
*/
|
|
4
|
-
// ============================================================================
|
|
5
|
-
// API 常量
|
|
6
|
-
// ============================================================================
|
|
7
|
-
export const API_ACTION = {
|
|
8
|
-
CREATE_PURGE_TASK: "CreatePurgeTask",
|
|
9
|
-
DESCRIBE_PURGE_TASKS: "DescribePurgeTasks",
|
|
10
|
-
CREATE_PREFETCH_TASK: "CreatePrefetchTask",
|
|
11
|
-
DESCRIBE_PREFETCH_TASKS: "DescribePrefetchTasks",
|
|
12
|
-
MODIFY_ZONE_STATUS: "ModifyZoneStatus",
|
|
13
|
-
DESCRIBE_ZONES: "DescribeZones",
|
|
14
|
-
DESCRIBE_HOST_SETTINGS: "DescribeHostSettings",
|
|
15
|
-
};
|
|
16
|
-
export const API_VERSION = {
|
|
17
|
-
V2022_09_01: "2022-09-01",
|
|
18
|
-
V2022_01_06: "2022-01-06",
|
|
19
|
-
V2024_06_04: "2024-06-04",
|
|
20
|
-
};
|
|
21
|
-
export const DEFAULT_ENDPOINT = "teo.tencentcloudapi.com";
|
|
22
|
-
export const DEFAULT_REGION = "ap-guangzhou";
|
|
23
|
-
export const DEFAULT_ZONE_ID = "*";
|
|
24
|
-
export const DEFAULT_METHOD = "delete";
|
|
25
|
-
// ============================================================================
|
|
26
|
-
// 显示常量
|
|
27
|
-
// ============================================================================
|
|
28
|
-
export const TABLE_CHARS = {
|
|
29
|
-
mid: "",
|
|
30
|
-
"left-mid": "",
|
|
31
|
-
"mid-mid": "",
|
|
32
|
-
"right-mid": "",
|
|
33
|
-
};
|
|
34
|
-
export const SEPARATOR_LINE = "─────────────────";
|
|
35
|
-
// ============================================================================
|
|
36
|
-
// 时间常量
|
|
37
|
-
// ============================================================================
|
|
38
|
-
export const TIME_RANGES = {
|
|
39
|
-
ONE_WEEK_MS: 7 * 24 * 60 * 60 * 1000,
|
|
40
|
-
ONE_MONTH_MS: 30 * 24 * 60 * 60 * 1000,
|
|
41
|
-
};
|
|
42
|
-
// ============================================================================
|
|
43
|
-
// 任务状态映射
|
|
44
|
-
// ============================================================================
|
|
45
|
-
export const PURGE_TYPE_LABELS = {
|
|
46
|
-
purge_url: "URL",
|
|
47
|
-
purge_prefix: "目录",
|
|
48
|
-
purge_all: "全部",
|
|
49
|
-
};
|
|
50
|
-
export const TASK_STATUS_LABELS = {
|
|
51
|
-
success: "成功",
|
|
52
|
-
failed: "失败",
|
|
53
|
-
processing: "处理中",
|
|
54
|
-
pending: "等待中",
|
|
55
|
-
};
|
|
56
|
-
export const AREA_LABELS = {
|
|
57
|
-
global: "全球加速",
|
|
58
|
-
mainland: "中国大陆",
|
|
59
|
-
overseas: "境外",
|
|
60
|
-
};
|
|
1
|
+
export const API_ACTION={CREATE_PURGE_TASK:"CreatePurgeTask",DESCRIBE_PURGE_TASKS:"DescribePurgeTasks",CREATE_PREFETCH_TASK:"CreatePrefetchTask",DESCRIBE_PREFETCH_TASKS:"DescribePrefetchTasks",MODIFY_ZONE_STATUS:"ModifyZoneStatus",DESCRIBE_ZONES:"DescribeZones",DESCRIBE_HOST_SETTINGS:"DescribeHostSettings"};export const API_VERSION={V2022_09_01:"2022-09-01",V2022_01_06:"2022-01-06",V2024_06_04:"2024-06-04"};export const DEFAULT_ENDPOINT="teo.tencentcloudapi.com";export const DEFAULT_REGION="ap-guangzhou";export const DEFAULT_ZONE_ID="*";export const DEFAULT_METHOD="delete";export const TABLE_CHARS={mid:"","left-mid":"","mid-mid":"","right-mid":""};export const SEPARATOR_LINE="─────────────────";export const TIME_RANGES={ONE_WEEK_MS:6048e5,ONE_MONTH_MS:2592e6};export const PURGE_TYPE_LABELS={purge_url:"URL",purge_prefix:"目录",purge_all:"全部"};export const TASK_STATUS_LABELS={success:"成功",failed:"失败",processing:"处理中",pending:"等待中"};export const AREA_LABELS={global:"全球加速",mainland:"中国大陆",overseas:"境外"};
|
package/dist/index.js
CHANGED
|
@@ -1,38 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import chalk from "chalk";
|
|
3
|
-
import { program } from "commander";
|
|
4
|
-
import configCmd from "./commands/config.js";
|
|
5
|
-
import { createHistoryCommand, createPrefetchCommand, createPurgeCommand } from "./commands/edgeone.js";
|
|
6
|
-
import { startInteractive } from "./repl/index.js";
|
|
7
|
-
import packageJson from "../package.json" with { type: "json" };
|
|
8
|
-
// CLI 版本
|
|
9
|
-
const version = packageJson.version;
|
|
10
|
-
// 程序信息
|
|
11
|
-
program
|
|
12
|
-
.name("edgeone-cli")
|
|
13
|
-
.description("EdgeOne CLI - 本地化 EdgeOne 服务管理工具")
|
|
14
|
-
.version(version, "-v, --version", "显示版本号")
|
|
15
|
-
.option("-i, --interactive", "进入交互模式");
|
|
16
|
-
// 欢迎信息
|
|
17
|
-
program.addHelpText("beforeAll", `
|
|
18
|
-
${chalk.cyan.bold("╔═══════════════════════════════════╗")}
|
|
19
|
-
${chalk.cyan.bold("║")} ${chalk.white.bold("EdgeOne CLI")} ${chalk.cyan.bold(" ║")}
|
|
20
|
-
${chalk.cyan.bold("║")} ${chalk.gray("本地化 EdgeOne 服务管理工具")} ${chalk.cyan.bold("║")}
|
|
21
|
-
${chalk.cyan.bold("╚═══════════════════════════════════╝")}
|
|
22
|
-
`);
|
|
23
|
-
// 注册命令
|
|
24
|
-
program.addCommand(configCmd);
|
|
25
|
-
program.addCommand(createPurgeCommand());
|
|
26
|
-
program.addCommand(createPrefetchCommand());
|
|
27
|
-
program.addCommand(createHistoryCommand());
|
|
28
|
-
// 检查是否需要进入交互模式(在解析之前)
|
|
29
|
-
const args = process.argv.slice(2);
|
|
30
|
-
const hasInteractiveFlag = args.includes('-i') || args.includes('--interactive');
|
|
31
|
-
if (hasInteractiveFlag) {
|
|
32
|
-
// 进入交互模式
|
|
33
|
-
startInteractive();
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
// 正常解析命令
|
|
37
|
-
program.parse();
|
|
38
|
-
}
|
|
2
|
+
import chalk from"chalk";import{program}from"commander";import configCmd from"./commands/config.js";import{createHistoryCommand,createPrefetchCommand,createPurgeCommand}from"./commands/edgeone.js";import{startInteractive}from"./repl/index.js";import packageJson from"../package.json"with{type:"json"};const version=packageJson.version;program.name("edgeone-cli").description("EdgeOne CLI - 本地化 EdgeOne 服务管理工具").version(version,"-v, --version","显示版本号").option("-i, --interactive","进入交互模式"),program.addHelpText("beforeAll",`\n${chalk.cyan.bold("╔═══════════════════════════════════╗")}\n${chalk.cyan.bold("║")} ${chalk.white.bold("EdgeOne CLI")} ${chalk.cyan.bold(" ║")}\n${chalk.cyan.bold("║")} ${chalk.gray("本地化 EdgeOne 服务管理工具")} ${chalk.cyan.bold("║")}\n${chalk.cyan.bold("╚═══════════════════════════════════╝")}\n`),program.addCommand(configCmd),program.addCommand(createPurgeCommand()),program.addCommand(createPrefetchCommand()),program.addCommand(createHistoryCommand());const args=process.argv.slice(2);args.includes("-i")||args.includes("--interactive")?startInteractive():program.parse();
|