@double_seven/swpm 1.0.2
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 +21 -0
- package/README.ja.md +81 -0
- package/README.ko.md +81 -0
- package/README.md +81 -0
- package/README.zh-CN.md +81 -0
- package/README.zh-TW.md +81 -0
- package/dist/commands/export.d.ts +1 -0
- package/dist/commands/export.js +59 -0
- package/dist/commands/install.d.ts +1 -0
- package/dist/commands/install.js +20 -0
- package/dist/commands/lang.d.ts +2 -0
- package/dist/commands/lang.js +82 -0
- package/dist/commands/list.d.ts +1 -0
- package/dist/commands/list.js +26 -0
- package/dist/commands/search.d.ts +1 -0
- package/dist/commands/search.js +26 -0
- package/dist/commands/sync.d.ts +1 -0
- package/dist/commands/sync.js +70 -0
- package/dist/commands/uninstall.d.ts +1 -0
- package/dist/commands/uninstall.js +70 -0
- package/dist/commands/upgrade.d.ts +1 -0
- package/dist/commands/upgrade.js +106 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.js +37 -0
- package/dist/i18n/en.json +81 -0
- package/dist/i18n/index.d.ts +14 -0
- package/dist/i18n/index.js +57 -0
- package/dist/i18n/ja.json +81 -0
- package/dist/i18n/ko.json +81 -0
- package/dist/i18n/zh-CN.json +81 -0
- package/dist/i18n/zh-TW.json +81 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +88 -0
- package/dist/types.d.ts +20 -0
- package/dist/types.js +2 -0
- package/dist/ui/selector.d.ts +4 -0
- package/dist/ui/selector.js +86 -0
- package/dist/ui/spinner.d.ts +8 -0
- package/dist/ui/spinner.js +26 -0
- package/dist/ui/table.d.ts +2 -0
- package/dist/ui/table.js +31 -0
- package/dist/winget/client.d.ts +13 -0
- package/dist/winget/client.js +94 -0
- package/dist/winget/parser.d.ts +4 -0
- package/dist/winget/parser.js +303 -0
- package/package.json +61 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "简体中文",
|
|
3
|
+
"nativeName": "简体中文",
|
|
4
|
+
"list.description": "列出已安装的软件",
|
|
5
|
+
"search.description": "搜索软件包",
|
|
6
|
+
"install.description": "安装软件(使用软件包 ID)",
|
|
7
|
+
"uninstall.description": "卸载软件。无参数时进入交互模式,可勾选要卸载的软件",
|
|
8
|
+
"upgrade.description": "升级软件。无参数时进入交互模式,可勾选要升级的软件",
|
|
9
|
+
"export.description": "导出已安装的 winget 软件列表为 YAML 文件(默认 ./swpm-packages.yaml)",
|
|
10
|
+
"sync.description": "根据 YAML 配置文件同步软件(安装缺失的包)",
|
|
11
|
+
"lang.description": "切换显示语言",
|
|
12
|
+
"upgrade.all": "升级所有可升级的软件",
|
|
13
|
+
"examples": "示例",
|
|
14
|
+
"examples.list": "列出已安装软件",
|
|
15
|
+
"examples.search": "搜索软件",
|
|
16
|
+
"examples.install": "安装软件",
|
|
17
|
+
"examples.uninstall": "卸载软件",
|
|
18
|
+
"examples.upgrade": "交互式选择升级",
|
|
19
|
+
"examples.upgradeAll": "一键升级全部",
|
|
20
|
+
"examples.upgradeOne": "升级指定软件",
|
|
21
|
+
"examples.export": "导出已安装软件列表",
|
|
22
|
+
"examples.exportPath": "导出到指定路径",
|
|
23
|
+
"examples.sync": "同步安装缺失的软件",
|
|
24
|
+
"examples.lang": "切换语言",
|
|
25
|
+
"winget.tip": "提示:winget 功能异常时,可在 PowerShell 中运行以下命令修复",
|
|
26
|
+
"install.installing": "安装",
|
|
27
|
+
"install.success": "安装完成",
|
|
28
|
+
"install.fail": "安装失败",
|
|
29
|
+
"uninstall.uninstalling": "卸载",
|
|
30
|
+
"uninstall.success": "卸载完成",
|
|
31
|
+
"uninstall.fail": "卸载失败",
|
|
32
|
+
"upgrade.upgrading": "升级",
|
|
33
|
+
"upgrade.success": "升级完成",
|
|
34
|
+
"upgrade.fail": "升级失败",
|
|
35
|
+
"upgrade.checking": "正在检查可用更新...",
|
|
36
|
+
"upgrade.allUpToDate": "所有软件已是最新版本!",
|
|
37
|
+
"upgrade.select": "选择要升级的软件(空格切换,回车确认)",
|
|
38
|
+
"upgrade.starting": "开始升级 {0} 个软件...",
|
|
39
|
+
"upgrade.summary": "升级汇总",
|
|
40
|
+
"upgrade.successCount": "成功",
|
|
41
|
+
"upgrade.failCount": "失败",
|
|
42
|
+
"upgrade.cancelled": "已取消。",
|
|
43
|
+
"upgrade.noSelection": "未选择任何软件,已取消。",
|
|
44
|
+
"export.getting": "正在获取已安装的软件...",
|
|
45
|
+
"export.fail": "获取软件列表失败",
|
|
46
|
+
"export.resolving": "正在解析 {0} 个被截断的 ID...",
|
|
47
|
+
"export.exported": "已导出 {0} 个软件到 {1}",
|
|
48
|
+
"export.cancelled": "已取消。",
|
|
49
|
+
"export.noSelection": "未选择任何软件,已取消。",
|
|
50
|
+
"export.noPackages": "没有可导出的软件。",
|
|
51
|
+
"export.select": "选择要导出的软件(空格切换,回车确认)",
|
|
52
|
+
"sync.reading": "正在读取配置文件...",
|
|
53
|
+
"sync.configNotFound": "配置文件不存在:{0}",
|
|
54
|
+
"sync.configParseFail": "读取配置文件失败:{0}",
|
|
55
|
+
"sync.noPackages": "配置文件中没有 packages 列表",
|
|
56
|
+
"sync.getting": "正在获取已安装的软件...",
|
|
57
|
+
"sync.fail": "获取软件列表失败",
|
|
58
|
+
"sync.allInstalled": "所有软件已安装!",
|
|
59
|
+
"sync.starting": "共 {0} 个目标,缺失 {1} 个,开始安装...",
|
|
60
|
+
"sync.summary": "同步汇总",
|
|
61
|
+
"sync.successCount": "成功",
|
|
62
|
+
"sync.failCount": "失败",
|
|
63
|
+
"search.searching": "正在搜索 \"{0}\"...",
|
|
64
|
+
"search.results": "搜索 \"{0}\" 结果(共 {1} 个)",
|
|
65
|
+
"search.fail": "搜索失败",
|
|
66
|
+
"list.getting": "正在获取已安装的软件...",
|
|
67
|
+
"list.fail": "获取软件列表失败",
|
|
68
|
+
"lang.prompt": "选择语言",
|
|
69
|
+
"lang.current": "当前语言",
|
|
70
|
+
"lang.switched": "语言已切换为:{0} ({1})",
|
|
71
|
+
"lang.firstRun": "欢迎使用 swpm!请选择语言:",
|
|
72
|
+
"executing": "执行",
|
|
73
|
+
"exitCode": "退出码",
|
|
74
|
+
"signal": "信号",
|
|
75
|
+
"launchFail": "无法启动 winget",
|
|
76
|
+
"uninstall.getting": "正在获取已安装的软件...",
|
|
77
|
+
"uninstall.starting": "开始卸载 {0} 个软件...",
|
|
78
|
+
"uninstall.summary": "卸载汇总",
|
|
79
|
+
"uninstall.noPackages": "没有可卸载的软件。",
|
|
80
|
+
"uninstall.select": "选择要卸载的软件(空格切换,回车确认)"
|
|
81
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "繁體中文",
|
|
3
|
+
"nativeName": "繁體中文",
|
|
4
|
+
"list.description": "列出已安裝的軟體",
|
|
5
|
+
"search.description": "搜尋軟體套件",
|
|
6
|
+
"install.description": "安裝軟體(使用軟體套件 ID)",
|
|
7
|
+
"uninstall.description": "解除安裝軟體。無參數時進入互動模式,可勾選要解除安裝的軟體",
|
|
8
|
+
"upgrade.description": "升級軟體。無參數時進入互動模式,可勾選要升級的軟體",
|
|
9
|
+
"export.description": "匯出已安裝的 winget 軟體列表為 YAML 檔案(預設 ./swpm-packages.yaml)",
|
|
10
|
+
"sync.description": "根據 YAML 設定檔同步軟體(安裝缺少的套件)",
|
|
11
|
+
"lang.description": "切換顯示語言",
|
|
12
|
+
"upgrade.all": "升級所有可升級的軟體",
|
|
13
|
+
"examples": "範例",
|
|
14
|
+
"examples.list": "列出已安裝軟體",
|
|
15
|
+
"examples.search": "搜尋軟體",
|
|
16
|
+
"examples.install": "安裝軟體",
|
|
17
|
+
"examples.uninstall": "解除安裝軟體",
|
|
18
|
+
"examples.upgrade": "互動式勾選升級",
|
|
19
|
+
"examples.upgradeAll": "一鍵升級全部",
|
|
20
|
+
"examples.upgradeOne": "升級指定軟體",
|
|
21
|
+
"examples.export": "匯出已安裝軟體列表",
|
|
22
|
+
"examples.exportPath": "匯出到指定路徑",
|
|
23
|
+
"examples.sync": "同步安裝缺少的軟體",
|
|
24
|
+
"examples.lang": "切換語言",
|
|
25
|
+
"winget.tip": "提示:winget 功能異常時,可在 PowerShell 中執行以下命令修復",
|
|
26
|
+
"install.installing": "安裝",
|
|
27
|
+
"install.success": "安裝完成",
|
|
28
|
+
"install.fail": "安裝失敗",
|
|
29
|
+
"uninstall.uninstalling": "解除安裝",
|
|
30
|
+
"uninstall.success": "解除安裝完成",
|
|
31
|
+
"uninstall.fail": "解除安裝失敗",
|
|
32
|
+
"upgrade.upgrading": "升級",
|
|
33
|
+
"upgrade.success": "升級完成",
|
|
34
|
+
"upgrade.fail": "升級失敗",
|
|
35
|
+
"upgrade.checking": "正在檢查可用更新...",
|
|
36
|
+
"upgrade.allUpToDate": "所有軟體已是最新版本!",
|
|
37
|
+
"upgrade.select": "選擇要升級的軟體(空白鍵切換,Enter 確認)",
|
|
38
|
+
"upgrade.starting": "開始升級 {0} 個軟體...",
|
|
39
|
+
"upgrade.summary": "升級彙總",
|
|
40
|
+
"upgrade.successCount": "成功",
|
|
41
|
+
"upgrade.failCount": "失敗",
|
|
42
|
+
"upgrade.cancelled": "已取消。",
|
|
43
|
+
"upgrade.noSelection": "未選擇任何軟體,已取消。",
|
|
44
|
+
"export.getting": "正在取得已安裝的軟體...",
|
|
45
|
+
"export.fail": "取得軟體列表失敗",
|
|
46
|
+
"export.resolving": "正在解析 {0} 個被截斷的 ID...",
|
|
47
|
+
"export.exported": "已匯出 {0} 個軟體到 {1}",
|
|
48
|
+
"export.cancelled": "已取消。",
|
|
49
|
+
"export.noSelection": "未選擇任何軟體,已取消。",
|
|
50
|
+
"export.noPackages": "沒有可匯出的軟體。",
|
|
51
|
+
"export.select": "選擇要匯出的軟體(空白鍵切換,Enter 確認)",
|
|
52
|
+
"sync.reading": "正在讀取設定檔...",
|
|
53
|
+
"sync.configNotFound": "設定檔不存在:{0}",
|
|
54
|
+
"sync.configParseFail": "讀取設定檔失敗:{0}",
|
|
55
|
+
"sync.noPackages": "設定檔中沒有 packages 列表",
|
|
56
|
+
"sync.getting": "正在取得已安裝的軟體...",
|
|
57
|
+
"sync.fail": "取得軟體列表失敗",
|
|
58
|
+
"sync.allInstalled": "所有軟體已安裝!",
|
|
59
|
+
"sync.starting": "共 {0} 個目標,缺少 {1} 個,開始安裝...",
|
|
60
|
+
"sync.summary": "同步彙總",
|
|
61
|
+
"sync.successCount": "成功",
|
|
62
|
+
"sync.failCount": "失敗",
|
|
63
|
+
"search.searching": "正在搜尋 \"{0}\"...",
|
|
64
|
+
"search.results": "搜尋 \"{0}\" 結果(共 {1} 個)",
|
|
65
|
+
"search.fail": "搜尋失敗",
|
|
66
|
+
"list.getting": "正在取得已安裝的軟體...",
|
|
67
|
+
"list.fail": "取得軟體列表失敗",
|
|
68
|
+
"lang.prompt": "選擇語言",
|
|
69
|
+
"lang.current": "目前語言",
|
|
70
|
+
"lang.switched": "語言已切換為:{0} ({1})",
|
|
71
|
+
"lang.firstRun": "歡迎使用 swpm!請選擇語言:",
|
|
72
|
+
"executing": "執行",
|
|
73
|
+
"exitCode": "結束代碼",
|
|
74
|
+
"signal": "訊號",
|
|
75
|
+
"launchFail": "無法啟動 winget",
|
|
76
|
+
"uninstall.getting": "正在取得已安裝的軟體...",
|
|
77
|
+
"uninstall.starting": "開始解除安裝 {0} 個軟體...",
|
|
78
|
+
"uninstall.summary": "解除安裝彙總",
|
|
79
|
+
"uninstall.noPackages": "沒有可解除安裝的軟體。",
|
|
80
|
+
"uninstall.select": "選擇要解除安裝的軟體(空白鍵切換,Enter 確認)"
|
|
81
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const path_1 = require("path");
|
|
9
|
+
const commander_1 = require("commander");
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const list_1 = require("./commands/list");
|
|
12
|
+
const search_1 = require("./commands/search");
|
|
13
|
+
const install_1 = require("./commands/install");
|
|
14
|
+
const uninstall_1 = require("./commands/uninstall");
|
|
15
|
+
const upgrade_1 = require("./commands/upgrade");
|
|
16
|
+
const export_1 = require("./commands/export");
|
|
17
|
+
const sync_1 = require("./commands/sync");
|
|
18
|
+
const lang_1 = require("./commands/lang");
|
|
19
|
+
const i18n_1 = require("./i18n");
|
|
20
|
+
const pkg = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, "..", "package.json"), "utf-8"));
|
|
21
|
+
async function main() {
|
|
22
|
+
const isHelp = process.argv.slice(2).length === 0;
|
|
23
|
+
await (0, lang_1.initLang)(isHelp);
|
|
24
|
+
const program = new commander_1.Command();
|
|
25
|
+
program
|
|
26
|
+
.name("swpm")
|
|
27
|
+
.description("A winget-based Windows software package manager")
|
|
28
|
+
.version(pkg.version);
|
|
29
|
+
program
|
|
30
|
+
.command("list")
|
|
31
|
+
.alias("ls")
|
|
32
|
+
.description((0, i18n_1.t)("list.description"))
|
|
33
|
+
.action(() => (0, list_1.listCommand)());
|
|
34
|
+
program
|
|
35
|
+
.command("search <keyword>")
|
|
36
|
+
.alias("find")
|
|
37
|
+
.description((0, i18n_1.t)("search.description"))
|
|
38
|
+
.action((keyword) => (0, search_1.searchCommand)(keyword));
|
|
39
|
+
program
|
|
40
|
+
.command("install <id>")
|
|
41
|
+
.alias("i")
|
|
42
|
+
.description((0, i18n_1.t)("install.description"))
|
|
43
|
+
.action((id) => (0, install_1.installCommand)(id));
|
|
44
|
+
program
|
|
45
|
+
.command("uninstall [id]")
|
|
46
|
+
.alias("rm")
|
|
47
|
+
.description((0, i18n_1.t)("uninstall.description"))
|
|
48
|
+
.action((id) => (0, uninstall_1.uninstallCommand)(id));
|
|
49
|
+
program
|
|
50
|
+
.command("upgrade [id]")
|
|
51
|
+
.alias("up")
|
|
52
|
+
.description((0, i18n_1.t)("upgrade.description"))
|
|
53
|
+
.option("-a, --all", (0, i18n_1.t)("upgrade.all"))
|
|
54
|
+
.action((id, options) => (0, upgrade_1.upgradeCommand)(id, options.all ?? false));
|
|
55
|
+
program
|
|
56
|
+
.command("export [path]")
|
|
57
|
+
.description((0, i18n_1.t)("export.description"))
|
|
58
|
+
.action((path) => (0, export_1.exportCommand)(path));
|
|
59
|
+
program
|
|
60
|
+
.command("sync <path>")
|
|
61
|
+
.description((0, i18n_1.t)("sync.description"))
|
|
62
|
+
.action((path) => (0, sync_1.syncCommand)(path));
|
|
63
|
+
program
|
|
64
|
+
.command("lang")
|
|
65
|
+
.description((0, i18n_1.t)("lang.description"))
|
|
66
|
+
.action(() => (0, lang_1.langCommand)());
|
|
67
|
+
if (isHelp) {
|
|
68
|
+
program.addHelpText("after", `
|
|
69
|
+
${chalk_1.default.gray((0, i18n_1.t)("examples"))}:
|
|
70
|
+
${chalk_1.default.cyan("swpm list")} ${(0, i18n_1.t)("examples.list")}
|
|
71
|
+
${chalk_1.default.cyan("swpm search vscode")} ${(0, i18n_1.t)("examples.search")}
|
|
72
|
+
${chalk_1.default.cyan("swpm install Microsoft.VisualStudioCode")} ${(0, i18n_1.t)("examples.install")}
|
|
73
|
+
${chalk_1.default.cyan("swpm uninstall Microsoft.VisualStudioCode")} ${(0, i18n_1.t)("examples.uninstall")}
|
|
74
|
+
${chalk_1.default.cyan("swpm upgrade")} ${(0, i18n_1.t)("examples.upgrade")}
|
|
75
|
+
${chalk_1.default.cyan("swpm upgrade --all")} ${(0, i18n_1.t)("examples.upgradeAll")}
|
|
76
|
+
${chalk_1.default.cyan("swpm upgrade 7zip.7zip")} ${(0, i18n_1.t)("examples.upgradeOne")}
|
|
77
|
+
${chalk_1.default.cyan("swpm export")} ${(0, i18n_1.t)("examples.export")}
|
|
78
|
+
${chalk_1.default.cyan("swpm export ./my-packages.yaml")} ${(0, i18n_1.t)("examples.exportPath")}
|
|
79
|
+
${chalk_1.default.cyan("swpm sync ./my-packages.yaml")} ${(0, i18n_1.t)("examples.sync")}
|
|
80
|
+
${chalk_1.default.cyan("swpm lang")} ${(0, i18n_1.t)("examples.lang")}
|
|
81
|
+
|
|
82
|
+
${chalk_1.default.gray((0, i18n_1.t)("winget.tip"))}:
|
|
83
|
+
${chalk_1.default.yellow("Get-AppxPackage -AllUsers *DesktopAppInstaller* | Reset-AppxPackage")}
|
|
84
|
+
`);
|
|
85
|
+
}
|
|
86
|
+
program.parse();
|
|
87
|
+
}
|
|
88
|
+
main();
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface PackageInfo {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
version: string;
|
|
5
|
+
available?: string;
|
|
6
|
+
source: string;
|
|
7
|
+
}
|
|
8
|
+
export interface UpgradeResult {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
oldVersion: string;
|
|
12
|
+
newVersion: string;
|
|
13
|
+
success: boolean;
|
|
14
|
+
error?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface CommandResult<T> {
|
|
17
|
+
success: boolean;
|
|
18
|
+
data: T;
|
|
19
|
+
error?: string;
|
|
20
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { PackageInfo } from "../types";
|
|
2
|
+
export declare function selectPackages(upgrades: PackageInfo[]): Promise<PackageInfo[]>;
|
|
3
|
+
export declare function selectExportPackages(packages: PackageInfo[]): Promise<PackageInfo[]>;
|
|
4
|
+
export declare function selectUninstallPackages(packages: PackageInfo[]): Promise<PackageInfo[]>;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.selectPackages = selectPackages;
|
|
7
|
+
exports.selectExportPackages = selectExportPackages;
|
|
8
|
+
exports.selectUninstallPackages = selectUninstallPackages;
|
|
9
|
+
const prompts_1 = require("@inquirer/prompts");
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const i18n_1 = require("../i18n");
|
|
12
|
+
const theme = {
|
|
13
|
+
icon: {
|
|
14
|
+
checked: chalk_1.default.green("✓"),
|
|
15
|
+
unchecked: " ",
|
|
16
|
+
cursor: chalk_1.default.cyan("❯"),
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
async function selectPackages(upgrades) {
|
|
20
|
+
if (upgrades.length === 0) {
|
|
21
|
+
console.log(chalk_1.default.green((0, i18n_1.t)("upgrade.allUpToDate")));
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
const choices = upgrades.map((pkg) => ({
|
|
25
|
+
name: `${chalk_1.default.bold(pkg.name)} ${chalk_1.default.gray(pkg.version)} → ${chalk_1.default.green(pkg.available || "?")} [${chalk_1.default.cyan(pkg.id)}]`,
|
|
26
|
+
value: pkg,
|
|
27
|
+
checked: true,
|
|
28
|
+
}));
|
|
29
|
+
return (0, prompts_1.checkbox)({
|
|
30
|
+
message: `${(0, i18n_1.t)("upgrade.select")}`,
|
|
31
|
+
choices: [
|
|
32
|
+
new prompts_1.Separator(chalk_1.default.gray("-".repeat(60))),
|
|
33
|
+
...choices,
|
|
34
|
+
new prompts_1.Separator(chalk_1.default.gray("-".repeat(60))),
|
|
35
|
+
],
|
|
36
|
+
pageSize: 15,
|
|
37
|
+
theme,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
async function selectExportPackages(packages) {
|
|
41
|
+
if (packages.length === 0) {
|
|
42
|
+
console.log(chalk_1.default.gray((0, i18n_1.t)("export.noPackages")));
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
const choices = packages.map((pkg) => {
|
|
46
|
+
const isMs = pkg.id.startsWith("Microsoft.");
|
|
47
|
+
const isVs = pkg.id.startsWith("Microsoft.VisualStudio") || pkg.id.startsWith("Microsoft.VisualStudioCode");
|
|
48
|
+
const defaultChecked = !isMs || isVs;
|
|
49
|
+
return {
|
|
50
|
+
name: `${chalk_1.default.bold(pkg.name)} ${chalk_1.default.gray("[" + pkg.id + "]")}`,
|
|
51
|
+
value: pkg,
|
|
52
|
+
checked: defaultChecked,
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
return (0, prompts_1.checkbox)({
|
|
56
|
+
message: (0, i18n_1.t)("export.select"),
|
|
57
|
+
choices: [
|
|
58
|
+
new prompts_1.Separator(chalk_1.default.gray("-".repeat(60))),
|
|
59
|
+
...choices,
|
|
60
|
+
new prompts_1.Separator(chalk_1.default.gray("-".repeat(60))),
|
|
61
|
+
],
|
|
62
|
+
pageSize: 15,
|
|
63
|
+
theme,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
async function selectUninstallPackages(packages) {
|
|
67
|
+
if (packages.length === 0) {
|
|
68
|
+
console.log(chalk_1.default.gray((0, i18n_1.t)("uninstall.noPackages")));
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
const choices = packages.map((pkg) => ({
|
|
72
|
+
name: `${chalk_1.default.bold(pkg.name)} ${chalk_1.default.gray("[" + pkg.id + "]")}`,
|
|
73
|
+
value: pkg,
|
|
74
|
+
checked: false,
|
|
75
|
+
}));
|
|
76
|
+
return (0, prompts_1.checkbox)({
|
|
77
|
+
message: (0, i18n_1.t)("uninstall.select"),
|
|
78
|
+
choices: [
|
|
79
|
+
new prompts_1.Separator(chalk_1.default.gray("-".repeat(60))),
|
|
80
|
+
...choices,
|
|
81
|
+
new prompts_1.Separator(chalk_1.default.gray("-".repeat(60))),
|
|
82
|
+
],
|
|
83
|
+
pageSize: 15,
|
|
84
|
+
theme,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.spinner = exports.Spinner = void 0;
|
|
4
|
+
class Spinner {
|
|
5
|
+
interval = null;
|
|
6
|
+
frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
7
|
+
frameIndex = 0;
|
|
8
|
+
start(message) {
|
|
9
|
+
this.stop();
|
|
10
|
+
process.stdout.write("\x1B[?25l"); // hide cursor
|
|
11
|
+
this.interval = setInterval(() => {
|
|
12
|
+
process.stdout.write(`\r\x1B[K${this.frames[this.frameIndex]} ${message}`);
|
|
13
|
+
this.frameIndex = (this.frameIndex + 1) % this.frames.length;
|
|
14
|
+
}, 80);
|
|
15
|
+
}
|
|
16
|
+
stop() {
|
|
17
|
+
if (this.interval) {
|
|
18
|
+
clearInterval(this.interval);
|
|
19
|
+
this.interval = null;
|
|
20
|
+
process.stdout.write("\r\x1B[K"); // clear line
|
|
21
|
+
process.stdout.write("\x1B[?25h"); // show cursor
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.Spinner = Spinner;
|
|
26
|
+
exports.spinner = new Spinner();
|
package/dist/ui/table.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.renderPackageTable = renderPackageTable;
|
|
7
|
+
const cli_table3_1 = __importDefault(require("cli-table3"));
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
function renderPackageTable(packages, showAvailable = true) {
|
|
10
|
+
if (packages.length === 0) {
|
|
11
|
+
return chalk_1.default.gray(" No matching packages found.");
|
|
12
|
+
}
|
|
13
|
+
const head = [chalk_1.default.bold("Name"), chalk_1.default.bold("ID"), chalk_1.default.bold("Version")];
|
|
14
|
+
if (showAvailable) {
|
|
15
|
+
head.push(chalk_1.default.bold("Available"));
|
|
16
|
+
}
|
|
17
|
+
const table = new cli_table3_1.default({
|
|
18
|
+
head,
|
|
19
|
+
colWidths: showAvailable ? [25, 40, 18, 18] : [30, 45, 20],
|
|
20
|
+
wordWrap: true,
|
|
21
|
+
style: { head: [], border: [] },
|
|
22
|
+
});
|
|
23
|
+
for (const pkg of packages) {
|
|
24
|
+
const row = [pkg.name, chalk_1.default.cyan(pkg.id), pkg.version || "-"];
|
|
25
|
+
if (showAvailable) {
|
|
26
|
+
row.push(pkg.available ? chalk_1.default.green(pkg.available) : "-");
|
|
27
|
+
}
|
|
28
|
+
table.push(row);
|
|
29
|
+
}
|
|
30
|
+
return table.toString();
|
|
31
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PackageInfo } from "../types";
|
|
2
|
+
export declare function listInstalled(): PackageInfo[];
|
|
3
|
+
export declare function search(query: string): PackageInfo[];
|
|
4
|
+
export declare function getUpgrades(): PackageInfo[];
|
|
5
|
+
export declare function resolveTruncatedId(pkg: {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
version: string;
|
|
9
|
+
}): string;
|
|
10
|
+
export declare function install(id: string): Promise<void>;
|
|
11
|
+
export declare function uninstall(id: string): Promise<void>;
|
|
12
|
+
export declare function upgradePackage(pkg: Pick<PackageInfo, "id" | "name" | "version">): Promise<string>;
|
|
13
|
+
export declare function upgradeAll(): Promise<void>;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.listInstalled = listInstalled;
|
|
4
|
+
exports.search = search;
|
|
5
|
+
exports.getUpgrades = getUpgrades;
|
|
6
|
+
exports.resolveTruncatedId = resolveTruncatedId;
|
|
7
|
+
exports.install = install;
|
|
8
|
+
exports.uninstall = uninstall;
|
|
9
|
+
exports.upgradePackage = upgradePackage;
|
|
10
|
+
exports.upgradeAll = upgradeAll;
|
|
11
|
+
const child_process_1 = require("child_process");
|
|
12
|
+
const parser_1 = require("./parser");
|
|
13
|
+
const i18n_1 = require("../i18n");
|
|
14
|
+
const WINGET = "winget.exe";
|
|
15
|
+
function ensureWinget() {
|
|
16
|
+
const r = (0, child_process_1.spawnSync)(WINGET, ["--version"], { stdio: "pipe" });
|
|
17
|
+
if (r.status !== 0) {
|
|
18
|
+
throw new Error("winget not found. Please install App Installer (Windows 10 1809+ or Windows 11).");
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function execRead(args) {
|
|
22
|
+
ensureWinget();
|
|
23
|
+
const r = (0, child_process_1.spawnSync)(WINGET, args, {
|
|
24
|
+
encoding: "utf-8",
|
|
25
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
26
|
+
timeout: 120_000,
|
|
27
|
+
});
|
|
28
|
+
return (r.stdout || "").toString();
|
|
29
|
+
}
|
|
30
|
+
function execWrite(args) {
|
|
31
|
+
ensureWinget();
|
|
32
|
+
const cmd = `${WINGET} ${args.join(" ")}`;
|
|
33
|
+
console.log(`[swpm] ${(0, i18n_1.t)("executing")}: ${cmd}`);
|
|
34
|
+
return new Promise((resolve, reject) => {
|
|
35
|
+
const child = (0, child_process_1.spawn)(cmd, [], {
|
|
36
|
+
stdio: "inherit",
|
|
37
|
+
shell: "cmd.exe",
|
|
38
|
+
windowsHide: false,
|
|
39
|
+
});
|
|
40
|
+
child.on("close", (code, signal) => {
|
|
41
|
+
if (code === 0)
|
|
42
|
+
resolve();
|
|
43
|
+
else
|
|
44
|
+
reject(new Error(`winget ${(0, i18n_1.t)("exitCode")}: ${code}${signal ? ` (${(0, i18n_1.t)("signal")}: ${signal})` : ""}`));
|
|
45
|
+
});
|
|
46
|
+
child.on("error", (err) => reject(new Error(`${(0, i18n_1.t)("launchFail")}: ${err.message}`)));
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function listInstalled() {
|
|
50
|
+
return (0, parser_1.parseList)(execRead(["list"]));
|
|
51
|
+
}
|
|
52
|
+
function search(query) {
|
|
53
|
+
return (0, parser_1.parseSearch)(execRead(["search", query]));
|
|
54
|
+
}
|
|
55
|
+
function getUpgrades() {
|
|
56
|
+
return (0, parser_1.parseUpgrade)(execRead(["upgrade"]));
|
|
57
|
+
}
|
|
58
|
+
function resolveTruncatedId(pkg) {
|
|
59
|
+
const id = pkg.id;
|
|
60
|
+
if (!id.endsWith("…"))
|
|
61
|
+
return id;
|
|
62
|
+
const partial = id.slice(0, -1);
|
|
63
|
+
const results = (0, parser_1.parseSearch)(execRead(["search", partial]));
|
|
64
|
+
const verPrefix = pkg.version ? pkg.version.split(".").slice(0, 2).join(".") : "";
|
|
65
|
+
const best = results.find((r) => {
|
|
66
|
+
if (!r.id || !r.id.startsWith(partial))
|
|
67
|
+
return false;
|
|
68
|
+
if (verPrefix && r.version && r.version.startsWith(verPrefix))
|
|
69
|
+
return true;
|
|
70
|
+
return false;
|
|
71
|
+
});
|
|
72
|
+
if (best)
|
|
73
|
+
return best.id;
|
|
74
|
+
const exact = results.find((r) => r.id && r.id.startsWith(partial));
|
|
75
|
+
if (exact)
|
|
76
|
+
return exact.id;
|
|
77
|
+
return partial;
|
|
78
|
+
}
|
|
79
|
+
async function install(id) {
|
|
80
|
+
const resolvedId = resolveTruncatedId({ id, name: "", version: "" });
|
|
81
|
+
await execWrite(["install", "--id", resolvedId]);
|
|
82
|
+
}
|
|
83
|
+
async function uninstall(id) {
|
|
84
|
+
const resolvedId = resolveTruncatedId({ id, name: "", version: "" });
|
|
85
|
+
await execWrite(["uninstall", "--id", resolvedId]);
|
|
86
|
+
}
|
|
87
|
+
async function upgradePackage(pkg) {
|
|
88
|
+
const resolvedId = resolveTruncatedId(pkg);
|
|
89
|
+
await execWrite(["upgrade", "--id", resolvedId]);
|
|
90
|
+
return resolvedId;
|
|
91
|
+
}
|
|
92
|
+
async function upgradeAll() {
|
|
93
|
+
await execWrite(["upgrade", "--all"]);
|
|
94
|
+
}
|