@daylenjeez/ccm-switch 1.2.9 → 1.3.1
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/README.md +3 -3
- package/README.zh-CN.md +3 -3
- package/dist/i18n/en.js +8 -2
- package/dist/i18n/index.d.ts +2 -1
- package/dist/i18n/index.js +1 -0
- package/dist/i18n/zh.d.ts +7 -1
- package/dist/i18n/zh.js +8 -2
- package/dist/index.js +58 -14
- package/package.json +2 -1
- package/src/i18n/en.ts +9 -3
- package/src/i18n/index.ts +1 -1
- package/src/i18n/zh.ts +9 -3
- package/src/index.ts +63 -15
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
Switch Claude Code custom model configurations from the terminal in seconds.
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/@daylenjeez/ccm-switch)
|
|
10
|
-
[](https://github.com/daylenjeez/ccm-switch/blob/main/LICENSE)
|
|
11
11
|
[](https://nodejs.org)
|
|
12
12
|
|
|
13
13
|
[中文文档](https://github.com/daylenjeez/ccm-switch/blob/main/README.zh-CN.md) | English
|
|
@@ -130,12 +130,12 @@ Aliases are stored in `~/.ccm/rc.json`:
|
|
|
130
130
|
| `ccm use <name>` | | Switch by name |
|
|
131
131
|
| `ccm add` | `new` | Interactive add wizard |
|
|
132
132
|
| `ccm save <name>` | | Save current settings as profile |
|
|
133
|
-
| `ccm show [name]` | | View config details |
|
|
133
|
+
| `ccm show [name]` | | View config details (all configs in JSON if no name) |
|
|
134
134
|
| `ccm modify [name]` | `edit` | Edit existing configuration |
|
|
135
135
|
| `ccm remove [name]` | `rm` | Interactive or named delete |
|
|
136
136
|
| `ccm current` | | Show active configuration |
|
|
137
|
-
| `ccm config` | | View data source mode (deprecated) |
|
|
138
137
|
| `ccm sync` | | Sync cc-switch configs into standalone |
|
|
138
|
+
| `ccm import [file]` | | Import configs from JSON (stdin if no file) |
|
|
139
139
|
| `ccm clear` | | Clean up data files |
|
|
140
140
|
|
|
141
141
|
### Aliases
|
package/README.zh-CN.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
在终端几秒内完成 Claude Code 自定义模型配置的管理和切换。
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/@daylenjeez/ccm-switch)
|
|
10
|
-
[](https://github.com/daylenjeez/ccm-switch/blob/main/LICENSE)
|
|
11
11
|
[](https://nodejs.org)
|
|
12
12
|
|
|
13
13
|
[English](https://github.com/daylenjeez/ccm-switch/blob/main/README.md) | 中文文档
|
|
@@ -130,12 +130,12 @@ ANTHROPIC_DEFAULT_HAIKU_MODEL (可选):
|
|
|
130
130
|
| `ccm use <name>` | | 按名称切换 |
|
|
131
131
|
| `ccm add` | `new` | 交互式添加向导 |
|
|
132
132
|
| `ccm save <name>` | | 将当前设置保存为方案 |
|
|
133
|
-
| `ccm show [name]` | |
|
|
133
|
+
| `ccm show [name]` | | 查看配置详情(无名称时输出全部 JSON) |
|
|
134
134
|
| `ccm modify [name]` | `edit` | 修改已有配置 |
|
|
135
135
|
| `ccm remove [name]` | `rm` | 交互式或指定名称删除 |
|
|
136
136
|
| `ccm current` | | 显示当前激活配置 |
|
|
137
|
-
| `ccm config` | | 查看数据源模式(已废弃) |
|
|
138
137
|
| `ccm sync` | | 从 cc-switch 同步配置到本地 |
|
|
138
|
+
| `ccm import [file]` | | 从 JSON 导入配置(无文件时从 stdin 读取) |
|
|
139
139
|
| `ccm clear` | | 清理数据文件 |
|
|
140
140
|
|
|
141
141
|
### 别名管理
|
package/dist/i18n/en.js
CHANGED
|
@@ -18,8 +18,6 @@ const en = {
|
|
|
18
18
|
"init.description": "Initialize ccm",
|
|
19
19
|
"init.cc_switch_found": "cc-switch detected. Import configurations from it? (Y/n) ",
|
|
20
20
|
"init.done": "✓ Initialized",
|
|
21
|
-
// config
|
|
22
|
-
"config.description": "View data source mode (deprecated)",
|
|
23
21
|
// list
|
|
24
22
|
"list.description": "List and select configurations",
|
|
25
23
|
"list.empty": "No configurations yet. Use ccm save <name> to save current config",
|
|
@@ -44,6 +42,7 @@ const en = {
|
|
|
44
42
|
// show
|
|
45
43
|
"show.description": "View configuration details (defaults to current)",
|
|
46
44
|
"show.no_current": "No active configuration. Specify a name: ccm show <name>",
|
|
45
|
+
"show.all_header": "All configurations:",
|
|
47
46
|
// remove
|
|
48
47
|
"remove.description": "Delete a configuration",
|
|
49
48
|
"remove.select": "Select configuration to delete:",
|
|
@@ -122,6 +121,13 @@ const en = {
|
|
|
122
121
|
"clear.cancelled": "Cancelled",
|
|
123
122
|
"clear.removed": "✓ Deleted {path}",
|
|
124
123
|
"clear.done": "✓ Cleanup complete",
|
|
124
|
+
// import
|
|
125
|
+
"import.description": "Import configurations from JSON (file or stdin)",
|
|
126
|
+
"import.paste_hint": "Paste JSON and press Ctrl+D (or Ctrl+Z on Windows) to finish:",
|
|
127
|
+
"import.file_not_found": 'File not found: {file}',
|
|
128
|
+
"import.json_parse_error": "Invalid JSON format",
|
|
129
|
+
"import.invalid_format": "Invalid format: expected object with configuration names as keys",
|
|
130
|
+
"import.done": "✓ Imported {count} configurations",
|
|
125
131
|
// store errors
|
|
126
132
|
"store.db_not_found": "cc-switch database not found: {path}",
|
|
127
133
|
};
|
package/dist/i18n/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type TranslationKey } from "./zh.js";
|
|
2
2
|
export type Locale = "zh" | "en";
|
|
3
|
+
declare function getLocale(): Locale;
|
|
3
4
|
export declare function setLocale(locale: Locale): void;
|
|
4
5
|
export declare function t(key: TranslationKey, vars?: Record<string, string>): string;
|
|
5
|
-
export { type TranslationKey };
|
|
6
|
+
export { getLocale, type TranslationKey };
|
package/dist/i18n/index.js
CHANGED
package/dist/i18n/zh.d.ts
CHANGED
|
@@ -13,7 +13,6 @@ declare const zh: {
|
|
|
13
13
|
readonly "init.description": "初始化 ccm";
|
|
14
14
|
readonly "init.cc_switch_found": "检测到 cc-switch 已安装,是否从中导入配置?(Y/n) ";
|
|
15
15
|
readonly "init.done": "✓ 初始化完成";
|
|
16
|
-
readonly "config.description": "查看数据源模式(已废弃)";
|
|
17
16
|
readonly "list.description": "列出并选择配置方案";
|
|
18
17
|
readonly "list.empty": "暂无配置方案。使用 ccm save <name> 保存当前配置";
|
|
19
18
|
readonly "list.header": "可用配置:";
|
|
@@ -33,6 +32,7 @@ declare const zh: {
|
|
|
33
32
|
readonly "save.done": "✓ 已保存当前配置为 \"{name}\"";
|
|
34
33
|
readonly "show.description": "查看配置详情(不指定则显示当前)";
|
|
35
34
|
readonly "show.no_current": "当前无激活配置,请指定名称: ccm show <name>";
|
|
35
|
+
readonly "show.all_header": "所有配置:";
|
|
36
36
|
readonly "remove.description": "删除配置方案";
|
|
37
37
|
readonly "remove.select": "选择要删除的配置:";
|
|
38
38
|
readonly "remove.confirm": "确认删除 \"{name}\"?(y/N) ";
|
|
@@ -103,6 +103,12 @@ declare const zh: {
|
|
|
103
103
|
readonly "clear.cancelled": "已取消清理";
|
|
104
104
|
readonly "clear.removed": "✓ 已删除 {path}";
|
|
105
105
|
readonly "clear.done": "✓ 清理完成";
|
|
106
|
+
readonly "import.description": "从 JSON 导入配置(文件或粘贴)";
|
|
107
|
+
readonly "import.paste_hint": "粘贴 JSON,按 Ctrl+D(或 Windows 的 Ctrl+Z)结束:";
|
|
108
|
+
readonly "import.file_not_found": "文件不存在: {file}";
|
|
109
|
+
readonly "import.json_parse_error": "JSON 格式无效";
|
|
110
|
+
readonly "import.invalid_format": "格式错误: 应为以配置名称为键的对象";
|
|
111
|
+
readonly "import.done": "✓ 已导入 {count} 个配置";
|
|
106
112
|
readonly "store.db_not_found": "cc-switch 数据库不存在: {path}";
|
|
107
113
|
};
|
|
108
114
|
export type TranslationKey = keyof typeof zh;
|
package/dist/i18n/zh.js
CHANGED
|
@@ -18,8 +18,6 @@ const zh = {
|
|
|
18
18
|
"init.description": "初始化 ccm",
|
|
19
19
|
"init.cc_switch_found": "检测到 cc-switch 已安装,是否从中导入配置?(Y/n) ",
|
|
20
20
|
"init.done": "✓ 初始化完成",
|
|
21
|
-
// config
|
|
22
|
-
"config.description": "查看数据源模式(已废弃)",
|
|
23
21
|
// list
|
|
24
22
|
"list.description": "列出并选择配置方案",
|
|
25
23
|
"list.empty": "暂无配置方案。使用 ccm save <name> 保存当前配置",
|
|
@@ -44,6 +42,7 @@ const zh = {
|
|
|
44
42
|
// show
|
|
45
43
|
"show.description": "查看配置详情(不指定则显示当前)",
|
|
46
44
|
"show.no_current": "当前无激活配置,请指定名称: ccm show <name>",
|
|
45
|
+
"show.all_header": "所有配置:",
|
|
47
46
|
// remove
|
|
48
47
|
"remove.description": "删除配置方案",
|
|
49
48
|
"remove.select": "选择要删除的配置:",
|
|
@@ -122,6 +121,13 @@ const zh = {
|
|
|
122
121
|
"clear.cancelled": "已取消清理",
|
|
123
122
|
"clear.removed": "✓ 已删除 {path}",
|
|
124
123
|
"clear.done": "✓ 清理完成",
|
|
124
|
+
// import
|
|
125
|
+
"import.description": "从 JSON 导入配置(文件或粘贴)",
|
|
126
|
+
"import.paste_hint": "粘贴 JSON,按 Ctrl+D(或 Windows 的 Ctrl+Z)结束:",
|
|
127
|
+
"import.file_not_found": '文件不存在: {file}',
|
|
128
|
+
"import.json_parse_error": "JSON 格式无效",
|
|
129
|
+
"import.invalid_format": "格式错误: 应为以配置名称为键的对象",
|
|
130
|
+
"import.done": "✓ 已导入 {count} 个配置",
|
|
125
131
|
// store errors
|
|
126
132
|
"store.db_not_found": "cc-switch 数据库不存在: {path}",
|
|
127
133
|
};
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { writeFileSync, readFileSync, unlinkSync, existsSync } from "fs";
|
|
|
10
10
|
import { tmpdir, homedir } from "os";
|
|
11
11
|
import { join, dirname } from "path";
|
|
12
12
|
import { fileURLToPath } from "url";
|
|
13
|
-
import { t, setLocale } from "./i18n/index.js";
|
|
13
|
+
import { t, setLocale, getLocale } from "./i18n/index.js";
|
|
14
14
|
import * as clack from "@clack/prompts";
|
|
15
15
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
16
|
const packageJsonPath = join(__dirname, "..", "package.json");
|
|
@@ -182,13 +182,6 @@ program
|
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
});
|
|
185
|
-
// ccm config (deprecated, kept for compatibility)
|
|
186
|
-
program
|
|
187
|
-
.command("config")
|
|
188
|
-
.description(t("config.description"))
|
|
189
|
-
.action(async () => {
|
|
190
|
-
console.log(chalk.gray("ccm now only uses standalone mode. No configuration needed."));
|
|
191
|
-
});
|
|
192
185
|
// ccm sync
|
|
193
186
|
program
|
|
194
187
|
.command("sync")
|
|
@@ -246,6 +239,50 @@ program
|
|
|
246
239
|
}
|
|
247
240
|
console.log(chalk.green(t("clear.done")));
|
|
248
241
|
});
|
|
242
|
+
// ccm import
|
|
243
|
+
program
|
|
244
|
+
.command("import [file]")
|
|
245
|
+
.description(t("import.description"))
|
|
246
|
+
.action(async (file) => {
|
|
247
|
+
const store = ensureStore();
|
|
248
|
+
let jsonContent;
|
|
249
|
+
if (file) {
|
|
250
|
+
// Read from file
|
|
251
|
+
if (!existsSync(file)) {
|
|
252
|
+
console.log(chalk.red(t("import.file_not_found", { file })));
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
jsonContent = readFileSync(file, "utf-8");
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
// Read from stdin
|
|
259
|
+
console.log(chalk.gray(t("import.paste_hint")));
|
|
260
|
+
const chunks = [];
|
|
261
|
+
process.stdin.setEncoding("utf-8");
|
|
262
|
+
for await (const chunk of process.stdin) {
|
|
263
|
+
chunks.push(Buffer.from(chunk));
|
|
264
|
+
}
|
|
265
|
+
jsonContent = Buffer.concat(chunks).toString("utf-8");
|
|
266
|
+
}
|
|
267
|
+
let configs;
|
|
268
|
+
try {
|
|
269
|
+
configs = JSON.parse(jsonContent);
|
|
270
|
+
}
|
|
271
|
+
catch {
|
|
272
|
+
console.log(chalk.red(t("import.json_parse_error")));
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
if (typeof configs !== "object" || configs === null || Object.keys(configs).length === 0) {
|
|
276
|
+
console.log(chalk.red(t("import.invalid_format")));
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
let count = 0;
|
|
280
|
+
for (const [name, settingsConfig] of Object.entries(configs)) {
|
|
281
|
+
store.save(name, settingsConfig);
|
|
282
|
+
count++;
|
|
283
|
+
}
|
|
284
|
+
console.log(chalk.green(t("import.done", { count: String(count) })));
|
|
285
|
+
});
|
|
249
286
|
// ccm list
|
|
250
287
|
program
|
|
251
288
|
.command("list")
|
|
@@ -517,19 +554,26 @@ program
|
|
|
517
554
|
}
|
|
518
555
|
await saveAndSwitch(store, name, settingsConfig);
|
|
519
556
|
});
|
|
520
|
-
// ccm show
|
|
557
|
+
// ccm show [name]
|
|
521
558
|
program
|
|
522
559
|
.command("show [name]")
|
|
523
560
|
.description(t("show.description"))
|
|
524
561
|
.action(async (name) => {
|
|
525
562
|
const store = ensureStore();
|
|
526
563
|
if (!name) {
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
564
|
+
// Show all configurations
|
|
565
|
+
const profiles = store.list();
|
|
566
|
+
if (profiles.length === 0) {
|
|
567
|
+
console.log(chalk.yellow(t("list.empty")));
|
|
530
568
|
return;
|
|
531
569
|
}
|
|
532
|
-
|
|
570
|
+
console.log(chalk.bold(`\n${t("show.all_header")}\n`));
|
|
571
|
+
const allConfigs = {};
|
|
572
|
+
for (const profile of profiles) {
|
|
573
|
+
allConfigs[profile.name] = profile.settingsConfig;
|
|
574
|
+
}
|
|
575
|
+
console.log(JSON.stringify(allConfigs, null, 2));
|
|
576
|
+
return;
|
|
533
577
|
}
|
|
534
578
|
const profile = await resolveProfile(store, name);
|
|
535
579
|
if (!profile)
|
|
@@ -865,7 +909,7 @@ localeCmd
|
|
|
865
909
|
.description(t("locale.list_description"))
|
|
866
910
|
.action(async () => {
|
|
867
911
|
const rc = readRc();
|
|
868
|
-
const current = rc?.locale ||
|
|
912
|
+
const current = rc?.locale || getLocale();
|
|
869
913
|
const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
|
|
870
914
|
if (isInteractive) {
|
|
871
915
|
const options = SUPPORTED_LOCALES.map(({ code, label }) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@daylenjeez/ccm-switch",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Claude Code Model Switcher - 快速切换 Claude Code 自定义模型配置",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@clack/prompts": "^1.2.0",
|
|
27
|
+
"@daylenjeez/ccm-switch": "^1.2.9",
|
|
27
28
|
"better-sqlite3": "^12.8.0",
|
|
28
29
|
"chalk": "^5.6.2",
|
|
29
30
|
"commander": "^14.0.3"
|
package/src/i18n/en.ts
CHANGED
|
@@ -25,9 +25,6 @@ const en: Record<TranslationKey, string> = {
|
|
|
25
25
|
"init.cc_switch_found":"cc-switch detected. Import configurations from it? (Y/n) ",
|
|
26
26
|
"init.done": "✓ Initialized",
|
|
27
27
|
|
|
28
|
-
// config
|
|
29
|
-
"config.description": "View data source mode (deprecated)",
|
|
30
|
-
|
|
31
28
|
// list
|
|
32
29
|
"list.description": "List and select configurations",
|
|
33
30
|
"list.empty": "No configurations yet. Use ccm save <name> to save current config",
|
|
@@ -56,6 +53,7 @@ const en: Record<TranslationKey, string> = {
|
|
|
56
53
|
// show
|
|
57
54
|
"show.description": "View configuration details (defaults to current)",
|
|
58
55
|
"show.no_current": "No active configuration. Specify a name: ccm show <name>",
|
|
56
|
+
"show.all_header": "All configurations:",
|
|
59
57
|
|
|
60
58
|
// remove
|
|
61
59
|
"remove.description": "Delete a configuration",
|
|
@@ -143,6 +141,14 @@ const en: Record<TranslationKey, string> = {
|
|
|
143
141
|
"clear.removed": "✓ Deleted {path}",
|
|
144
142
|
"clear.done": "✓ Cleanup complete",
|
|
145
143
|
|
|
144
|
+
// import
|
|
145
|
+
"import.description": "Import configurations from JSON (file or stdin)",
|
|
146
|
+
"import.paste_hint": "Paste JSON and press Ctrl+D (or Ctrl+Z on Windows) to finish:",
|
|
147
|
+
"import.file_not_found": 'File not found: {file}',
|
|
148
|
+
"import.json_parse_error": "Invalid JSON format",
|
|
149
|
+
"import.invalid_format": "Invalid format: expected object with configuration names as keys",
|
|
150
|
+
"import.done": "✓ Imported {count} configurations",
|
|
151
|
+
|
|
146
152
|
// store errors
|
|
147
153
|
"store.db_not_found": "cc-switch database not found: {path}",
|
|
148
154
|
};
|
package/src/i18n/index.ts
CHANGED
package/src/i18n/zh.ts
CHANGED
|
@@ -23,9 +23,6 @@ const zh = {
|
|
|
23
23
|
"init.cc_switch_found":"检测到 cc-switch 已安装,是否从中导入配置?(Y/n) ",
|
|
24
24
|
"init.done": "✓ 初始化完成",
|
|
25
25
|
|
|
26
|
-
// config
|
|
27
|
-
"config.description": "查看数据源模式(已废弃)",
|
|
28
|
-
|
|
29
26
|
// list
|
|
30
27
|
"list.description": "列出并选择配置方案",
|
|
31
28
|
"list.empty": "暂无配置方案。使用 ccm save <name> 保存当前配置",
|
|
@@ -54,6 +51,7 @@ const zh = {
|
|
|
54
51
|
// show
|
|
55
52
|
"show.description": "查看配置详情(不指定则显示当前)",
|
|
56
53
|
"show.no_current": "当前无激活配置,请指定名称: ccm show <name>",
|
|
54
|
+
"show.all_header": "所有配置:",
|
|
57
55
|
|
|
58
56
|
// remove
|
|
59
57
|
"remove.description": "删除配置方案",
|
|
@@ -141,6 +139,14 @@ const zh = {
|
|
|
141
139
|
"clear.removed": "✓ 已删除 {path}",
|
|
142
140
|
"clear.done": "✓ 清理完成",
|
|
143
141
|
|
|
142
|
+
// import
|
|
143
|
+
"import.description": "从 JSON 导入配置(文件或粘贴)",
|
|
144
|
+
"import.paste_hint": "粘贴 JSON,按 Ctrl+D(或 Windows 的 Ctrl+Z)结束:",
|
|
145
|
+
"import.file_not_found": '文件不存在: {file}',
|
|
146
|
+
"import.json_parse_error": "JSON 格式无效",
|
|
147
|
+
"import.invalid_format": "格式错误: 应为以配置名称为键的对象",
|
|
148
|
+
"import.done": "✓ 已导入 {count} 个配置",
|
|
149
|
+
|
|
144
150
|
// store errors
|
|
145
151
|
"store.db_not_found": "cc-switch 数据库不存在: {path}",
|
|
146
152
|
} as const;
|
package/src/index.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { writeFileSync, readFileSync, unlinkSync, existsSync } from "fs";
|
|
|
11
11
|
import { tmpdir, homedir } from "os";
|
|
12
12
|
import { join, dirname } from "path";
|
|
13
13
|
import { fileURLToPath } from "url";
|
|
14
|
-
import { t, setLocale } from "./i18n/index.js";
|
|
14
|
+
import { t, setLocale, getLocale } from "./i18n/index.js";
|
|
15
15
|
import * as clack from "@clack/prompts";
|
|
16
16
|
|
|
17
17
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -204,14 +204,6 @@ program
|
|
|
204
204
|
}
|
|
205
205
|
});
|
|
206
206
|
|
|
207
|
-
// ccm config (deprecated, kept for compatibility)
|
|
208
|
-
program
|
|
209
|
-
.command("config")
|
|
210
|
-
.description(t("config.description"))
|
|
211
|
-
.action(async () => {
|
|
212
|
-
console.log(chalk.gray("ccm now only uses standalone mode. No configuration needed."));
|
|
213
|
-
});
|
|
214
|
-
|
|
215
207
|
// ccm sync
|
|
216
208
|
program
|
|
217
209
|
.command("sync")
|
|
@@ -278,6 +270,54 @@ program
|
|
|
278
270
|
console.log(chalk.green(t("clear.done")));
|
|
279
271
|
});
|
|
280
272
|
|
|
273
|
+
// ccm import
|
|
274
|
+
program
|
|
275
|
+
.command("import [file]")
|
|
276
|
+
.description(t("import.description"))
|
|
277
|
+
.action(async (file?: string) => {
|
|
278
|
+
const store = ensureStore();
|
|
279
|
+
|
|
280
|
+
let jsonContent: string;
|
|
281
|
+
if (file) {
|
|
282
|
+
// Read from file
|
|
283
|
+
if (!existsSync(file)) {
|
|
284
|
+
console.log(chalk.red(t("import.file_not_found", { file })));
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
jsonContent = readFileSync(file, "utf-8");
|
|
288
|
+
} else {
|
|
289
|
+
// Read from stdin
|
|
290
|
+
console.log(chalk.gray(t("import.paste_hint")));
|
|
291
|
+
const chunks: Buffer[] = [];
|
|
292
|
+
process.stdin.setEncoding("utf-8");
|
|
293
|
+
for await (const chunk of process.stdin) {
|
|
294
|
+
chunks.push(Buffer.from(chunk));
|
|
295
|
+
}
|
|
296
|
+
jsonContent = Buffer.concat(chunks).toString("utf-8");
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
let configs: Record<string, Record<string, unknown>>;
|
|
300
|
+
try {
|
|
301
|
+
configs = JSON.parse(jsonContent);
|
|
302
|
+
} catch {
|
|
303
|
+
console.log(chalk.red(t("import.json_parse_error")));
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (typeof configs !== "object" || configs === null || Object.keys(configs).length === 0) {
|
|
308
|
+
console.log(chalk.red(t("import.invalid_format")));
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
let count = 0;
|
|
313
|
+
for (const [name, settingsConfig] of Object.entries(configs)) {
|
|
314
|
+
store.save(name, settingsConfig);
|
|
315
|
+
count++;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
console.log(chalk.green(t("import.done", { count: String(count) })));
|
|
319
|
+
});
|
|
320
|
+
|
|
281
321
|
// ccm list
|
|
282
322
|
program
|
|
283
323
|
.command("list")
|
|
@@ -576,7 +616,7 @@ program
|
|
|
576
616
|
await saveAndSwitch(store, name, settingsConfig);
|
|
577
617
|
});
|
|
578
618
|
|
|
579
|
-
// ccm show
|
|
619
|
+
// ccm show [name]
|
|
580
620
|
program
|
|
581
621
|
.command("show [name]")
|
|
582
622
|
.description(t("show.description"))
|
|
@@ -584,12 +624,20 @@ program
|
|
|
584
624
|
const store = ensureStore();
|
|
585
625
|
|
|
586
626
|
if (!name) {
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
627
|
+
// Show all configurations
|
|
628
|
+
const profiles = store.list();
|
|
629
|
+
if (profiles.length === 0) {
|
|
630
|
+
console.log(chalk.yellow(t("list.empty")));
|
|
590
631
|
return;
|
|
591
632
|
}
|
|
592
|
-
|
|
633
|
+
|
|
634
|
+
console.log(chalk.bold(`\n${t("show.all_header")}\n`));
|
|
635
|
+
const allConfigs: Record<string, Record<string, unknown>> = {};
|
|
636
|
+
for (const profile of profiles) {
|
|
637
|
+
allConfigs[profile.name] = profile.settingsConfig;
|
|
638
|
+
}
|
|
639
|
+
console.log(JSON.stringify(allConfigs, null, 2));
|
|
640
|
+
return;
|
|
593
641
|
}
|
|
594
642
|
|
|
595
643
|
const profile = await resolveProfile(store, name);
|
|
@@ -956,7 +1004,7 @@ localeCmd
|
|
|
956
1004
|
.description(t("locale.list_description"))
|
|
957
1005
|
.action(async () => {
|
|
958
1006
|
const rc = readRc();
|
|
959
|
-
const current = rc?.locale ||
|
|
1007
|
+
const current = rc?.locale || getLocale();
|
|
960
1008
|
const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
|
|
961
1009
|
|
|
962
1010
|
if (isInteractive) {
|