edgeone-cli 1.0.11 → 1.0.13

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 (51) hide show
  1. package/dist/api/client.d.ts +46 -0
  2. package/dist/api/client.d.ts.map +1 -0
  3. package/dist/api/client.js +210 -1
  4. package/dist/api/signer.js +1 -1
  5. package/dist/commands/config.d.ts +19 -0
  6. package/dist/commands/config.d.ts.map +1 -0
  7. package/dist/commands/config.js +312 -1
  8. package/dist/commands/edgeone.d.ts +14 -0
  9. package/dist/commands/edgeone.d.ts.map +1 -0
  10. package/dist/commands/edgeone.js +414 -1
  11. package/dist/constants/index.d.ts +36 -0
  12. package/dist/constants/index.d.ts.map +1 -0
  13. package/dist/constants/index.js +60 -0
  14. package/dist/index.d.ts +3 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +37 -1
  17. package/dist/repl/config-menu.d.ts +12 -0
  18. package/dist/repl/config-menu.d.ts.map +1 -0
  19. package/dist/repl/config-menu.js +264 -0
  20. package/dist/repl/index.d.ts +8 -0
  21. package/dist/repl/index.d.ts.map +1 -0
  22. package/dist/repl/index.js +95 -0
  23. package/dist/repl/prefetch-menu.d.ts +15 -0
  24. package/dist/repl/prefetch-menu.d.ts.map +1 -0
  25. package/dist/repl/prefetch-menu.js +192 -0
  26. package/dist/repl/purge-menu.d.ts +15 -0
  27. package/dist/repl/purge-menu.d.ts.map +1 -0
  28. package/dist/repl/purge-menu.js +228 -0
  29. package/dist/repl/ui.d.ts +16 -0
  30. package/dist/repl/ui.d.ts.map +1 -0
  31. package/dist/repl/ui.js +29 -0
  32. package/dist/repl/zone-menu.d.ts +15 -0
  33. package/dist/repl/zone-menu.d.ts.map +1 -0
  34. package/dist/repl/zone-menu.js +219 -0
  35. package/dist/repl.js +1 -1
  36. package/dist/types/index.d.ts +241 -0
  37. package/dist/types/index.d.ts.map +1 -0
  38. package/dist/types/index.js +5 -0
  39. package/dist/utils/crypto.d.ts +13 -0
  40. package/dist/utils/crypto.d.ts.map +1 -0
  41. package/dist/utils/crypto.js +85 -1
  42. package/dist/utils/date.d.ts +26 -0
  43. package/dist/utils/date.d.ts.map +1 -0
  44. package/dist/utils/date.js +52 -0
  45. package/dist/utils/display.d.ts +38 -0
  46. package/dist/utils/display.d.ts.map +1 -0
  47. package/dist/utils/display.js +72 -0
  48. package/dist/utils/signature.d.ts +6 -0
  49. package/dist/utils/signature.d.ts.map +1 -0
  50. package/dist/utils/signature.js +49 -1
  51. package/package.json +1 -1
