@reliverse/dler 1.7.68 → 1.7.70
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 +1 -1
- package/README.md +148 -98
- package/bin/app/build/cmd.js +0 -2
- package/bin/app/cmds.d.ts +1 -0
- package/bin/app/cmds.js +1 -0
- package/bin/app/create/cmd.d.ts +47 -0
- package/bin/app/create/cmd.js +170 -0
- package/bin/app/get/cmd.d.ts +1 -0
- package/bin/app/get/cmd.js +1 -0
- package/bin/app/init/cmd.d.ts +2 -0
- package/bin/app/init/cmd.js +14 -0
- package/bin/app/install/cmd.d.ts +50 -0
- package/bin/app/install/cmd.js +83 -0
- package/bin/app/remove/cmd.d.ts +48 -0
- package/bin/app/remove/cmd.js +255 -0
- package/bin/app/update/cmd.d.ts +11 -0
- package/bin/app/update/cmd.js +277 -2
- package/bin/app/upgrade/cmd.d.ts +8 -0
- package/bin/app/upgrade/cmd.js +295 -0
- package/bin/app/x/cmd.d.ts +18 -31
- package/bin/app/x/cmd.js +133 -137
- package/bin/cli.js +16 -10
- package/bin/libs/cfg/cfg-impl/cfg-consts.d.ts +1 -1
- package/bin/libs/cfg/cfg-impl/cfg-consts.js +1 -1
- package/bin/libs/cfg/cfg-mod.d.ts +1 -23
- package/bin/libs/cfg/cfg-mod.js +1 -85
- package/bin/libs/get/mod.d.ts +37 -0
- package/bin/libs/get/mod.js +509 -0
- package/bin/libs/sdk/sdk-impl/config/default.d.ts +1 -1
- package/bin/libs/sdk/sdk-impl/config/default.js +1 -1
- package/bin/libs/sdk/sdk-impl/config/info.js +1 -1
- package/bin/libs/sdk/sdk-impl/config/init.d.ts +1 -0
- package/bin/libs/sdk/sdk-impl/config/init.js +98 -5
- package/bin/libs/sdk/sdk-impl/config/load.js +4 -4
- package/bin/libs/sdk/sdk-impl/utils/exec/exec-mod.js +0 -8
- package/bin/libs/sdk/sdk-mod.d.ts +1 -1
- package/bin/libs/sdk/sdk-mod.js +1 -1
- package/bin/mod.d.ts +1 -1
- package/bin/mod.js +1 -1
- package/package.json +3 -9
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-biome.d.ts +0 -2
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-biome.js +0 -34
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-comments.d.ts +0 -1
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-comments.js +0 -57
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-consts.d.ts +0 -34
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-consts.js +0 -36
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-content.d.ts +0 -14
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-content.js +0 -15
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-core.d.ts +0 -14
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-core.js +0 -63
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-create.d.ts +0 -36
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-create.js +0 -275
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-def-utils.d.ts +0 -6
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-def-utils.js +0 -225
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-default.d.ts +0 -3
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-default.js +0 -155
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-define.d.ts +0 -125
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-define.js +0 -4
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-detect.d.ts +0 -23
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-detect.js +0 -347
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-gen-cfg.d.ts +0 -3
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-gen-cfg.js +0 -186
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-migrate.d.ts +0 -5
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-migrate.js +0 -56
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-path.d.ts +0 -11
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-path.js +0 -33
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-prompts.d.ts +0 -5
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-prompts.js +0 -12
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-read.d.ts +0 -11
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-read.js +0 -84
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-repair.d.ts +0 -16
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-repair.js +0 -137
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-schema.d.ts +0 -130
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-schema.js +0 -438
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-types.d.ts +0 -75
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-types.js +0 -0
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-unstable.d.ts +0 -11
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-unstable.js +0 -41
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-update.d.ts +0 -10
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-update.js +0 -152
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-utils.d.ts +0 -17
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-utils.js +0 -86
- package/bin/libs/cfg/cfg-impl/rse-config/rse-mod.d.ts +0 -20
- package/bin/libs/cfg/cfg-impl/rse-config/rse-mod.js +0 -20
package/bin/app/update/cmd.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import path from "@reliverse/pathkit";
|
|
2
2
|
import fs from "@reliverse/relifso";
|
|
3
3
|
import { relinka } from "@reliverse/relinka";
|
|
4
|
-
import { defineArgs, defineCommand } from "@reliverse/rempts";
|
|
4
|
+
import { defineArgs, defineCommand, multiselectPrompt } from "@reliverse/rempts";
|
|
5
5
|
import { $ } from "bun";
|
|
6
|
+
import { lookpath } from "lookpath";
|
|
6
7
|
import pMap from "p-map";
|
|
7
8
|
import { readPackageJSON } from "pkg-types";
|
|
8
9
|
import semver from "semver";
|
|
@@ -52,6 +53,220 @@ async function getLatestVersion(packageName) {
|
|
|
52
53
|
}
|
|
53
54
|
}
|
|
54
55
|
}
|
|
56
|
+
async function getGlobalPackages(packageManager) {
|
|
57
|
+
try {
|
|
58
|
+
let result;
|
|
59
|
+
if (packageManager === "npm") {
|
|
60
|
+
result = await $`npm list -g --depth=0 --json`.json();
|
|
61
|
+
} else if (packageManager === "yarn") {
|
|
62
|
+
try {
|
|
63
|
+
result = await $`yarn global list --json`.json();
|
|
64
|
+
} catch {
|
|
65
|
+
result = await $`yarn global list`.text();
|
|
66
|
+
const packages2 = {};
|
|
67
|
+
const lines = result.split("\n");
|
|
68
|
+
for (const line of lines) {
|
|
69
|
+
const match = line.match(/^(.+)@([^@]+)$/);
|
|
70
|
+
if (match) {
|
|
71
|
+
packages2[match[1]] = match[2];
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return packages2;
|
|
75
|
+
}
|
|
76
|
+
} else if (packageManager === "pnpm") {
|
|
77
|
+
result = await $`pnpm list -g --depth=0 --json`.json();
|
|
78
|
+
} else if (packageManager === "bun") {
|
|
79
|
+
result = await $`bun pm ls -g --json`.json();
|
|
80
|
+
} else {
|
|
81
|
+
throw new Error(`Unsupported package manager: ${packageManager}`);
|
|
82
|
+
}
|
|
83
|
+
const dependencies = result?.dependencies || {};
|
|
84
|
+
const packages = {};
|
|
85
|
+
for (const [name, info] of Object.entries(dependencies)) {
|
|
86
|
+
if (info && typeof info === "object" && "version" in info) {
|
|
87
|
+
packages[name] = info.version;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return packages;
|
|
91
|
+
} catch (error) {
|
|
92
|
+
relinka("warn", `Failed to get global packages for ${packageManager}: ${error}`);
|
|
93
|
+
return {};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async function updateGlobalPackage(packageManager, packageName) {
|
|
97
|
+
try {
|
|
98
|
+
if (packageManager === "npm") {
|
|
99
|
+
await $`npm install -g ${packageName}@latest`;
|
|
100
|
+
} else if (packageManager === "yarn") {
|
|
101
|
+
await $`yarn global add ${packageName}@latest`;
|
|
102
|
+
} else if (packageManager === "pnpm") {
|
|
103
|
+
await $`pnpm add -g ${packageName}@latest`;
|
|
104
|
+
} else if (packageManager === "bun") {
|
|
105
|
+
await $`bun install -g ${packageName}@latest`;
|
|
106
|
+
} else {
|
|
107
|
+
throw new Error(`Unsupported package manager: ${packageManager}`);
|
|
108
|
+
}
|
|
109
|
+
return true;
|
|
110
|
+
} catch (error) {
|
|
111
|
+
relinka(
|
|
112
|
+
"warn",
|
|
113
|
+
`Failed to update global package ${packageName} with ${packageManager}: ${error}`
|
|
114
|
+
);
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async function handleGlobalUpdates(args) {
|
|
119
|
+
const packageManagers = ["bun", "npm", "yarn", "pnpm"];
|
|
120
|
+
const availablePackageManagers = [];
|
|
121
|
+
for (const pm of packageManagers) {
|
|
122
|
+
if (await lookpath(pm)) {
|
|
123
|
+
availablePackageManagers.push(pm);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (availablePackageManagers.length === 0) {
|
|
127
|
+
relinka("error", "No supported package managers found");
|
|
128
|
+
return process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
relinka("info", `Found package managers: ${availablePackageManagers.join(", ")}`);
|
|
131
|
+
const allGlobalPackages = {};
|
|
132
|
+
for (const pm of availablePackageManagers) {
|
|
133
|
+
const packages = await getGlobalPackages(pm);
|
|
134
|
+
for (const [name, version] of Object.entries(packages)) {
|
|
135
|
+
if (!allGlobalPackages[name] || semver.gt(version, allGlobalPackages[name].version)) {
|
|
136
|
+
allGlobalPackages[name] = { version, packageManager: pm };
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const globalPackageNames = Object.keys(allGlobalPackages);
|
|
141
|
+
if (globalPackageNames.length === 0) {
|
|
142
|
+
relinka("warn", "No global packages found");
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
let filteredPackages = [];
|
|
146
|
+
if (args.name && args.name.length > 0) {
|
|
147
|
+
filteredPackages = args.name.filter((pkg) => pkg in allGlobalPackages);
|
|
148
|
+
const notFound = args.name.filter((pkg) => !(pkg in allGlobalPackages));
|
|
149
|
+
if (notFound.length > 0) {
|
|
150
|
+
relinka("warn", `Global packages not found: ${notFound.join(", ")}`);
|
|
151
|
+
}
|
|
152
|
+
} else {
|
|
153
|
+
const ignoreList = args.ignore || [];
|
|
154
|
+
filteredPackages = globalPackageNames.filter((pkg) => !ignoreList.includes(pkg));
|
|
155
|
+
}
|
|
156
|
+
if (filteredPackages.length === 0) {
|
|
157
|
+
relinka("warn", "No global packages to update");
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
relinka("info", `Checking ${filteredPackages.length} global packages for updates...`);
|
|
161
|
+
const results = await pMap(
|
|
162
|
+
filteredPackages,
|
|
163
|
+
async (packageName) => {
|
|
164
|
+
const globalPackage = allGlobalPackages[packageName];
|
|
165
|
+
if (!globalPackage) {
|
|
166
|
+
return {
|
|
167
|
+
package: packageName,
|
|
168
|
+
currentVersion: "unknown",
|
|
169
|
+
latestVersion: "unknown",
|
|
170
|
+
updated: false,
|
|
171
|
+
error: "Package not found in global packages",
|
|
172
|
+
location: "global"
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
const latest = await getLatestVersion(packageName);
|
|
177
|
+
const needsUpdate = semver.gt(latest, globalPackage.version);
|
|
178
|
+
return {
|
|
179
|
+
package: packageName,
|
|
180
|
+
currentVersion: globalPackage.version,
|
|
181
|
+
latestVersion: latest,
|
|
182
|
+
updated: needsUpdate,
|
|
183
|
+
location: `global (${globalPackage.packageManager})`
|
|
184
|
+
};
|
|
185
|
+
} catch (error) {
|
|
186
|
+
return {
|
|
187
|
+
package: packageName,
|
|
188
|
+
currentVersion: globalPackage.version,
|
|
189
|
+
latestVersion: globalPackage.version,
|
|
190
|
+
updated: false,
|
|
191
|
+
error: error instanceof Error ? error.message : String(error),
|
|
192
|
+
location: `global (${globalPackage.packageManager})`
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
{ concurrency: args.concurrency }
|
|
197
|
+
);
|
|
198
|
+
let toUpdate = results.filter((r) => r.updated && !r.error);
|
|
199
|
+
const errors = results.filter((r) => r.error);
|
|
200
|
+
const upToDate = results.filter((r) => !r.updated && !r.error);
|
|
201
|
+
if (errors.length > 0) {
|
|
202
|
+
relinka("warn", `Failed to check ${errors.length} global packages:`);
|
|
203
|
+
for (const error of errors) {
|
|
204
|
+
relinka("warn", ` ${error.package} (${error.location}): ${error.error}`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (upToDate.length > 0) {
|
|
208
|
+
relinka("success", `${upToDate.length} global packages are up to date`);
|
|
209
|
+
}
|
|
210
|
+
if (toUpdate.length === 0) {
|
|
211
|
+
relinka("success", "All global packages are up to date");
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
relinka("info", `${toUpdate.length} global packages can be updated:`);
|
|
215
|
+
for (const update of toUpdate) {
|
|
216
|
+
relinka(
|
|
217
|
+
"log",
|
|
218
|
+
` ${update.package} (${update.location}): ${update.currentVersion} \u2192 ${update.latestVersion}`
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
if (args.interactive) {
|
|
222
|
+
const allGlobalPackages2 = [
|
|
223
|
+
...toUpdate.map((pkg) => ({ ...pkg, canUpdate: true, isUpToDate: false, hasError: false })),
|
|
224
|
+
...upToDate.map((pkg) => ({ ...pkg, canUpdate: false, isUpToDate: true, hasError: false })),
|
|
225
|
+
...errors.map((pkg) => ({ ...pkg, canUpdate: false, isUpToDate: false, hasError: true }))
|
|
226
|
+
];
|
|
227
|
+
const selectedPackages = await multiselectPrompt({
|
|
228
|
+
title: "Select global packages to update",
|
|
229
|
+
options: [
|
|
230
|
+
{ label: "Exit", value: "exit" },
|
|
231
|
+
...allGlobalPackages2.map((pkg) => {
|
|
232
|
+
let label = `${pkg.package} (${pkg.location})`;
|
|
233
|
+
if (pkg.canUpdate) {
|
|
234
|
+
label += `: ${pkg.currentVersion} \u2192 ${pkg.latestVersion}`;
|
|
235
|
+
} else if (pkg.isUpToDate) {
|
|
236
|
+
label += `: ${pkg.currentVersion} (up-to-date)`;
|
|
237
|
+
} else if (pkg.hasError) {
|
|
238
|
+
label += `: ${pkg.currentVersion} (has errors)`;
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
label,
|
|
242
|
+
value: pkg.package,
|
|
243
|
+
disabled: !pkg.canUpdate,
|
|
244
|
+
hint: pkg.hasError ? pkg.error : void 0
|
|
245
|
+
};
|
|
246
|
+
})
|
|
247
|
+
]
|
|
248
|
+
});
|
|
249
|
+
if (selectedPackages.length === 0 || selectedPackages.includes("exit")) {
|
|
250
|
+
relinka("info", "Exiting global update process");
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
const actualSelectedPackages = selectedPackages.filter((pkg) => pkg !== "exit");
|
|
254
|
+
toUpdate = toUpdate.filter((update) => actualSelectedPackages.includes(update.package));
|
|
255
|
+
relinka("info", `Updating ${actualSelectedPackages.length} selected global packages...`);
|
|
256
|
+
}
|
|
257
|
+
if (args["dry-run"]) {
|
|
258
|
+
relinka("info", "Dry run mode - no changes were made");
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
let successCount = 0;
|
|
262
|
+
for (const update of toUpdate) {
|
|
263
|
+
const globalPackage = allGlobalPackages[update.package];
|
|
264
|
+
if (globalPackage && await updateGlobalPackage(globalPackage.packageManager, update.package)) {
|
|
265
|
+
successCount++;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
relinka("success", `Successfully updated ${successCount}/${toUpdate.length} global packages`);
|
|
269
|
+
}
|
|
55
270
|
export default defineCommand({
|
|
56
271
|
meta: {
|
|
57
272
|
name: "update",
|
|
@@ -117,10 +332,24 @@ export default defineCommand({
|
|
|
117
332
|
description: "Skip the install step after updating dependencies",
|
|
118
333
|
default: false,
|
|
119
334
|
alias: "no-i"
|
|
335
|
+
},
|
|
336
|
+
global: {
|
|
337
|
+
type: "boolean",
|
|
338
|
+
description: "Update global packages instead of local dependencies",
|
|
339
|
+
default: false,
|
|
340
|
+
alias: "g"
|
|
341
|
+
},
|
|
342
|
+
interactive: {
|
|
343
|
+
type: "boolean",
|
|
344
|
+
description: "Interactively select which dependencies to update",
|
|
345
|
+
default: false
|
|
120
346
|
}
|
|
121
347
|
}),
|
|
122
348
|
async run({ args }) {
|
|
123
349
|
try {
|
|
350
|
+
if (args.global) {
|
|
351
|
+
return await handleGlobalUpdates(args);
|
|
352
|
+
}
|
|
124
353
|
const packageJsonPath = path.resolve(process.cwd(), "package.json");
|
|
125
354
|
if (!await fs.pathExists(packageJsonPath)) {
|
|
126
355
|
relinka("error", "No package.json found in current directory");
|
|
@@ -288,7 +517,7 @@ export default defineCommand({
|
|
|
288
517
|
},
|
|
289
518
|
{ concurrency: args.concurrency }
|
|
290
519
|
);
|
|
291
|
-
|
|
520
|
+
let toUpdate = results.filter((r) => r.updated && !r.error);
|
|
292
521
|
const errors = results.filter((r) => r.error);
|
|
293
522
|
const upToDate = results.filter((r) => !r.updated && !r.error && r.semverCompatible);
|
|
294
523
|
if (errors.length > 0) {
|
|
@@ -315,6 +544,52 @@ export default defineCommand({
|
|
|
315
544
|
` ${update.package} (${update.location}): ${update.currentVersion} \u2192 ${update.latestVersion}`
|
|
316
545
|
);
|
|
317
546
|
}
|
|
547
|
+
if (args.interactive) {
|
|
548
|
+
const allPackages = [
|
|
549
|
+
...toUpdate.map((pkg) => ({
|
|
550
|
+
...pkg,
|
|
551
|
+
canUpdate: true,
|
|
552
|
+
isUpToDate: false,
|
|
553
|
+
hasError: false
|
|
554
|
+
})),
|
|
555
|
+
...upToDate.map((pkg) => ({
|
|
556
|
+
...pkg,
|
|
557
|
+
canUpdate: false,
|
|
558
|
+
isUpToDate: true,
|
|
559
|
+
hasError: false
|
|
560
|
+
})),
|
|
561
|
+
...errors.map((pkg) => ({ ...pkg, canUpdate: false, isUpToDate: false, hasError: true }))
|
|
562
|
+
];
|
|
563
|
+
const selectedPackages = await multiselectPrompt({
|
|
564
|
+
title: "Select dependencies to update",
|
|
565
|
+
options: [
|
|
566
|
+
{ label: "Exit", value: "exit" },
|
|
567
|
+
...allPackages.map((pkg) => {
|
|
568
|
+
let label = `${pkg.package} (${pkg.location})`;
|
|
569
|
+
if (pkg.canUpdate) {
|
|
570
|
+
label += `: ${pkg.currentVersion} \u2192 ${pkg.latestVersion}`;
|
|
571
|
+
} else if (pkg.isUpToDate) {
|
|
572
|
+
label += `: ${pkg.currentVersion} (up-to-date)`;
|
|
573
|
+
} else if (pkg.hasError) {
|
|
574
|
+
label += `: ${pkg.currentVersion} (has errors)`;
|
|
575
|
+
}
|
|
576
|
+
return {
|
|
577
|
+
label,
|
|
578
|
+
value: pkg.package,
|
|
579
|
+
disabled: !pkg.canUpdate,
|
|
580
|
+
hint: pkg.hasError ? pkg.error : void 0
|
|
581
|
+
};
|
|
582
|
+
})
|
|
583
|
+
]
|
|
584
|
+
});
|
|
585
|
+
if (selectedPackages.length === 0 || selectedPackages.includes("exit")) {
|
|
586
|
+
relinka("info", "Exiting update process");
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
const actualSelectedPackages = selectedPackages.filter((pkg) => pkg !== "exit");
|
|
590
|
+
toUpdate = toUpdate.filter((update) => actualSelectedPackages.includes(update.package));
|
|
591
|
+
relinka("info", `Updating ${actualSelectedPackages.length} selected dependencies...`);
|
|
592
|
+
}
|
|
318
593
|
if (args["dry-run"]) {
|
|
319
594
|
relinka("info", "Dry run mode - no changes were made");
|
|
320
595
|
return;
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import { relinka } from "@reliverse/relinka";
|
|
2
|
+
import { defineArgs, defineCommand, multiselectPrompt } from "@reliverse/rempts";
|
|
3
|
+
import { lookpath } from "lookpath";
|
|
4
|
+
import { readPackageJSON } from "pkg-types";
|
|
5
|
+
import { x } from "../../libs/sdk/sdk-impl/utils/exec/exec-mod.js";
|
|
6
|
+
import { detectPackageManager } from "../../libs/sdk/sdk-impl/utils/pm/pm-detect.js";
|
|
7
|
+
export default defineCommand({
|
|
8
|
+
meta: {
|
|
9
|
+
name: "upgrade",
|
|
10
|
+
version: "1.0.0",
|
|
11
|
+
description: "Upgrade system development tools"
|
|
12
|
+
},
|
|
13
|
+
args: defineArgs({
|
|
14
|
+
interactive: {
|
|
15
|
+
type: "boolean",
|
|
16
|
+
description: "Interactively select which tools to upgrade",
|
|
17
|
+
default: true
|
|
18
|
+
}
|
|
19
|
+
}),
|
|
20
|
+
async run({ args }) {
|
|
21
|
+
const toolUpgradeFunctions = [
|
|
22
|
+
{ name: "dler (local)", fn: upgradeDlerLocal },
|
|
23
|
+
{ name: "dler (global)", fn: upgradeDlerGlobal },
|
|
24
|
+
{ name: "git", fn: upgradeGit },
|
|
25
|
+
{ name: "node.js", fn: upgradeNode },
|
|
26
|
+
{ name: "npm", fn: upgradeNpm },
|
|
27
|
+
{ name: "bun", fn: upgradeBun },
|
|
28
|
+
{ name: "yarn", fn: upgradeYarn },
|
|
29
|
+
{ name: "pnpm", fn: upgradePnpm }
|
|
30
|
+
];
|
|
31
|
+
let results = [];
|
|
32
|
+
if (args.interactive) {
|
|
33
|
+
const preliminaryResults = await Promise.all(
|
|
34
|
+
toolUpgradeFunctions.map(async ({ fn }) => await fn())
|
|
35
|
+
);
|
|
36
|
+
const availableTools = toolUpgradeFunctions.map((tool, index) => ({
|
|
37
|
+
...tool,
|
|
38
|
+
result: preliminaryResults[index]
|
|
39
|
+
})).filter(({ result }) => result && result.status !== "not-found");
|
|
40
|
+
if (availableTools.length === 0) {
|
|
41
|
+
relinka("warn", "No tools available for upgrade");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const selectedTools = await multiselectPrompt({
|
|
45
|
+
title: "Select tools to upgrade",
|
|
46
|
+
displayInstructions: true,
|
|
47
|
+
options: [
|
|
48
|
+
{ label: "Exit", value: "exit", disabled: true },
|
|
49
|
+
...availableTools.map(({ name, result }) => {
|
|
50
|
+
const isUpToDate = result && result.status === "up-to-date";
|
|
51
|
+
const hasErrors = result && result.status === "error";
|
|
52
|
+
const canUpgrade = result && result.status === "upgraded";
|
|
53
|
+
let label = name;
|
|
54
|
+
if (isUpToDate) {
|
|
55
|
+
label += " (up-to-date)";
|
|
56
|
+
} else if (hasErrors) {
|
|
57
|
+
label += " (has errors)";
|
|
58
|
+
} else if (canUpgrade) {
|
|
59
|
+
label += " (can be upgraded)";
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
label,
|
|
63
|
+
value: name,
|
|
64
|
+
disabled: isUpToDate,
|
|
65
|
+
hint: hasErrors ? result.message : void 0
|
|
66
|
+
};
|
|
67
|
+
})
|
|
68
|
+
]
|
|
69
|
+
});
|
|
70
|
+
if (selectedTools.length === 0 || selectedTools.includes("exit")) {
|
|
71
|
+
relinka("info", "Exiting upgrade process");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const actualSelectedTools = selectedTools.filter((tool) => tool !== "exit");
|
|
75
|
+
relinka("info", `Upgrading ${actualSelectedTools.length} selected tools...`);
|
|
76
|
+
for (const toolName of actualSelectedTools) {
|
|
77
|
+
const tool = availableTools.find((t) => t.name === toolName);
|
|
78
|
+
if (tool) {
|
|
79
|
+
const result = await tool.fn();
|
|
80
|
+
results.push(result);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
results = await Promise.all(toolUpgradeFunctions.map(async ({ fn }) => await fn()));
|
|
85
|
+
}
|
|
86
|
+
const upgraded = results.filter((r) => r.status === "upgraded");
|
|
87
|
+
const upToDate = results.filter((r) => r.status === "up-to-date");
|
|
88
|
+
const notFound = results.filter((r) => r.status === "not-found");
|
|
89
|
+
const errors = results.filter((r) => r.status === "error");
|
|
90
|
+
if (upgraded.length > 0) {
|
|
91
|
+
relinka("success", `Upgraded ${upgraded.length} tools:`);
|
|
92
|
+
upgraded.forEach((r) => relinka("log", ` \u2713 ${r.tool}${r.message ? ` - ${r.message}` : ""}`));
|
|
93
|
+
}
|
|
94
|
+
if (upToDate.length > 0) {
|
|
95
|
+
relinka("info", `${upToDate.length} tools already up-to-date:`);
|
|
96
|
+
upToDate.forEach((r) => relinka("log", ` \u2022 ${r.tool}${r.message ? ` - ${r.message}` : ""}`));
|
|
97
|
+
}
|
|
98
|
+
if (notFound.length > 0) {
|
|
99
|
+
relinka("warn", `${notFound.length} tools not installed (skipped):`);
|
|
100
|
+
notFound.forEach((r) => relinka("log", ` - ${r.tool}`));
|
|
101
|
+
}
|
|
102
|
+
if (errors.length > 0) {
|
|
103
|
+
relinka("error", `${errors.length} tools had errors:`);
|
|
104
|
+
errors.forEach((r) => relinka("log", ` \u2717 ${r.tool}${r.message ? ` - ${r.message}` : ""}`));
|
|
105
|
+
}
|
|
106
|
+
relinka("success", "Upgrade check completed!");
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
async function upgradeDlerLocal() {
|
|
110
|
+
try {
|
|
111
|
+
const pkg = await readPackageJSON();
|
|
112
|
+
const hasDler = pkg.dependencies && "@reliverse/dler" in pkg.dependencies || pkg.devDependencies && "@reliverse/dler" in pkg.devDependencies;
|
|
113
|
+
if (!hasDler) {
|
|
114
|
+
return { tool: "dler (local)", status: "not-found" };
|
|
115
|
+
}
|
|
116
|
+
const packageManager = await detectPackageManager(process.cwd());
|
|
117
|
+
if (!packageManager) {
|
|
118
|
+
return { tool: "dler (local)", status: "error", message: "No package manager detected" };
|
|
119
|
+
}
|
|
120
|
+
const { exitCode } = await x(packageManager.command, ["update", "@reliverse/dler"], {
|
|
121
|
+
nodeOptions: { stdio: "pipe" }
|
|
122
|
+
});
|
|
123
|
+
return exitCode === 0 ? { tool: "dler (local)", status: "upgraded", message: `via ${packageManager.command}` } : { tool: "dler (local)", status: "error", message: "Upgrade failed" };
|
|
124
|
+
} catch (error) {
|
|
125
|
+
return {
|
|
126
|
+
tool: "dler (local)",
|
|
127
|
+
status: "not-found"
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
async function upgradeDlerGlobal() {
|
|
132
|
+
try {
|
|
133
|
+
const dlerPath = await lookpath("dler");
|
|
134
|
+
if (!dlerPath) {
|
|
135
|
+
return { tool: "dler (global)", status: "not-found" };
|
|
136
|
+
}
|
|
137
|
+
const packageManagers = ["bun", "npm", "yarn", "pnpm"];
|
|
138
|
+
for (const pm of packageManagers) {
|
|
139
|
+
const pmPath = await lookpath(pm);
|
|
140
|
+
if (pmPath) {
|
|
141
|
+
try {
|
|
142
|
+
const args = pm === "npm" ? ["install", "-g", "@reliverse/dler@latest"] : pm === "yarn" ? ["global", "add", "@reliverse/dler@latest"] : ["install", "-g", "@reliverse/dler@latest"];
|
|
143
|
+
const { exitCode } = await x(pm, args, {
|
|
144
|
+
nodeOptions: { stdio: "pipe" }
|
|
145
|
+
});
|
|
146
|
+
if (exitCode === 0) {
|
|
147
|
+
return { tool: "dler (global)", status: "upgraded", message: `via ${pm}` };
|
|
148
|
+
}
|
|
149
|
+
} catch {
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return { tool: "dler (global)", status: "error", message: "No suitable package manager found" };
|
|
154
|
+
} catch (error) {
|
|
155
|
+
return { tool: "dler (global)", status: "error", message: String(error) };
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
async function upgradeGit() {
|
|
159
|
+
try {
|
|
160
|
+
const gitPath = await lookpath("git");
|
|
161
|
+
if (!gitPath) {
|
|
162
|
+
return { tool: "git", status: "not-found" };
|
|
163
|
+
}
|
|
164
|
+
const { stdout } = await x("git", ["--version"], {
|
|
165
|
+
nodeOptions: { stdio: "pipe" }
|
|
166
|
+
});
|
|
167
|
+
return {
|
|
168
|
+
tool: "git",
|
|
169
|
+
status: "up-to-date",
|
|
170
|
+
message: `${stdout.trim()} - manual upgrade required`
|
|
171
|
+
};
|
|
172
|
+
} catch (error) {
|
|
173
|
+
return { tool: "git", status: "error", message: String(error) };
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
async function upgradeNode() {
|
|
177
|
+
try {
|
|
178
|
+
const nodePath = await lookpath("node");
|
|
179
|
+
if (!nodePath) {
|
|
180
|
+
return { tool: "node.js", status: "not-found" };
|
|
181
|
+
}
|
|
182
|
+
const { stdout } = await x("node", ["--version"], {
|
|
183
|
+
nodeOptions: { stdio: "pipe" }
|
|
184
|
+
});
|
|
185
|
+
return {
|
|
186
|
+
tool: "node.js",
|
|
187
|
+
status: "up-to-date",
|
|
188
|
+
message: `${stdout.trim()} - manual upgrade required`
|
|
189
|
+
};
|
|
190
|
+
} catch (error) {
|
|
191
|
+
return { tool: "node.js", status: "error", message: String(error) };
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
async function upgradeNpm() {
|
|
195
|
+
try {
|
|
196
|
+
const npmPath = await lookpath("npm");
|
|
197
|
+
if (!npmPath) {
|
|
198
|
+
return { tool: "npm", status: "not-found" };
|
|
199
|
+
}
|
|
200
|
+
try {
|
|
201
|
+
const { exitCode, stdout, stderr } = await x("npm", ["install", "-g", "npm@latest"], {
|
|
202
|
+
nodeOptions: { stdio: "pipe" }
|
|
203
|
+
});
|
|
204
|
+
if (exitCode === 0) {
|
|
205
|
+
const output = (stdout + stderr).toLowerCase();
|
|
206
|
+
if (output.includes("unchanged") || output.includes("up-to-date") || output.includes("already")) {
|
|
207
|
+
return { tool: "npm", status: "up-to-date" };
|
|
208
|
+
}
|
|
209
|
+
return { tool: "npm", status: "upgraded" };
|
|
210
|
+
} else {
|
|
211
|
+
return { tool: "npm", status: "error", message: "Upgrade failed" };
|
|
212
|
+
}
|
|
213
|
+
} catch (pipeError) {
|
|
214
|
+
const { exitCode } = await x("npm", ["install", "-g", "npm@latest"], {
|
|
215
|
+
nodeOptions: { stdio: "inherit" }
|
|
216
|
+
});
|
|
217
|
+
return exitCode === 0 ? { tool: "npm", status: "upgraded" } : { tool: "npm", status: "error", message: "Upgrade failed" };
|
|
218
|
+
}
|
|
219
|
+
} catch (error) {
|
|
220
|
+
return { tool: "npm", status: "error", message: String(error) };
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
async function upgradeBun() {
|
|
224
|
+
try {
|
|
225
|
+
const bunPath = await lookpath("bun");
|
|
226
|
+
if (!bunPath) {
|
|
227
|
+
return { tool: "bun", status: "not-found" };
|
|
228
|
+
}
|
|
229
|
+
const { exitCode, stdout, stderr } = await x("bun", ["upgrade"], {
|
|
230
|
+
nodeOptions: { stdio: "pipe" }
|
|
231
|
+
});
|
|
232
|
+
if (exitCode !== 0) {
|
|
233
|
+
return { tool: "bun", status: "error", message: "Upgrade failed" };
|
|
234
|
+
}
|
|
235
|
+
const output = (stdout + stderr).toLowerCase();
|
|
236
|
+
if (output.includes("already") || output.includes("up-to-date") || output.includes("latest")) {
|
|
237
|
+
return { tool: "bun", status: "up-to-date" };
|
|
238
|
+
}
|
|
239
|
+
return { tool: "bun", status: "upgraded" };
|
|
240
|
+
} catch (error) {
|
|
241
|
+
return { tool: "bun", status: "error", message: String(error) };
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
async function upgradeYarn() {
|
|
245
|
+
try {
|
|
246
|
+
const yarnPath = await lookpath("yarn");
|
|
247
|
+
if (!yarnPath) {
|
|
248
|
+
return { tool: "yarn", status: "not-found" };
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
const { exitCode: upgradeResult } = await x("yarn", ["self-update"], {
|
|
252
|
+
nodeOptions: { stdio: "pipe" }
|
|
253
|
+
});
|
|
254
|
+
if (upgradeResult === 0) {
|
|
255
|
+
return { tool: "yarn", status: "upgraded", message: "self-update" };
|
|
256
|
+
}
|
|
257
|
+
} catch {
|
|
258
|
+
}
|
|
259
|
+
const npmPath = await lookpath("npm");
|
|
260
|
+
if (npmPath) {
|
|
261
|
+
const { exitCode } = await x("npm", ["install", "-g", "yarn@latest"], {
|
|
262
|
+
nodeOptions: { stdio: "pipe" }
|
|
263
|
+
});
|
|
264
|
+
return exitCode === 0 ? { tool: "yarn", status: "upgraded", message: "via npm" } : { tool: "yarn", status: "error", message: "Upgrade failed" };
|
|
265
|
+
}
|
|
266
|
+
return { tool: "yarn", status: "error", message: "No upgrade method available" };
|
|
267
|
+
} catch (error) {
|
|
268
|
+
return { tool: "yarn", status: "error", message: String(error) };
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
async function upgradePnpm() {
|
|
272
|
+
try {
|
|
273
|
+
const pnpmPath = await lookpath("pnpm");
|
|
274
|
+
if (!pnpmPath) {
|
|
275
|
+
return { tool: "pnpm", status: "not-found" };
|
|
276
|
+
}
|
|
277
|
+
try {
|
|
278
|
+
const { exitCode } = await x("pnpm", ["add", "-g", "pnpm@latest"], {
|
|
279
|
+
nodeOptions: { stdio: "pipe" }
|
|
280
|
+
});
|
|
281
|
+
return exitCode === 0 ? { tool: "pnpm", status: "upgraded" } : { tool: "pnpm", status: "error", message: "Upgrade failed" };
|
|
282
|
+
} catch {
|
|
283
|
+
const npmPath = await lookpath("npm");
|
|
284
|
+
if (npmPath) {
|
|
285
|
+
const { exitCode } = await x("npm", ["install", "-g", "pnpm@latest"], {
|
|
286
|
+
nodeOptions: { stdio: "pipe" }
|
|
287
|
+
});
|
|
288
|
+
return exitCode === 0 ? { tool: "pnpm", status: "upgraded", message: "via npm" } : { tool: "pnpm", status: "error", message: "Upgrade failed" };
|
|
289
|
+
}
|
|
290
|
+
return { tool: "pnpm", status: "error", message: "No upgrade method available" };
|
|
291
|
+
}
|
|
292
|
+
} catch (error) {
|
|
293
|
+
return { tool: "pnpm", status: "error", message: String(error) };
|
|
294
|
+
}
|
|
295
|
+
}
|