@zzclub/z-cli 0.8.0 → 1.0.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/LICENSE +20 -20
- package/dist/commands/config.d.ts +9 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +33 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/set.d.ts +11 -0
- package/dist/commands/set.d.ts.map +1 -0
- package/dist/commands/set.js +43 -0
- package/dist/commands/set.js.map +1 -0
- package/dist/commands/tiny/compressor.d.ts +11 -0
- package/dist/commands/tiny/compressor.d.ts.map +1 -0
- package/dist/commands/tiny/compressor.js +46 -0
- package/dist/commands/tiny/compressor.js.map +1 -0
- package/dist/commands/tiny/file-processor.d.ts +40 -0
- package/dist/commands/tiny/file-processor.d.ts.map +1 -0
- package/dist/commands/tiny/file-processor.js +137 -0
- package/dist/commands/tiny/file-processor.js.map +1 -0
- package/dist/commands/tiny/index.d.ts +15 -0
- package/dist/commands/tiny/index.d.ts.map +1 -0
- package/dist/commands/tiny/index.js +55 -0
- package/dist/commands/tiny/index.js.map +1 -0
- package/dist/commands/tiny/types.d.ts +55 -0
- package/dist/commands/tiny/types.d.ts.map +1 -0
- package/dist/commands/tiny/types.js +5 -0
- package/dist/commands/tiny/types.js.map +1 -0
- package/dist/core/config-manager.d.ts +38 -0
- package/dist/core/config-manager.d.ts.map +1 -0
- package/dist/core/config-manager.js +87 -0
- package/dist/core/config-manager.js.map +1 -0
- package/dist/core/logger.d.ts +17 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +30 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +177 -0
- package/dist/index.js.map +1 -0
- package/dist/types/config.d.ts +32 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +18 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +34 -19
- package/readme.md +457 -0
- package/CHANGELOG.md +0 -223
- package/README.md +0 -329
- package/src/command/config.js +0 -97
- package/src/command/i18n.js +0 -318
- package/src/command/index.js +0 -30
- package/src/command/picgo.js +0 -122
- package/src/command/replace.js +0 -81
- package/src/command/set.js +0 -47
- package/src/command/tiny.js +0 -328
- package/src/command/translate.js +0 -344
- package/src/config.json +0 -16
- package/src/index.js +0 -31
- package/src/translate-api/index.js +0 -77
- package/src/translate-api/md5.js +0 -231
- package/src/utils/common.js +0 -218
- package/src/utils/file.js +0 -61
- package/src/utils/picgo.js +0 -149
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2024 z-cli
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 z-cli
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6B5E"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ConfigManager } from '../core/config-manager.js';
|
|
2
|
+
import { logger } from '../core/logger.js';
|
|
3
|
+
/**
|
|
4
|
+
* Config 命令 - 查看或重置配置
|
|
5
|
+
*/
|
|
6
|
+
export async function configCommand(options) {
|
|
7
|
+
try {
|
|
8
|
+
const configManager = new ConfigManager();
|
|
9
|
+
// 显示配置文件路径
|
|
10
|
+
if (options.path) {
|
|
11
|
+
logger.info(`配置文件路径: ${configManager.getConfigPath()}`);
|
|
12
|
+
process.exit(0);
|
|
13
|
+
}
|
|
14
|
+
// 重置配置
|
|
15
|
+
if (options.reset) {
|
|
16
|
+
configManager.reset();
|
|
17
|
+
logger.success('配置已重置为默认值');
|
|
18
|
+
const config = configManager.getConfig();
|
|
19
|
+
console.log(JSON.stringify(config, null, 2));
|
|
20
|
+
process.exit(0);
|
|
21
|
+
}
|
|
22
|
+
// 显示当前配置
|
|
23
|
+
const config = configManager.getConfig();
|
|
24
|
+
logger.info('当前配置:');
|
|
25
|
+
console.log(JSON.stringify(config, null, 2));
|
|
26
|
+
process.exit(0);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
logger.error(`配置操作失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAO3C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAyB;IAC3D,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;QAE1C,WAAW;QACX,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,MAAM,CAAC,IAAI,CAAC,WAAW,aAAa,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;YACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,OAAO;QACP,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,aAAa,CAAC,KAAK,EAAE,CAAC;YACtB,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;YAC5B,MAAM,MAAM,GAAG,aAAa,CAAC,SAAS,EAAE,CAAC;YACzC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,SAAS;QACT,MAAM,MAAM,GAAG,aAAa,CAAC,SAAS,EAAE,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAE7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,WAAW,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface SetCliOptions {
|
|
2
|
+
quality?: number;
|
|
3
|
+
recursive?: boolean;
|
|
4
|
+
overwrite?: boolean;
|
|
5
|
+
output?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Set 命令 - 更新配置
|
|
9
|
+
*/
|
|
10
|
+
export declare function setCommand(options: SetCliOptions): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=set.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../src/commands/set.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA2CtE"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ConfigManager } from '../core/config-manager.js';
|
|
2
|
+
import { logger } from '../core/logger.js';
|
|
3
|
+
/**
|
|
4
|
+
* Set 命令 - 更新配置
|
|
5
|
+
*/
|
|
6
|
+
export async function setCommand(options) {
|
|
7
|
+
try {
|
|
8
|
+
const configManager = new ConfigManager();
|
|
9
|
+
const updates = {};
|
|
10
|
+
if (options.quality !== undefined) {
|
|
11
|
+
if (options.quality < 1 || options.quality > 100) {
|
|
12
|
+
logger.error('压缩质量必须在 1-100 之间');
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
updates.quality = options.quality;
|
|
16
|
+
}
|
|
17
|
+
if (options.recursive !== undefined) {
|
|
18
|
+
updates.recursive = options.recursive;
|
|
19
|
+
}
|
|
20
|
+
if (options.overwrite !== undefined) {
|
|
21
|
+
updates.overwrite = options.overwrite;
|
|
22
|
+
}
|
|
23
|
+
if (options.output !== undefined) {
|
|
24
|
+
updates.outputDir = options.output;
|
|
25
|
+
}
|
|
26
|
+
if (Object.keys(updates).length === 0) {
|
|
27
|
+
logger.warn('没有提供任何配置更新');
|
|
28
|
+
process.exit(0);
|
|
29
|
+
}
|
|
30
|
+
configManager.updateTinyConfig(updates);
|
|
31
|
+
logger.success('配置已更新');
|
|
32
|
+
// 显示当前配置
|
|
33
|
+
const config = configManager.getTinyConfig();
|
|
34
|
+
logger.info('当前配置:');
|
|
35
|
+
console.log(JSON.stringify(config, null, 2));
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
logger.error(`配置更新失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=set.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set.js","sourceRoot":"","sources":["../../src/commands/set.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAS3C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAsB;IACrD,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAQ,EAAE,CAAC;QAExB,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAClC,IAAI,OAAO,CAAC,OAAO,GAAG,CAAC,IAAI,OAAO,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC;gBACjD,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;gBACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QACpC,CAAC;QAED,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACpC,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACxC,CAAC;QAED,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACpC,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACxC,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACjC,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;QACrC,CAAC;QAED,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC1B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,aAAa,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACxC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAExB,SAAS;QACT,MAAM,MAAM,GAAG,aAAa,CAAC,aAAa,EAAE,CAAC;QAC7C,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAE7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,WAAW,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CompressionOptions, CompressionResult } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* 图片压缩器
|
|
4
|
+
*/
|
|
5
|
+
export declare class ImageCompressor {
|
|
6
|
+
/**
|
|
7
|
+
* 压缩单个图片
|
|
8
|
+
*/
|
|
9
|
+
compress(inputPath: string, outputPath: string, options: CompressionOptions): Promise<CompressionResult>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=compressor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compressor.d.ts","sourceRoot":"","sources":["../../../src/commands/tiny/compressor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAExE;;GAEG;AACH,qBAAa,eAAe;IAC1B;;OAEG;IACG,QAAQ,CACZ,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,iBAAiB,CAAC;CAsC9B"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import sharp from 'sharp';
|
|
2
|
+
import { statSync } from 'node:fs';
|
|
3
|
+
/**
|
|
4
|
+
* 图片压缩器
|
|
5
|
+
*/
|
|
6
|
+
export class ImageCompressor {
|
|
7
|
+
/**
|
|
8
|
+
* 压缩单个图片
|
|
9
|
+
*/
|
|
10
|
+
async compress(inputPath, outputPath, options) {
|
|
11
|
+
try {
|
|
12
|
+
// 获取原始文件大小
|
|
13
|
+
const originalSize = statSync(inputPath).size;
|
|
14
|
+
// 使用 Sharp 压缩
|
|
15
|
+
await sharp(inputPath)
|
|
16
|
+
.jpeg({ quality: options.quality, mozjpeg: true })
|
|
17
|
+
.png({ quality: options.quality, compressionLevel: 9 })
|
|
18
|
+
.webp({ quality: options.quality })
|
|
19
|
+
.toFile(outputPath);
|
|
20
|
+
// 获取压缩后文件大小
|
|
21
|
+
const compressedSize = statSync(outputPath).size;
|
|
22
|
+
// 计算压缩率
|
|
23
|
+
const compressionRatio = ((originalSize - compressedSize) / originalSize) * 100;
|
|
24
|
+
return {
|
|
25
|
+
inputPath,
|
|
26
|
+
outputPath,
|
|
27
|
+
originalSize,
|
|
28
|
+
compressedSize,
|
|
29
|
+
compressionRatio,
|
|
30
|
+
success: true,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
return {
|
|
35
|
+
inputPath,
|
|
36
|
+
outputPath,
|
|
37
|
+
originalSize: 0,
|
|
38
|
+
compressedSize: 0,
|
|
39
|
+
compressionRatio: 0,
|
|
40
|
+
success: false,
|
|
41
|
+
error: error instanceof Error ? error.message : String(error),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=compressor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compressor.js","sourceRoot":"","sources":["../../../src/commands/tiny/compressor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGnC;;GAEG;AACH,MAAM,OAAO,eAAe;IAC1B;;OAEG;IACH,KAAK,CAAC,QAAQ,CACZ,SAAiB,EACjB,UAAkB,EAClB,OAA2B;QAE3B,IAAI,CAAC;YACH,WAAW;YACX,MAAM,YAAY,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC;YAE9C,cAAc;YACd,MAAM,KAAK,CAAC,SAAS,CAAC;iBACnB,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;iBACjD,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,gBAAgB,EAAE,CAAC,EAAE,CAAC;iBACtD,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;iBAClC,MAAM,CAAC,UAAU,CAAC,CAAC;YAEtB,YAAY;YACZ,MAAM,cAAc,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;YAEjD,QAAQ;YACR,MAAM,gBAAgB,GAAG,CAAC,CAAC,YAAY,GAAG,cAAc,CAAC,GAAG,YAAY,CAAC,GAAG,GAAG,CAAC;YAEhF,OAAO;gBACL,SAAS;gBACT,UAAU;gBACV,YAAY;gBACZ,cAAc;gBACd,gBAAgB;gBAChB,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,SAAS;gBACT,UAAU;gBACV,YAAY,EAAE,CAAC;gBACf,cAAc,EAAE,CAAC;gBACjB,gBAAgB,EAAE,CAAC;gBACnB,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { CompressionOptions, ProcessingStats } from './types.js';
|
|
2
|
+
import { ImageCompressor } from './compressor.js';
|
|
3
|
+
/**
|
|
4
|
+
* 文件处理器
|
|
5
|
+
*/
|
|
6
|
+
export declare class FileProcessor {
|
|
7
|
+
private compressor;
|
|
8
|
+
constructor(compressor: ImageCompressor);
|
|
9
|
+
/**
|
|
10
|
+
* 处理单个文件或目录
|
|
11
|
+
*/
|
|
12
|
+
process(inputPath: string, options: CompressionOptions & {
|
|
13
|
+
recursive?: boolean;
|
|
14
|
+
}): Promise<ProcessingStats>;
|
|
15
|
+
/**
|
|
16
|
+
* 处理单个文件
|
|
17
|
+
*/
|
|
18
|
+
private processFile;
|
|
19
|
+
/**
|
|
20
|
+
* 处理目录
|
|
21
|
+
*/
|
|
22
|
+
private processDirectory;
|
|
23
|
+
/**
|
|
24
|
+
* 收集目录中的图片文件
|
|
25
|
+
*/
|
|
26
|
+
private collectImageFiles;
|
|
27
|
+
/**
|
|
28
|
+
* 确定输出路径
|
|
29
|
+
*/
|
|
30
|
+
private getOutputPath;
|
|
31
|
+
/**
|
|
32
|
+
* 创建空统计
|
|
33
|
+
*/
|
|
34
|
+
private emptyStats;
|
|
35
|
+
/**
|
|
36
|
+
* 合并统计数据
|
|
37
|
+
*/
|
|
38
|
+
private mergeStats;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=file-processor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-processor.d.ts","sourceRoot":"","sources":["../../../src/commands/tiny/file-processor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEtE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGlD;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAAkB;gBAExB,UAAU,EAAE,eAAe;IAIvC;;OAEG;IACG,OAAO,CACX,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,kBAAkB,GAAG;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,GACpD,OAAO,CAAC,eAAe,CAAC;IAc3B;;OAEG;YACW,WAAW;IAqCzB;;OAEG;YACW,gBAAgB;IAuB9B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAoBzB;;OAEG;IACH,OAAO,CAAC,aAAa;IAarB;;OAEG;IACH,OAAO,CAAC,UAAU;IAYlB;;OAEG;IACH,OAAO,CAAC,UAAU;CAcnB"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { readdirSync, statSync } from 'node:fs';
|
|
2
|
+
import { join, dirname, basename, extname } from 'node:path';
|
|
3
|
+
import { SUPPORTED_FORMATS } from './types.js';
|
|
4
|
+
import { logger, formatFileSize, formatCompressionRatio } from '../../core/logger.js';
|
|
5
|
+
/**
|
|
6
|
+
* 文件处理器
|
|
7
|
+
*/
|
|
8
|
+
export class FileProcessor {
|
|
9
|
+
compressor;
|
|
10
|
+
constructor(compressor) {
|
|
11
|
+
this.compressor = compressor;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* 处理单个文件或目录
|
|
15
|
+
*/
|
|
16
|
+
async process(inputPath, options) {
|
|
17
|
+
const stat = statSync(inputPath);
|
|
18
|
+
if (stat.isFile()) {
|
|
19
|
+
return this.processFile(inputPath, options);
|
|
20
|
+
}
|
|
21
|
+
if (stat.isDirectory() && options.recursive) {
|
|
22
|
+
return this.processDirectory(inputPath, options);
|
|
23
|
+
}
|
|
24
|
+
throw new Error('输入路径必须是文件,或者是目录(需要 --recursive 参数)');
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 处理单个文件
|
|
28
|
+
*/
|
|
29
|
+
async processFile(filePath, options) {
|
|
30
|
+
// 检查文件格式
|
|
31
|
+
const ext = extname(filePath).toLowerCase();
|
|
32
|
+
if (!SUPPORTED_FORMATS.includes(ext)) {
|
|
33
|
+
throw new Error(`不支持的文件格式: ${ext},支持的格式: ${SUPPORTED_FORMATS.join(', ')}`);
|
|
34
|
+
}
|
|
35
|
+
// 确定输出路径
|
|
36
|
+
const outputPath = this.getOutputPath(filePath, options);
|
|
37
|
+
logger.start(`正在压缩: ${filePath}`);
|
|
38
|
+
const result = await this.compressor.compress(filePath, outputPath, options);
|
|
39
|
+
if (result.success) {
|
|
40
|
+
logger.success(`压缩成功: ${formatFileSize(result.originalSize)} → ${formatFileSize(result.compressedSize)} ` +
|
|
41
|
+
`(减少 ${formatCompressionRatio(result.compressionRatio)})`);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
logger.error(`压缩失败: ${result.error}`);
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
total: 1,
|
|
48
|
+
success: result.success ? 1 : 0,
|
|
49
|
+
failed: result.success ? 0 : 1,
|
|
50
|
+
totalOriginalSize: result.originalSize,
|
|
51
|
+
totalCompressedSize: result.compressedSize,
|
|
52
|
+
averageCompressionRatio: result.compressionRatio,
|
|
53
|
+
results: [result],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* 处理目录
|
|
58
|
+
*/
|
|
59
|
+
async processDirectory(dirPath, options) {
|
|
60
|
+
const files = this.collectImageFiles(dirPath, options.recursive || false);
|
|
61
|
+
if (files.length === 0) {
|
|
62
|
+
logger.warn(`目录中没有找到支持的图片文件: ${dirPath}`);
|
|
63
|
+
return this.emptyStats();
|
|
64
|
+
}
|
|
65
|
+
logger.info(`找到 ${files.length} 个图片文件`);
|
|
66
|
+
const stats = this.emptyStats();
|
|
67
|
+
for (const file of files) {
|
|
68
|
+
const fileStats = await this.processFile(file, options);
|
|
69
|
+
this.mergeStats(stats, fileStats);
|
|
70
|
+
}
|
|
71
|
+
return stats;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* 收集目录中的图片文件
|
|
75
|
+
*/
|
|
76
|
+
collectImageFiles(dirPath, recursive) {
|
|
77
|
+
const files = [];
|
|
78
|
+
const entries = readdirSync(dirPath, { withFileTypes: true });
|
|
79
|
+
for (const entry of entries) {
|
|
80
|
+
const fullPath = join(dirPath, entry.name);
|
|
81
|
+
if (entry.isFile()) {
|
|
82
|
+
const ext = extname(entry.name).toLowerCase();
|
|
83
|
+
if (SUPPORTED_FORMATS.includes(ext)) {
|
|
84
|
+
files.push(fullPath);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
else if (entry.isDirectory() && recursive) {
|
|
88
|
+
files.push(...this.collectImageFiles(fullPath, recursive));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return files;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* 确定输出路径
|
|
95
|
+
*/
|
|
96
|
+
getOutputPath(inputPath, options) {
|
|
97
|
+
const dir = dirname(inputPath);
|
|
98
|
+
const base = basename(inputPath, extname(inputPath));
|
|
99
|
+
const ext = extname(inputPath);
|
|
100
|
+
if (options.overwrite) {
|
|
101
|
+
return inputPath;
|
|
102
|
+
}
|
|
103
|
+
const outputDir = options.outputDir || dir;
|
|
104
|
+
return join(outputDir, `${base}-compressed${ext}`);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* 创建空统计
|
|
108
|
+
*/
|
|
109
|
+
emptyStats() {
|
|
110
|
+
return {
|
|
111
|
+
total: 0,
|
|
112
|
+
success: 0,
|
|
113
|
+
failed: 0,
|
|
114
|
+
totalOriginalSize: 0,
|
|
115
|
+
totalCompressedSize: 0,
|
|
116
|
+
averageCompressionRatio: 0,
|
|
117
|
+
results: [],
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* 合并统计数据
|
|
122
|
+
*/
|
|
123
|
+
mergeStats(target, source) {
|
|
124
|
+
target.total += source.total;
|
|
125
|
+
target.success += source.success;
|
|
126
|
+
target.failed += source.failed;
|
|
127
|
+
target.totalOriginalSize += source.totalOriginalSize;
|
|
128
|
+
target.totalCompressedSize += source.totalCompressedSize;
|
|
129
|
+
target.results.push(...source.results);
|
|
130
|
+
// 重新计算平均压缩率
|
|
131
|
+
if (target.totalOriginalSize > 0) {
|
|
132
|
+
target.averageCompressionRatio =
|
|
133
|
+
((target.totalOriginalSize - target.totalCompressedSize) / target.totalOriginalSize) * 100;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=file-processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-processor.js","sourceRoot":"","sources":["../../../src/commands/tiny/file-processor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny 命令选项(从 CLI 传入)
|
|
3
|
+
*/
|
|
4
|
+
export interface TinyCliOptions {
|
|
5
|
+
file?: string;
|
|
6
|
+
quality?: number;
|
|
7
|
+
recursive?: boolean;
|
|
8
|
+
overwrite?: boolean;
|
|
9
|
+
output?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Tiny 命令处理函数
|
|
13
|
+
*/
|
|
14
|
+
export declare function tinyCommand(options: TinyCliOptions): Promise<void>;
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/tiny/index.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAuDxE"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import { ImageCompressor } from './compressor.js';
|
|
3
|
+
import { FileProcessor } from './file-processor.js';
|
|
4
|
+
import { ConfigManager } from '../../core/config-manager.js';
|
|
5
|
+
import { logger, formatFileSize, formatCompressionRatio } from '../../core/logger.js';
|
|
6
|
+
/**
|
|
7
|
+
* Tiny 命令处理函数
|
|
8
|
+
*/
|
|
9
|
+
export async function tinyCommand(options) {
|
|
10
|
+
try {
|
|
11
|
+
const configManager = new ConfigManager();
|
|
12
|
+
const config = configManager.getTinyConfig();
|
|
13
|
+
// 合并配置和命令行选项
|
|
14
|
+
const quality = options.quality ?? config.quality;
|
|
15
|
+
const recursive = options.recursive ?? config.recursive;
|
|
16
|
+
const overwrite = options.overwrite ?? config.overwrite;
|
|
17
|
+
const outputDir = options.output ?? config.outputDir;
|
|
18
|
+
// 验证输入
|
|
19
|
+
if (!options.file) {
|
|
20
|
+
logger.error('请使用 -f 或 --file 指定要压缩的文件或目录');
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
const inputPath = resolve(process.cwd(), options.file);
|
|
24
|
+
// 验证质量参数
|
|
25
|
+
if (quality < 1 || quality > 100) {
|
|
26
|
+
logger.error('压缩质量必须在 1-100 之间');
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
// 创建压缩选项
|
|
30
|
+
const compressionOptions = {
|
|
31
|
+
quality,
|
|
32
|
+
overwrite,
|
|
33
|
+
outputDir,
|
|
34
|
+
recursive,
|
|
35
|
+
};
|
|
36
|
+
// 执行压缩
|
|
37
|
+
const compressor = new ImageCompressor();
|
|
38
|
+
const processor = new FileProcessor(compressor);
|
|
39
|
+
const stats = await processor.process(inputPath, compressionOptions);
|
|
40
|
+
// 显示统计信息
|
|
41
|
+
logger.box(`压缩完成\n\n` +
|
|
42
|
+
`总文件数: ${stats.total}\n` +
|
|
43
|
+
`成功: ${stats.success}\n` +
|
|
44
|
+
`失败: ${stats.failed}\n` +
|
|
45
|
+
`总原始大小: ${formatFileSize(stats.totalOriginalSize)}\n` +
|
|
46
|
+
`总压缩后大小: ${formatFileSize(stats.totalCompressedSize)}\n` +
|
|
47
|
+
`平均压缩率: ${formatCompressionRatio(stats.averageCompressionRatio)}`);
|
|
48
|
+
process.exit(0);
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
logger.error(`执行失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/tiny/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAatF;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAuB;IACvD,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;QAC1C,MAAM,MAAM,GAAG,aAAa,CAAC,aAAa,EAAE,CAAC;QAE7C,aAAa;QACb,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC;QAClD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC;QACxD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC;QACxD,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC,SAAS,CAAC;QAErD,OAAO;QACP,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,MAAM,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;YAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAEvD,SAAS;QACT,IAAI,OAAO,GAAG,CAAC,IAAI,OAAO,GAAG,GAAG,EAAE,CAAC;YACjC,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,SAAS;QACT,MAAM,kBAAkB,GAAgD;YACtE,OAAO;YACP,SAAS;YACT,SAAS;YACT,SAAS;SACV,CAAC;QAEF,OAAO;QACP,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,IAAI,aAAa,CAAC,UAAU,CAAC,CAAC;QAEhD,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;QAErE,SAAS;QACT,MAAM,CAAC,GAAG,CACR,UAAU;YACV,SAAS,KAAK,CAAC,KAAK,IAAI;YACxB,OAAO,KAAK,CAAC,OAAO,IAAI;YACxB,OAAO,KAAK,CAAC,MAAM,IAAI;YACvB,UAAU,cAAc,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI;YACrD,WAAW,cAAc,CAAC,KAAK,CAAC,mBAAmB,CAAC,IAAI;YACxD,UAAU,sBAAsB,CAAC,KAAK,CAAC,uBAAuB,CAAC,EAAE,CAClE,CAAC;QAEF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,SAAS,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 压缩选项
|
|
3
|
+
*/
|
|
4
|
+
export interface CompressionOptions {
|
|
5
|
+
/** 压缩质量 (1-100) */
|
|
6
|
+
quality: number;
|
|
7
|
+
/** 是否覆盖原文件 */
|
|
8
|
+
overwrite: boolean;
|
|
9
|
+
/** 输出目录 */
|
|
10
|
+
outputDir: string | null;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 压缩结果
|
|
14
|
+
*/
|
|
15
|
+
export interface CompressionResult {
|
|
16
|
+
/** 源文件路径 */
|
|
17
|
+
inputPath: string;
|
|
18
|
+
/** 输出文件路径 */
|
|
19
|
+
outputPath: string;
|
|
20
|
+
/** 原始文件大小(字节) */
|
|
21
|
+
originalSize: number;
|
|
22
|
+
/** 压缩后文件大小(字节) */
|
|
23
|
+
compressedSize: number;
|
|
24
|
+
/** 压缩率(百分比) */
|
|
25
|
+
compressionRatio: number;
|
|
26
|
+
/** 是否成功 */
|
|
27
|
+
success: boolean;
|
|
28
|
+
/** 错误信息(如果失败) */
|
|
29
|
+
error?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 批量处理统计
|
|
33
|
+
*/
|
|
34
|
+
export interface ProcessingStats {
|
|
35
|
+
/** 处理的文件总数 */
|
|
36
|
+
total: number;
|
|
37
|
+
/** 成功数量 */
|
|
38
|
+
success: number;
|
|
39
|
+
/** 失败数量 */
|
|
40
|
+
failed: number;
|
|
41
|
+
/** 总原始大小(字节) */
|
|
42
|
+
totalOriginalSize: number;
|
|
43
|
+
/** 总压缩后大小(字节) */
|
|
44
|
+
totalCompressedSize: number;
|
|
45
|
+
/** 平均压缩率(百分比) */
|
|
46
|
+
averageCompressionRatio: number;
|
|
47
|
+
/** 处理结果列表 */
|
|
48
|
+
results: CompressionResult[];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 支持的图片格式
|
|
52
|
+
*/
|
|
53
|
+
export declare const SUPPORTED_FORMATS: readonly [".jpg", ".jpeg", ".png", ".webp"];
|
|
54
|
+
export type SupportedFormat = typeof SUPPORTED_FORMATS[number];
|
|
55
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/commands/tiny/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,mBAAmB;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW;IACX,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,YAAY;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,cAAc;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW;IACX,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB;IACjB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB;IACjB,uBAAuB,EAAE,MAAM,CAAC;IAChC,aAAa;IACb,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,6CAA8C,CAAC;AAC7E,MAAM,MAAM,eAAe,GAAG,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/commands/tiny/types.ts"],"names":[],"mappings":"AAoDA;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAU,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { GlobalConfig } from '../types/config.js';
|
|
2
|
+
/**
|
|
3
|
+
* 配置管理器
|
|
4
|
+
*/
|
|
5
|
+
export declare class ConfigManager {
|
|
6
|
+
private configPath;
|
|
7
|
+
private config;
|
|
8
|
+
constructor();
|
|
9
|
+
/**
|
|
10
|
+
* 加载配置
|
|
11
|
+
*/
|
|
12
|
+
private load;
|
|
13
|
+
/**
|
|
14
|
+
* 保存配置
|
|
15
|
+
*/
|
|
16
|
+
private save;
|
|
17
|
+
/**
|
|
18
|
+
* 获取完整配置
|
|
19
|
+
*/
|
|
20
|
+
getConfig(): GlobalConfig;
|
|
21
|
+
/**
|
|
22
|
+
* 获取 Tiny 配置
|
|
23
|
+
*/
|
|
24
|
+
getTinyConfig(): import("../types/config.js").TinyConfig;
|
|
25
|
+
/**
|
|
26
|
+
* 更新 Tiny 配置
|
|
27
|
+
*/
|
|
28
|
+
updateTinyConfig(updates: Partial<GlobalConfig['tiny']>): void;
|
|
29
|
+
/**
|
|
30
|
+
* 重置为默认配置
|
|
31
|
+
*/
|
|
32
|
+
reset(): void;
|
|
33
|
+
/**
|
|
34
|
+
* 获取配置文件路径
|
|
35
|
+
*/
|
|
36
|
+
getConfigPath(): string;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=config-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-manager.d.ts","sourceRoot":"","sources":["../../src/core/config-manager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvD;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAe;;IAe7B;;OAEG;IACH,OAAO,CAAC,IAAI;IAqBZ;;OAEG;IACH,OAAO,CAAC,IAAI;IAQZ;;OAEG;IACH,SAAS,IAAI,YAAY;IAIzB;;OAEG;IACH,aAAa;IAIb;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI;IAK9D;;OAEG;IACH,KAAK,IAAI,IAAI;IAKb;;OAEG;IACH,aAAa,IAAI,MAAM;CAGxB"}
|