@@ -0,0 +1,241 @@
1
+ /**
2
+ * 统一类型定义
3
+ * 所有接口和类型定义集中管理,业务逻辑文件专注于功能实现
4
+ */
5
+ /**
6
+ * 运行模式
7
+ */
8
+ export type ConfigMode = "debug" | "production";
9
+ /**
10
+ * 站点配置
11
+ */
12
+ export interface ZoneConfig {
13
+ id: string;
14
+ name?: string;
15
+ }
16
+ /**
17
+ * 存储的配置(内部使用,包含加密标识)
18
+ */
19
+ export interface StoredConfig {
20
+ secretId: string;
21
+ secretKey: string;
22
+ endpoint: string;
23
+ mode?: ConfigMode;
24
+ domainIdList?: string[] | ZoneConfig[];
25
+ encrypted?: boolean;
26
+ }
27
+ /**
28
+ * 配置对象
29
+ */
30
+ export interface Config {
31
+ secretId: string;
32
+ secretKey: string;
33
+ endpoint: string;
34
+ mode: ConfigMode;
35
+ domainIdList: ZoneConfig[];
36
+ }
37
+ /**
38
+ * 签名计算选项
39
+ */
40
+ export interface SignatureOptions {
41
+ secretId: string;
42
+ secretKey: string;
43
+ endpoint: string;
44
+ action: string;
45
+ requestBody: string;
46
+ timestamp: string;
47
+ }
48
+ /**
49
+ * 创建清除缓存任务选项
50
+ */
51
+ export interface CreatePurgeTaskOptions {
52
+ zoneId?: string;
53
+ type: PurgeType;
54
+ targets?: string[];
55
+ url?: string;
56
+ }
57
+ /**
58
+ * 创建预热任务选项
59
+ */
60
+ export interface CreatePrefetchTaskOptions {
61
+ zoneId?: string;
62
+ urls: string[];
63
+ }
64
+ /**
65
+ * 修改站点状态选项
66
+ */
67
+ export interface ModifyZoneStatusOptions {
68
+ zoneId: string;
69
+ paused: boolean;
70
+ }
71
+ /**
72
+ * 查询站点状态选项
73
+ */
74
+ export interface DescribeZoneStatusOptions {
75
+ zoneId: string;
76
+ }
77
+ /**
78
+ * 查询站点域名列表选项
79
+ */
80
+ export interface DescribeHostSettingsOptions {
81
+ zoneId: string;
82
+ }
83
+ /**
84
+ * API 错误信息
85
+ */
86
+ export interface ApiError {
87
+ Code: string;
88
+ Message: string;
89
+ }
90
+ /**
91
+ * 带错误的响应
92
+ */
93
+ export interface ResponseWithError {
94
+ Error: ApiError;
95
+ }
96
+ /**
97
+ * 基础 API 响应
98
+ */
99
+ export interface ApiResponse<T = unknown> {
100
+ Response: T;
101
+ }
102
+ /**
103
+ * API 错误响应
104
+ */
105
+ export interface ApiErrorResponse {
106
+ Response: {
107
+ Error: ApiError;
108
+ };
109
+ }
110
+ /**
111
+ * 基础响应
112
+ */
113
+ export interface BaseResponse {
114
+ RequestId: string;
115
+ }
116
+ /**
117
+ * 创建清除缓存任务响应
118
+ */
119
+ export interface CreatePurgeTaskResponse extends BaseResponse {
120
+ JobId?: string;
121
+ }
122
+ /**
123
+ * 创建清除缓存任务结果
124
+ */
125
+ export interface CreatePurgeTaskResult {
126
+ Response: CreatePurgeTaskResponse;
127
+ }
128
+ /**
129
+ * 任务信息
130
+ */
131
+ export interface Task {
132
+ JobId: string;
133
+ Status: TaskStatus;
134
+ Target: string;
135
+ Type: PurgeType;
136
+ CreateTime: string;
137
+ UpdateTime?: string;
138
+ }
139
+ /**
140
+ * 查询清除缓存任务响应
141
+ */
142
+ export interface DescribePurgeTasksResponse extends BaseResponse {
143
+ Tasks?: Task[];
144
+ TotalCount?: number;
145
+ }
146
+ /**
147
+ * 查询预热任务响应
148
+ */
149
+ export interface DescribePrefetchTasksResponse extends BaseResponse {
150
+ PrefetchTasks?: Task[];
151
+ TotalCount?: number;
152
+ }
153
+ /**
154
+ * 站点信息
155
+ */
156
+ export interface ZoneInfo {
157
+ ZoneId: string;
158
+ ZoneName: string;
159
+ Paused: boolean;
160
+ Area: "global" | "mainland" | "overseas";
161
+ NameServers?: string[];
162
+ NSDetail?: Record<string, unknown>;
163
+ CNAMEDetail?: Record<string, unknown>;
164
+ DNSPodDetail?: Record<string, unknown>;
165
+ }
166
+ /**
167
+ * 查询站点响应
168
+ */
169
+ export interface DescribeZonesResponse extends BaseResponse {
170
+ Zones?: ZoneInfo[];
171
+ TotalCount?: number;
172
+ }
173
+ /**
174
+ * 清除类型
175
+ */
176
+ export type PurgeType = "purge_url" | "purge_prefix" | "purge_all";
177
+ /**
178
+ * 任务状态
179
+ */
180
+ export type TaskStatus = "success" | "failed" | "processing" | "pending";
181
+ /**
182
+ * API 结果(成功或错误)
183
+ */
184
+ export type ApiResult<T> = ApiResponse<T> | ApiErrorResponse;
185
+ /**
186
+ * CLI 表格配置
187
+ */
188
+ export interface TableConfig {
189
+ head: string[];
190
+ colWidths: number[];
191
+ }
192
+ /**
193
+ * 交互式菜单通用答案
194
+ */
195
+ export interface PromptAnswer {
196
+ action?: string;
197
+ zone?: string;
198
+ type?: string;
199
+ paused?: boolean | string;
200
+ }
201
+ /**
202
+ * 配置答案
203
+ */
204
+ export interface ConfigAnswer {
205
+ secretId: string;
206
+ secretKey: string;
207
+ endpoint: string;
208
+ mode: ConfigMode;
209
+ domainIdList: string;
210
+ }
211
+ /**
212
+ * 清除缓存答案
213
+ */
214
+ export interface PurgeAnswer {
215
+ type: string;
216
+ confirm?: boolean;
217
+ dir?: string;
218
+ urls?: string;
219
+ }
220
+ /**
221
+ * 预热答案
222
+ */
223
+ export interface PrefetchAnswer {
224
+ urls: string;
225
+ confirm?: boolean;
226
+ }
227
+ /**
228
+ * 站点答案
229
+ */
230
+ export interface ZoneAnswer {
231
+ zones: string[];
232
+ }
233
+ /**
234
+ * 检查是否为 API 错误响应
235
+ */
236
+ export type ApiErrorGuard = (result: ApiResult<unknown>) => result is ApiErrorResponse;
237
+ /**
238
+ * 获取任务状态符号函数类型
239
+ */
240
+ export type TaskStatusSymbolGetter = (status: TaskStatus) => string;
241
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * 统一类型定义
3
+ * 所有接口和类型定义集中管理,业务逻辑文件专注于功能实现
4
+ */
5
+ export {};
@@ -0,0 +1,13 @@
1
+ /**
2
+ * 加密文本
3
+ */
4
+ export declare function encrypt(text: string): string;
5
+ /**
6
+ * 解密文本
7
+ */
8
+ export declare function decrypt(encryptedText: string): string;
9
+ /**
10
+ * 检查文本是否为加密格式
11
+ */
12
+ export declare function isEncrypted(text: string): boolean;
13
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/utils/crypto.ts"],"names":[],"mappings":"AAmCA;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAsB5C;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAsBrD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOjD"}
@@ -1 +1,85 @@
1
- import crypto from"crypto";import os from"os";function getMachineId(){const platform=os.platform(),arch=os.arch(),hostname=os.hostname(),cpus=os.cpus(),machineInfo=`${platform}-${arch}-${hostname}-${cpus.length>0?cpus[0].model:""}`;return crypto.createHash("sha256").update(machineInfo).digest("hex")}function deriveKey(password,salt){return crypto.pbkdf2Sync(password,salt,1e5,32,"sha256")}export function encrypt(text){const machineId=getMachineId(),salt=crypto.randomBytes(64),key=deriveKey(machineId,salt),iv=crypto.randomBytes(16),cipher=crypto.createCipheriv("aes-256-gcm",key,iv);let encrypted=cipher.update(text,"utf8","hex");encrypted+=cipher.final("hex");const tag=cipher.getAuthTag();return Buffer.concat([salt,iv,tag,Buffer.from(encrypted,"hex")]).toString("base64")}export function decrypt(encryptedText){try{const combined=Buffer.from(encryptedText,"base64"),salt=combined.subarray(0,64),iv=combined.subarray(64,80),tag=combined.subarray(80,96),encrypted=combined.subarray(96),key=deriveKey(getMachineId(),salt),decipher=crypto.createDecipheriv("aes-256-gcm",key,iv);decipher.setAuthTag(tag);let decrypted=decipher.update(encrypted);return decrypted=Buffer.concat([decrypted,decipher.final()]),decrypted.toString("utf8")}catch(error){throw new Error("解密失败,配置文件可能已损坏或在其他机器上生成")}}export function isEncrypted(text){try{return Buffer.from(text,"base64").length>=96}catch{return!1}}
1
+ /**
2
+ * 加密工具模块
3
+ * 使用 AES-256-GCM 加密敏感信息
4
+ */
5
+ import crypto from 'crypto';
6
+ import os from 'os';
7
+ const ALGORITHM = 'aes-256-gcm';
8
+ const KEY_LENGTH = 32;
9
+ const IV_LENGTH = 16;
10
+ const SALT_LENGTH = 64;
11
+ const TAG_LENGTH = 16;
12
+ /**
13
+ * 获取机器标识(用于生成加密密钥)
14
+ */
15
+ function getMachineId() {
16
+ const platform = os.platform();
17
+ const arch = os.arch();
18
+ const hostname = os.hostname();
19
+ const cpus = os.cpus();
20
+ const cpuModel = cpus.length > 0 ? cpus[0].model : '';
21
+ // 组合多个机器特征生成唯一标识
22
+ const machineInfo = `${platform}-${arch}-${hostname}-${cpuModel}`;
23
+ return crypto.createHash('sha256').update(machineInfo).digest('hex');
24
+ }
25
+ /**
26
+ * 生成加密密钥
27
+ */
28
+ function deriveKey(password, salt) {
29
+ return crypto.pbkdf2Sync(password, salt, 100000, KEY_LENGTH, 'sha256');
30
+ }
31
+ /**
32
+ * 加密文本
33
+ */
34
+ export function encrypt(text) {
35
+ const machineId = getMachineId();
36
+ const salt = crypto.randomBytes(SALT_LENGTH);
37
+ const key = deriveKey(machineId, salt);
38
+ const iv = crypto.randomBytes(IV_LENGTH);
39
+ const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
40
+ let encrypted = cipher.update(text, 'utf8', 'hex');
41
+ encrypted += cipher.final('hex');
42
+ const tag = cipher.getAuthTag();
43
+ // 格式: salt(128) + iv(32) + tag(32) + encrypted
44
+ const combined = Buffer.concat([
45
+ salt,
46
+ iv,
47
+ tag,
48
+ Buffer.from(encrypted, 'hex')
49
+ ]);
50
+ return combined.toString('base64');
51
+ }
52
+ /**
53
+ * 解密文本
54
+ */
55
+ export function decrypt(encryptedText) {
56
+ try {
57
+ const combined = Buffer.from(encryptedText, 'base64');
58
+ const salt = combined.subarray(0, SALT_LENGTH);
59
+ const iv = combined.subarray(SALT_LENGTH, SALT_LENGTH + IV_LENGTH);
60
+ const tag = combined.subarray(SALT_LENGTH + IV_LENGTH, SALT_LENGTH + IV_LENGTH + TAG_LENGTH);
61
+ const encrypted = combined.subarray(SALT_LENGTH + IV_LENGTH + TAG_LENGTH);
62
+ const machineId = getMachineId();
63
+ const key = deriveKey(machineId, salt);
64
+ const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
65
+ decipher.setAuthTag(tag);
66
+ let decrypted = decipher.update(encrypted);
67
+ decrypted = Buffer.concat([decrypted, decipher.final()]);
68
+ return decrypted.toString('utf8');
69
+ }
70
+ catch (error) {
71
+ throw new Error('解密失败,配置文件可能已损坏或在其他机器上生成');
72
+ }
73
+ }
74
+ /**
75
+ * 检查文本是否为加密格式
76
+ */
77
+ export function isEncrypted(text) {
78
+ try {
79
+ const combined = Buffer.from(text, 'base64');
80
+ return combined.length >= SALT_LENGTH + IV_LENGTH + TAG_LENGTH;
81
+ }
82
+ catch {
83
+ return false;
84
+ }
85
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * 日期时间工具函数
3
+ */
4
+ /**
5
+ * 将 UTC 时间转换为北京时间 (UTC+8)
6
+ * @param utcTime UTC 时间字符串,格式如 "2026-03-11T10:46:33Z"
7
+ * @returns 格式化后的北京时间字符串,格式如 "2026-03-11 18:46:33"
8
+ */
9
+ export declare function utcToBeijingTime(utcTime: string): string;
10
+ /**
11
+ * 格式化为 ISO 8601 格式,时区为 +08:00
12
+ * @param date 日期对象
13
+ * @returns ISO 8601 格式字符串,如 "2026-03-11T18:46:33+08:00"
14
+ */
15
+ export declare function toISOStringWithTimezone(date: Date): string;
16
+ /**
17
+ * 获取当前时间一周前的日期
18
+ * @returns 一周前的 Date 对象
19
+ */
20
+ export declare function getOneWeekAgo(): Date;
21
+ /**
22
+ * 获取当前时间一月前的日期
23
+ * @returns 一月前的 Date 对象
24
+ */
25
+ export declare function getOneMonthAgo(): Date;
26
+ //# sourceMappingURL=date.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../src/utils/date.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAYxD;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAQ1D;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAGpC;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAGrC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * 日期时间工具函数
3
+ */
4
+ /**
5
+ * 将 UTC 时间转换为北京时间 (UTC+8)
6
+ * @param utcTime UTC 时间字符串,格式如 "2026-03-11T10:46:33Z"
7
+ * @returns 格式化后的北京时间字符串,格式如 "2026-03-11 18:46:33"
8
+ */
9
+ export function utcToBeijingTime(utcTime) {
10
+ if (!utcTime)
11
+ return "";
12
+ const date = new Date(utcTime);
13
+ // 转换为北京时间(UTC+8)
14
+ const beijingTime = new Date(date.getTime() + 8 * 60 * 60 * 1000);
15
+ const year = beijingTime.getUTCFullYear();
16
+ const month = String(beijingTime.getUTCMonth() + 1).padStart(2, "0");
17
+ const day = String(beijingTime.getUTCDate()).padStart(2, "0");
18
+ const hours = String(beijingTime.getUTCHours()).padStart(2, "0");
19
+ const minutes = String(beijingTime.getUTCMinutes()).padStart(2, "0");
20
+ const seconds = String(beijingTime.getUTCSeconds()).padStart(2, "0");
21
+ return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
22
+ }
23
+ /**
24
+ * 格式化为 ISO 8601 格式,时区为 +08:00
25
+ * @param date 日期对象
26
+ * @returns ISO 8601 格式字符串,如 "2026-03-11T18:46:33+08:00"
27
+ */
28
+ export function toISOStringWithTimezone(date) {
29
+ const year = date.getFullYear();
30
+ const month = String(date.getMonth() + 1).padStart(2, "0");
31
+ const day = String(date.getDate()).padStart(2, "0");
32
+ const hours = String(date.getHours()).padStart(2, "0");
33
+ const minutes = String(date.getMinutes()).padStart(2, "0");
34
+ const seconds = String(date.getSeconds()).padStart(2, "0");
35
+ return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}+08:00`;
36
+ }
37
+ /**
38
+ * 获取当前时间一周前的日期
39
+ * @returns 一周前的 Date 对象
40
+ */
41
+ export function getOneWeekAgo() {
42
+ const now = new Date();
43
+ return new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
44
+ }
45
+ /**
46
+ * 获取当前时间一月前的日期
47
+ * @returns 一月前的 Date 对象
48
+ */
49
+ export function getOneMonthAgo() {
50
+ const now = new Date();
51
+ return new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
52
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * 显示相关工具函数
3
+ */
4
+ import type { TableConfig } from '../types/index.js';
5
+ /**
6
+ * 遮罩字符串(用于隐藏敏感信息)
7
+ * @param str 原始字符串
8
+ * @param showLength 开头和结尾显示的字符数
9
+ * @returns 遮罩后的字符串
10
+ */
11
+ export declare function maskString(str: string, showLength?: number): string;
12
+ /**
13
+ * 截断过长的文本
14
+ * @param text 原始文本
15
+ * @param maxLength 最大长度
16
+ * @returns 截断后的文本
17
+ */
18
+ export declare function truncateText(text: string, maxLength: number): string;
19
+ /**
20
+ * 创建标准化的表格配置
21
+ * @param heads 表头数组
22
+ * @param colWidths 列宽数组
23
+ * @returns cli-table3 配置对象
24
+ */
25
+ export declare function createTableConfig(heads: string[], colWidths: number[]): TableConfig;
26
+ /**
27
+ * 获取任务状态的显示符号
28
+ * @param status 任务状态
29
+ * @returns 状态符号字符串
30
+ */
31
+ export declare function getStatusSymbol(status: string): string;
32
+ /**
33
+ * 获取任务类型的中文名称
34
+ * @param type 任务类型
35
+ * @returns 中文名称
36
+ */
37
+ export declare function getPurgeTypeName(type: string): string;
38
+ //# sourceMappingURL=display.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../../src/utils/display.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,SAAI,GAAG,MAAM,CAI9D;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAIpE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,WAAW,CAKnF;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAWtD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAWrD"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * 遮罩字符串(用于隐藏敏感信息)
3
+ * @param str 原始字符串
4
+ * @param showLength 开头和结尾显示的字符数
5
+ * @returns 遮罩后的字符串
6
+ */
7
+ export function maskString(str, showLength = 4) {
8
+ if (!str)
9
+ return "N/A";
10
+ if (str.length <= showLength * 2)
11
+ return str;
12
+ return str.slice(0, showLength) + "****" + str.slice(-showLength);
13
+ }
14
+ /**
15
+ * 截断过长的文本
16
+ * @param text 原始文本
17
+ * @param maxLength 最大长度
18
+ * @returns 截断后的文本
19
+ */
20
+ export function truncateText(text, maxLength) {
21
+ if (!text)
22
+ return "";
23
+ if (text.length <= maxLength)
24
+ return text;
25
+ return text.slice(0, maxLength - 3) + "...";
26
+ }
27
+ /**
28
+ * 创建标准化的表格配置
29
+ * @param heads 表头数组
30
+ * @param colWidths 列宽数组
31
+ * @returns cli-table3 配置对象
32
+ */
33
+ export function createTableConfig(heads, colWidths) {
34
+ return {
35
+ head: heads,
36
+ colWidths: colWidths,
37
+ };
38
+ }
39
+ /**
40
+ * 获取任务状态的显示符号
41
+ * @param status 任务状态
42
+ * @returns 状态符号字符串
43
+ */
44
+ export function getStatusSymbol(status) {
45
+ switch (status) {
46
+ case "success":
47
+ return "✓";
48
+ case "processing":
49
+ case "pending":
50
+ return "⏳";
51
+ case "failed":
52
+ default:
53
+ return "✗";
54
+ }
55
+ }
56
+ /**
57
+ * 获取任务类型的中文名称
58
+ * @param type 任务类型
59
+ * @returns 中文名称
60
+ */
61
+ export function getPurgeTypeName(type) {
62
+ switch (type) {
63
+ case "purge_url":
64
+ return "URL";
65
+ case "purge_prefix":
66
+ return "目录";
67
+ case "purge_all":
68
+ return "全部";
69
+ default:
70
+ return type;
71
+ }
72
+ }
@@ -0,0 +1,6 @@
1
+ import type { SignatureOptions } from '../types/index.js';
2
+ /**
3
+ * 计算 TC3-HMAC-SHA256 签名
4
+ */
5
+ export declare function calculateSignature(options: SignatureOptions): string;
6
+ //# sourceMappingURL=signature.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signature.d.ts","sourceRoot":"","sources":["../../src/utils/signature.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAsDpE"}
@@ -1 +1,49 @@
1
- import crypto from"crypto";export function calculateSignature(options){const{secretId,secretKey,endpoint,action,requestBody,timestamp}=options,CanonicalRequest="POST\n/\n\n"+`content-type:application/json; charset=utf-8\nhost:${new URL(`https://${endpoint}`).host}\nx-tc-action:${action.toLowerCase()}\n`+"\ncontent-type;host;x-tc-action\n"+crypto.createHash("sha256").update(requestBody).digest("hex").toLowerCase(),dateStr=new Date(1e3*parseInt(timestamp)).toISOString().slice(0,10),CredentialScope=`${dateStr}/teo/tc3_request`,StringToSign="TC3-HMAC-SHA256\n"+timestamp+"\n"+CredentialScope+"\n"+crypto.createHash("sha256").update(CanonicalRequest).digest("hex").toLowerCase(),secretDate=crypto.createHmac("sha256","TC3"+secretKey).update(dateStr).digest(),secretService=crypto.createHmac("sha256",secretDate).update("teo").digest(),secretSigning=crypto.createHmac("sha256",secretService).update("tc3_request").digest();return`TC3-HMAC-SHA256 Credential=${secretId}/${CredentialScope}, SignedHeaders=content-type;host;x-tc-action, Signature=${crypto.createHmac("sha256",secretSigning).update(StringToSign).digest("hex")}`}
1
+ /**
2
+ * TC3-HMAC-SHA256 签名工具
3
+ */
4
+ import crypto from 'crypto';
5
+ /**
6
+ * 计算 TC3-HMAC-SHA256 签名
7
+ */
8
+ export function calculateSignature(options) {
9
+ const { secretId, secretKey, endpoint, action, requestBody, timestamp } = options;
10
+ // 确保 endpoint 有效,防止 Invalid URL 错误
11
+ const validEndpoint = endpoint || "teo.tencentcloudapi.com";
12
+ const host = new URL(`https://${validEndpoint}`).host;
13
+ // 第一步:拼接规范请求串 CanonicalRequest
14
+ const HTTPRequestMethod = 'POST';
15
+ const CanonicalURI = '/';
16
+ const CanonicalQueryString = '';
17
+ // CanonicalHeaders 按照小写 key 的 ASCII 升序排列
18
+ const CanonicalHeaders = `content-type:application/json; charset=utf-8\n` +
19
+ `host:${host}\n` +
20
+ `x-tc-action:${action.toLowerCase()}\n`;
21
+ const SignedHeaders = 'content-type;host;x-tc-action';
22
+ const HashedRequestPayload = crypto.createHash('sha256').update(requestBody).digest('hex').toLowerCase();
23
+ const CanonicalRequest = HTTPRequestMethod + '\n' +
24
+ CanonicalURI + '\n' +
25
+ CanonicalQueryString + '\n' +
26
+ CanonicalHeaders + '\n' +
27
+ SignedHeaders + '\n' +
28
+ HashedRequestPayload;
29
+ // 第二步:拼接待签名字符串 StringToSign
30
+ const Algorithm = 'TC3-HMAC-SHA256';
31
+ // 将时间戳转换为 UTC 日期格式 YYYY-MM-DD
32
+ const dateStr = new Date(parseInt(timestamp) * 1000).toISOString().slice(0, 10);
33
+ const CredentialScope = `${dateStr}/teo/tc3_request`;
34
+ const HashedCanonicalRequest = crypto.createHash('sha256').update(CanonicalRequest).digest('hex').toLowerCase();
35
+ const StringToSign = Algorithm + '\n' +
36
+ timestamp + '\n' +
37
+ CredentialScope + '\n' +
38
+ HashedCanonicalRequest;
39
+ // 第三步:计算签名 Signature
40
+ // 派生签名密钥
41
+ const secretDate = crypto.createHmac('sha256', 'TC3' + secretKey).update(dateStr).digest();
42
+ const secretService = crypto.createHmac('sha256', secretDate).update('teo').digest();
43
+ const secretSigning = crypto.createHmac('sha256', secretService).update('tc3_request').digest();
44
+ // 计算签名
45
+ const signature = crypto.createHmac('sha256', secretSigning).update(StringToSign).digest('hex');
46
+ // 第四步:拼接 Authorization 值
47
+ const authorization = `${Algorithm} Credential=${secretId}/${CredentialScope}, SignedHeaders=${SignedHeaders}, Signature=${signature}`;
48
+ return authorization;
49
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edgeone-cli",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "EdgeOne CLI - 本地化 EdgeOne 服务管理工具",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",