@reliverse/dler 1.7.111 → 1.7.113
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/bin/app/ai/ai-impl/ai-auth.js +0 -2
- package/bin/app/ai/ai-impl/mcp/mcp-mod.js +0 -2
- package/bin/app/better/auth/(utils)/get-config.js +2 -1
- package/bin/app/better/auth/init/cmd.js +4 -3
- package/bin/app/config/constants.d.ts +1 -1
- package/bin/app/config/constants.js +1 -1
- package/bin/app/config/prepare.js +6 -6
- package/bin/app/login/login-impl.d.ts +0 -1
- package/bin/app/login/login-impl.js +1 -2
- package/bin/app/migrate/cmd.d.ts +12 -0
- package/bin/app/migrate/cmd.js +87 -1
- package/bin/app/migrate/codemods/monorepo-catalog.d.ts +96 -0
- package/bin/app/{update/migrate/cmd.js → migrate/codemods/monorepo-catalog.js} +16 -104
- package/bin/app/providers/better-t-stack/types.d.ts +3 -3
- package/bin/app/update/cmd.d.ts +10 -0
- package/bin/app/update/cmd.js +155 -901
- package/bin/app/update/impl.d.ts +42 -0
- package/bin/app/update/impl.js +260 -0
- package/bin/app/update/utils.d.ts +134 -0
- package/bin/app/update/utils.js +899 -0
- package/bin/dler.js +1 -6
- package/bin/mod.d.ts +167 -19
- package/bin/mod.js +300 -60
- package/package.json +19 -7
- package/bin/app/update/cmd-2.d.ts +0 -2
- package/bin/app/update/cmd-2.js +0 -50
- package/bin/app/update/migrate/cmd.d.ts +0 -23
- package/bin/app/update/update-impl.d.ts +0 -2
- package/bin/app/update/update-impl.js +0 -50
- package/bin/app/upgrade/cmd.d.ts +0 -8
- package/bin/app/upgrade/cmd.js +0 -302
|
@@ -0,0 +1,899 @@
|
|
|
1
|
+
import path from "@reliverse/pathkit";
|
|
2
|
+
import fs from "@reliverse/relifso";
|
|
3
|
+
import { relinka } from "@reliverse/relinka";
|
|
4
|
+
import { multiselectPrompt } from "@reliverse/rempts";
|
|
5
|
+
import { $ } from "bun";
|
|
6
|
+
import { lookpath } from "lookpath";
|
|
7
|
+
import pMap from "p-map";
|
|
8
|
+
import { readPackageJSON } from "pkg-types";
|
|
9
|
+
import semver from "semver";
|
|
10
|
+
import { glob } from "tinyglobby";
|
|
11
|
+
import { getAllPkgManagers } from "../utils/dependencies/getUserPkgManager.js";
|
|
12
|
+
import { x } from "../utils/exec/exec-mod.js";
|
|
13
|
+
import { detectPackageManager } from "../utils/pm/pm-detect.js";
|
|
14
|
+
import { latestVersion } from "../utils/pm/pm-meta.js";
|
|
15
|
+
import { getCurrentWorkingDirectory } from "../utils/terminalHelpers.js";
|
|
16
|
+
export const versionCache = /* @__PURE__ */ new Map();
|
|
17
|
+
export const CACHE_TTL = 5 * 60 * 1e3;
|
|
18
|
+
export function isNpmAlias(versionSpec) {
|
|
19
|
+
return versionSpec.startsWith("npm:");
|
|
20
|
+
}
|
|
21
|
+
export function isWorkspaceDependency(versionSpec) {
|
|
22
|
+
return versionSpec.startsWith("workspace:");
|
|
23
|
+
}
|
|
24
|
+
export function isCatalogReference(versionSpec) {
|
|
25
|
+
return versionSpec.startsWith("catalog:");
|
|
26
|
+
}
|
|
27
|
+
export function isNonSemverSpecifier(versionSpec) {
|
|
28
|
+
return isNpmAlias(versionSpec) || isWorkspaceDependency(versionSpec) || isCatalogReference(versionSpec) || versionSpec.startsWith("git+") || versionSpec.startsWith("file:") || versionSpec.startsWith("link:") || versionSpec.startsWith("http:") || versionSpec.startsWith("https:");
|
|
29
|
+
}
|
|
30
|
+
export function isSemverCompatible(currentVersionRange, latestVersion2) {
|
|
31
|
+
try {
|
|
32
|
+
if (isNpmAlias(currentVersionRange)) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
if (isWorkspaceDependency(currentVersionRange)) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
if (!currentVersionRange.startsWith("^") && !currentVersionRange.startsWith("~")) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
return semver.satisfies(latestVersion2, currentVersionRange);
|
|
42
|
+
} catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export function collectTargetDependencies(pkg, args) {
|
|
47
|
+
const map = {};
|
|
48
|
+
const dependencies = pkg.dependencies || {};
|
|
49
|
+
const devDependencies = pkg.devDependencies || {};
|
|
50
|
+
const peerDependencies = pkg.peerDependencies || {};
|
|
51
|
+
const optionalDependencies = pkg.optionalDependencies || {};
|
|
52
|
+
const includeDeps = !args["dev-only"] && !args["peer-only"] && !args["optional-only"] && !args["catalogs-only"];
|
|
53
|
+
const includeCatalogs = !args["dev-only"] && !args["peer-only"] && !args["optional-only"] && !args["prod-only"];
|
|
54
|
+
if (args["prod-only"] || includeDeps) {
|
|
55
|
+
for (const dep of Object.keys(dependencies)) {
|
|
56
|
+
const version = dependencies[dep];
|
|
57
|
+
if (!version) continue;
|
|
58
|
+
if (!map[dep]) map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
|
|
59
|
+
map[dep].versionSpec = version;
|
|
60
|
+
map[dep].locations.add("dependencies");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (args["dev-only"] || includeDeps) {
|
|
64
|
+
for (const dep of Object.keys(devDependencies)) {
|
|
65
|
+
const version = devDependencies[dep];
|
|
66
|
+
if (!version) continue;
|
|
67
|
+
if (!map[dep]) map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
|
|
68
|
+
map[dep].versionSpec = version;
|
|
69
|
+
map[dep].locations.add("devDependencies");
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (args["peer-only"] || includeDeps) {
|
|
73
|
+
for (const dep of Object.keys(peerDependencies)) {
|
|
74
|
+
const version = peerDependencies[dep];
|
|
75
|
+
if (!version) continue;
|
|
76
|
+
if (!map[dep]) map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
|
|
77
|
+
map[dep].versionSpec = version;
|
|
78
|
+
map[dep].locations.add("peerDependencies");
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (args["optional-only"] || includeDeps) {
|
|
82
|
+
for (const dep of Object.keys(optionalDependencies)) {
|
|
83
|
+
const version = optionalDependencies[dep];
|
|
84
|
+
if (!version) continue;
|
|
85
|
+
if (!map[dep]) map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
|
|
86
|
+
map[dep].versionSpec = version;
|
|
87
|
+
map[dep].locations.add("optionalDependencies");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (args["catalogs-only"] || includeCatalogs) {
|
|
91
|
+
const workspacesCatalog = pkg.workspaces?.catalog || {};
|
|
92
|
+
for (const dep of Object.keys(workspacesCatalog)) {
|
|
93
|
+
const version = workspacesCatalog[dep];
|
|
94
|
+
if (!version) continue;
|
|
95
|
+
if (!map[dep]) map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
|
|
96
|
+
map[dep].versionSpec = version;
|
|
97
|
+
map[dep].locations.add("catalog");
|
|
98
|
+
}
|
|
99
|
+
const workspacesCatalogs = pkg.workspaces?.catalogs || {};
|
|
100
|
+
for (const catalogName of Object.keys(workspacesCatalogs)) {
|
|
101
|
+
const catalog = workspacesCatalogs[catalogName] || {};
|
|
102
|
+
for (const dep of Object.keys(catalog)) {
|
|
103
|
+
const version = catalog[dep];
|
|
104
|
+
if (!version) continue;
|
|
105
|
+
if (!map[dep]) map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
|
|
106
|
+
map[dep].versionSpec = version;
|
|
107
|
+
map[dep].locations.add(`catalogs.${catalogName}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const topLevelCatalog = pkg.catalog || {};
|
|
111
|
+
for (const dep of Object.keys(topLevelCatalog)) {
|
|
112
|
+
const version = topLevelCatalog[dep];
|
|
113
|
+
if (!version) continue;
|
|
114
|
+
if (!map[dep]) map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
|
|
115
|
+
map[dep].versionSpec = version;
|
|
116
|
+
map[dep].locations.add("catalog");
|
|
117
|
+
}
|
|
118
|
+
const topLevelCatalogs = pkg.catalogs || {};
|
|
119
|
+
for (const catalogName of Object.keys(topLevelCatalogs)) {
|
|
120
|
+
const catalog = topLevelCatalogs[catalogName] || {};
|
|
121
|
+
for (const dep of Object.keys(catalog)) {
|
|
122
|
+
const version = catalog[dep];
|
|
123
|
+
if (!version) continue;
|
|
124
|
+
if (!map[dep]) map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
|
|
125
|
+
map[dep].versionSpec = version;
|
|
126
|
+
map[dep].locations.add(`catalogs.${catalogName}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return { map };
|
|
131
|
+
}
|
|
132
|
+
export function applyVersionUpdate(pkg, depName, newVersion, locations) {
|
|
133
|
+
if (locations.has("dependencies")) {
|
|
134
|
+
if (!pkg.dependencies) pkg.dependencies = {};
|
|
135
|
+
pkg.dependencies[depName] = newVersion;
|
|
136
|
+
}
|
|
137
|
+
if (locations.has("devDependencies")) {
|
|
138
|
+
if (!pkg.devDependencies) pkg.devDependencies = {};
|
|
139
|
+
pkg.devDependencies[depName] = newVersion;
|
|
140
|
+
}
|
|
141
|
+
if (locations.has("peerDependencies")) {
|
|
142
|
+
if (!pkg.peerDependencies) pkg.peerDependencies = {};
|
|
143
|
+
pkg.peerDependencies[depName] = newVersion;
|
|
144
|
+
}
|
|
145
|
+
if (locations.has("optionalDependencies")) {
|
|
146
|
+
if (!pkg.optionalDependencies) pkg.optionalDependencies = {};
|
|
147
|
+
pkg.optionalDependencies[depName] = newVersion;
|
|
148
|
+
}
|
|
149
|
+
const ensureWorkspaces = () => {
|
|
150
|
+
if (!pkg.workspaces) pkg.workspaces = {};
|
|
151
|
+
};
|
|
152
|
+
if (locations.has("catalog")) {
|
|
153
|
+
ensureWorkspaces();
|
|
154
|
+
if (!pkg.workspaces.catalog) pkg.workspaces.catalog = {};
|
|
155
|
+
pkg.workspaces.catalog[depName] = newVersion;
|
|
156
|
+
if (pkg.catalog) pkg.catalog[depName] = newVersion;
|
|
157
|
+
}
|
|
158
|
+
for (const loc of locations) {
|
|
159
|
+
const match = /^catalogs\.(.+)$/.exec(loc);
|
|
160
|
+
if (match) {
|
|
161
|
+
const catalogName = match[1] ?? "";
|
|
162
|
+
if (!catalogName) continue;
|
|
163
|
+
ensureWorkspaces();
|
|
164
|
+
if (!pkg.workspaces.catalogs) pkg.workspaces.catalogs = {};
|
|
165
|
+
if (!pkg.workspaces.catalogs[catalogName])
|
|
166
|
+
pkg.workspaces.catalogs[catalogName] = {};
|
|
167
|
+
pkg.workspaces.catalogs[catalogName][depName] = newVersion;
|
|
168
|
+
if (pkg.catalogs && pkg.catalogs[catalogName]) {
|
|
169
|
+
pkg.catalogs[catalogName][depName] = newVersion;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
export async function findWorkspacePackageJsons(cwd) {
|
|
175
|
+
const root = await readPackageJSON(cwd);
|
|
176
|
+
const ws = root.workspaces;
|
|
177
|
+
let patterns = [];
|
|
178
|
+
if (Array.isArray(ws)) {
|
|
179
|
+
patterns = ws;
|
|
180
|
+
} else if (ws && Array.isArray(ws.packages)) {
|
|
181
|
+
patterns = ws.packages;
|
|
182
|
+
}
|
|
183
|
+
if (!patterns.length) return [];
|
|
184
|
+
const dirs = await glob(patterns, {
|
|
185
|
+
cwd,
|
|
186
|
+
onlyDirectories: true,
|
|
187
|
+
absolute: true,
|
|
188
|
+
ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"]
|
|
189
|
+
});
|
|
190
|
+
const pkgJsonPaths = [];
|
|
191
|
+
for (const dir of dirs) {
|
|
192
|
+
const pj = path.join(dir, "package.json");
|
|
193
|
+
if (await fs.pathExists(pj)) pkgJsonPaths.push(pj);
|
|
194
|
+
}
|
|
195
|
+
return pkgJsonPaths;
|
|
196
|
+
}
|
|
197
|
+
export async function isMonorepo(cwd) {
|
|
198
|
+
try {
|
|
199
|
+
const root = await readPackageJSON(cwd);
|
|
200
|
+
const ws = root.workspaces;
|
|
201
|
+
if (Array.isArray(ws) && ws.length > 0) {
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
if (ws && Array.isArray(ws.packages) && ws.packages.length > 0) {
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
return false;
|
|
208
|
+
} catch {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
export async function findAllPackageJsons(cwd) {
|
|
213
|
+
const packageJsonFiles = await glob("**/package.json", {
|
|
214
|
+
cwd,
|
|
215
|
+
absolute: true,
|
|
216
|
+
ignore: [
|
|
217
|
+
"**/node_modules/**",
|
|
218
|
+
"**/dist/**",
|
|
219
|
+
"**/build/**",
|
|
220
|
+
"**/.git/**",
|
|
221
|
+
"**/coverage/**",
|
|
222
|
+
"**/.next/**",
|
|
223
|
+
"**/.nuxt/**",
|
|
224
|
+
"**/out/**"
|
|
225
|
+
]
|
|
226
|
+
});
|
|
227
|
+
const existingFiles = [];
|
|
228
|
+
for (const file of packageJsonFiles) {
|
|
229
|
+
if (await fs.pathExists(file)) {
|
|
230
|
+
existingFiles.push(file);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return existingFiles;
|
|
234
|
+
}
|
|
235
|
+
export async function fetchVersionFromRegistry(packageName) {
|
|
236
|
+
const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`);
|
|
237
|
+
if (!response.ok) {
|
|
238
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
239
|
+
}
|
|
240
|
+
const data = await response.json();
|
|
241
|
+
return data.version;
|
|
242
|
+
}
|
|
243
|
+
export async function getLatestVersion(packageName) {
|
|
244
|
+
const cached = versionCache.get(packageName);
|
|
245
|
+
const now = Date.now();
|
|
246
|
+
if (cached && now - cached.timestamp < CACHE_TTL) {
|
|
247
|
+
return cached.version;
|
|
248
|
+
}
|
|
249
|
+
try {
|
|
250
|
+
const version = await latestVersion(packageName);
|
|
251
|
+
versionCache.set(packageName, { version, timestamp: now });
|
|
252
|
+
return version;
|
|
253
|
+
} catch (error) {
|
|
254
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
255
|
+
try {
|
|
256
|
+
const version = await fetchVersionFromRegistry(packageName);
|
|
257
|
+
versionCache.set(packageName, { version, timestamp: now });
|
|
258
|
+
return version;
|
|
259
|
+
} catch (fallbackError) {
|
|
260
|
+
throw new Error(
|
|
261
|
+
`Latest version main check and npm registry fallback failed. Main check error: ${errorMessage}. Registry error: ${fallbackError instanceof Error ? fallbackError.message : String(fallbackError)}`
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
export async function checkPackageUpdate(packageName, versionSpec, locations, options) {
|
|
267
|
+
try {
|
|
268
|
+
const latest = await getLatestVersion(packageName);
|
|
269
|
+
const cleanCurrent = versionSpec.replace(/^[\^~]/, "");
|
|
270
|
+
let isCompatible = isSemverCompatible(versionSpec, latest);
|
|
271
|
+
const isExact = !versionSpec.startsWith("^") && !versionSpec.startsWith("~");
|
|
272
|
+
if (isExact || !isCompatible && options.allowMajor) {
|
|
273
|
+
isCompatible = true;
|
|
274
|
+
}
|
|
275
|
+
return {
|
|
276
|
+
package: packageName,
|
|
277
|
+
currentVersion: cleanCurrent,
|
|
278
|
+
latestVersion: latest,
|
|
279
|
+
updated: latest !== cleanCurrent && isCompatible,
|
|
280
|
+
semverCompatible: isCompatible,
|
|
281
|
+
location: Array.from(locations).join(", ")
|
|
282
|
+
};
|
|
283
|
+
} catch (error) {
|
|
284
|
+
return {
|
|
285
|
+
package: packageName,
|
|
286
|
+
currentVersion: versionSpec,
|
|
287
|
+
latestVersion: versionSpec,
|
|
288
|
+
updated: false,
|
|
289
|
+
error: error instanceof Error ? error.message : String(error),
|
|
290
|
+
semverCompatible: false,
|
|
291
|
+
location: Array.from(locations).join(", ")
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
export function prepareDependenciesForUpdate(allDepsMap, args) {
|
|
296
|
+
const depsToUpdate = Object.keys(allDepsMap);
|
|
297
|
+
let filteredDeps = [];
|
|
298
|
+
if (args.name && args.name.length > 0) {
|
|
299
|
+
filteredDeps = args.name.filter((dep) => dep in allDepsMap);
|
|
300
|
+
const notFound = args.name.filter((dep) => !(dep in allDepsMap));
|
|
301
|
+
if (notFound.length > 0) {
|
|
302
|
+
relinka("warn", `Dependencies not found: ${notFound.join(", ")}`);
|
|
303
|
+
}
|
|
304
|
+
} else {
|
|
305
|
+
const ignoreList = args.ignore || [];
|
|
306
|
+
filteredDeps = depsToUpdate.filter((dep) => !ignoreList.includes(dep));
|
|
307
|
+
}
|
|
308
|
+
return filteredDeps.filter((dep) => {
|
|
309
|
+
const versionSpec = allDepsMap[dep]?.versionSpec ?? "";
|
|
310
|
+
if (!versionSpec) return false;
|
|
311
|
+
if (isNonSemverSpecifier(versionSpec)) return false;
|
|
312
|
+
return true;
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
export async function updatePackageJsonFile(packageJsonPath, dependencies, updatesToApply, savePrefix) {
|
|
316
|
+
if (updatesToApply.length === 0) return 0;
|
|
317
|
+
try {
|
|
318
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf8"));
|
|
319
|
+
const updatedPackageJson = { ...packageJson };
|
|
320
|
+
for (const update of updatesToApply) {
|
|
321
|
+
const prefix = savePrefix === "none" ? "" : savePrefix;
|
|
322
|
+
const newVersion = `${prefix}${update.latestVersion}`;
|
|
323
|
+
const locations = dependencies[update.package]?.locations || /* @__PURE__ */ new Set();
|
|
324
|
+
applyVersionUpdate(updatedPackageJson, update.package, newVersion, locations);
|
|
325
|
+
}
|
|
326
|
+
await fs.writeFile(packageJsonPath, JSON.stringify(updatedPackageJson, null, 2) + "\n", "utf8");
|
|
327
|
+
return updatesToApply.length;
|
|
328
|
+
} catch (error) {
|
|
329
|
+
relinka(
|
|
330
|
+
"warn",
|
|
331
|
+
`Failed to update ${packageJsonPath}: ${error instanceof Error ? error.message : String(error)}`
|
|
332
|
+
);
|
|
333
|
+
return 0;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
export async function updateWorkspacePackages(workspacePaths, args, options) {
|
|
337
|
+
if (workspacePaths.length === 0) return 0;
|
|
338
|
+
relinka("log", `Scanning ${workspacePaths.length} workspace packages...`);
|
|
339
|
+
let totalWorkspaceUpdated = 0;
|
|
340
|
+
for (const packageJsonPath of workspacePaths) {
|
|
341
|
+
try {
|
|
342
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf8"));
|
|
343
|
+
const { map } = collectTargetDependencies(packageJson, args);
|
|
344
|
+
const candidates = prepareDependenciesForUpdate(map, args);
|
|
345
|
+
if (candidates.length === 0) continue;
|
|
346
|
+
const results = await pMap(
|
|
347
|
+
candidates,
|
|
348
|
+
(dep) => {
|
|
349
|
+
const depInfo = map[dep];
|
|
350
|
+
if (!depInfo?.versionSpec) {
|
|
351
|
+
return Promise.resolve({
|
|
352
|
+
package: dep,
|
|
353
|
+
currentVersion: "unknown",
|
|
354
|
+
latestVersion: "unknown",
|
|
355
|
+
updated: false,
|
|
356
|
+
error: "Current version not found",
|
|
357
|
+
semverCompatible: false,
|
|
358
|
+
location: Array.from(depInfo?.locations || ["unknown"]).join(", ")
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
return checkPackageUpdate(dep, depInfo.versionSpec, depInfo.locations, options);
|
|
362
|
+
},
|
|
363
|
+
{ concurrency: options.concurrency }
|
|
364
|
+
);
|
|
365
|
+
const toUpdate = results.filter((r) => r.updated && !r.error);
|
|
366
|
+
const updated = await updatePackageJsonFile(
|
|
367
|
+
packageJsonPath,
|
|
368
|
+
map,
|
|
369
|
+
toUpdate,
|
|
370
|
+
options.savePrefix
|
|
371
|
+
);
|
|
372
|
+
if (updated > 0) {
|
|
373
|
+
totalWorkspaceUpdated += updated;
|
|
374
|
+
relinka("log", `Updated ${updated} deps in ${packageJsonPath}`);
|
|
375
|
+
}
|
|
376
|
+
} catch (error) {
|
|
377
|
+
relinka(
|
|
378
|
+
"warn",
|
|
379
|
+
`Skipping ${packageJsonPath}: ${error instanceof Error ? error.message : String(error)}`
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
return totalWorkspaceUpdated;
|
|
384
|
+
}
|
|
385
|
+
export function displayUpdateResults(results) {
|
|
386
|
+
const toUpdate = results.filter((r) => r.updated && !r.error);
|
|
387
|
+
const errors = results.filter((r) => r.error);
|
|
388
|
+
const upToDate = results.filter((r) => !r.updated && !r.error && r.semverCompatible);
|
|
389
|
+
if (errors.length > 0) {
|
|
390
|
+
relinka("warn", `Failed to check ${errors.length} dependencies:`);
|
|
391
|
+
for (const error of errors) {
|
|
392
|
+
relinka("warn", ` ${error.package} (${error.location}): ${error.error}`);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
if (upToDate.length > 0) {
|
|
396
|
+
relinka("log", `${upToDate.length} deps are already up to date`);
|
|
397
|
+
}
|
|
398
|
+
if (toUpdate.length === 0) {
|
|
399
|
+
relinka("verbose", `All ${upToDate.length} deps are already up to date`);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
relinka("log", `${toUpdate.length} deps can be updated:`);
|
|
403
|
+
const byLocation = /* @__PURE__ */ new Map();
|
|
404
|
+
for (const update of toUpdate) {
|
|
405
|
+
const location = update.location || "unknown";
|
|
406
|
+
if (!byLocation.has(location)) {
|
|
407
|
+
byLocation.set(location, []);
|
|
408
|
+
}
|
|
409
|
+
byLocation.get(location).push(update);
|
|
410
|
+
}
|
|
411
|
+
for (const [location, updates] of byLocation.entries()) {
|
|
412
|
+
relinka("log", ` ${location}:`);
|
|
413
|
+
for (const update of updates) {
|
|
414
|
+
relinka("log", ` ${update.package}: ${update.currentVersion} \u2192 ${update.latestVersion}`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
export async function getGlobalPackages(packageManager) {
|
|
419
|
+
try {
|
|
420
|
+
let result;
|
|
421
|
+
if (packageManager === "npm") {
|
|
422
|
+
result = await $`npm list -g --depth=0 --json`.json();
|
|
423
|
+
} else if (packageManager === "yarn") {
|
|
424
|
+
try {
|
|
425
|
+
result = await $`yarn global list --json`.json();
|
|
426
|
+
} catch {
|
|
427
|
+
result = await $`yarn global list`.text();
|
|
428
|
+
const packages2 = {};
|
|
429
|
+
const lines = result.split("\n");
|
|
430
|
+
for (const line of lines) {
|
|
431
|
+
const match = line.match(/^(.+)@([^@]+)$/);
|
|
432
|
+
if (match) {
|
|
433
|
+
packages2[match[1]] = match[2];
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
return packages2;
|
|
437
|
+
}
|
|
438
|
+
} else if (packageManager === "pnpm") {
|
|
439
|
+
result = await $`pnpm list -g --depth=0 --json`.json();
|
|
440
|
+
} else if (packageManager === "bun") {
|
|
441
|
+
result = await $`bun pm ls -g --json`.json();
|
|
442
|
+
} else {
|
|
443
|
+
throw new Error(`Unsupported package manager: ${packageManager}`);
|
|
444
|
+
}
|
|
445
|
+
const dependencies = result?.dependencies || {};
|
|
446
|
+
const packages = {};
|
|
447
|
+
for (const [name, info] of Object.entries(dependencies)) {
|
|
448
|
+
if (info && typeof info === "object" && "version" in info) {
|
|
449
|
+
packages[name] = info.version;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
return packages;
|
|
453
|
+
} catch (error) {
|
|
454
|
+
relinka("warn", `Failed to get global packages for ${packageManager}: ${error}`);
|
|
455
|
+
return {};
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
export async function runInstallCommand(packageManager, linker) {
|
|
459
|
+
try {
|
|
460
|
+
switch (packageManager.name) {
|
|
461
|
+
case "bun": {
|
|
462
|
+
const linkerArg = linker ? `--linker ${linker}` : "";
|
|
463
|
+
await $`bun install ${linkerArg}`;
|
|
464
|
+
break;
|
|
465
|
+
}
|
|
466
|
+
case "npm":
|
|
467
|
+
await $`npm install`;
|
|
468
|
+
break;
|
|
469
|
+
case "yarn":
|
|
470
|
+
await $`yarn install`;
|
|
471
|
+
break;
|
|
472
|
+
case "pnpm":
|
|
473
|
+
await $`pnpm install`;
|
|
474
|
+
break;
|
|
475
|
+
case "deno":
|
|
476
|
+
await $`deno cache --reload import_map.json`;
|
|
477
|
+
break;
|
|
478
|
+
default:
|
|
479
|
+
throw new Error(`Unsupported package manager: ${packageManager.name}`);
|
|
480
|
+
}
|
|
481
|
+
} catch (error) {
|
|
482
|
+
relinka("warn", `Failed to run install command for ${packageManager.name}: ${error}`);
|
|
483
|
+
throw error;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
export async function runInstallCommandWithFilter(packageManager, linker, filterArgs = []) {
|
|
487
|
+
try {
|
|
488
|
+
switch (packageManager.name) {
|
|
489
|
+
case "bun": {
|
|
490
|
+
const linkerArg = linker ? `--linker ${linker}` : "";
|
|
491
|
+
const filterStr = filterArgs.join(" ");
|
|
492
|
+
await $`bun install ${linkerArg} ${filterStr}`;
|
|
493
|
+
break;
|
|
494
|
+
}
|
|
495
|
+
case "npm": {
|
|
496
|
+
const npmFilterStr = filterArgs.join(" ");
|
|
497
|
+
await $`npm install ${npmFilterStr}`;
|
|
498
|
+
break;
|
|
499
|
+
}
|
|
500
|
+
case "yarn": {
|
|
501
|
+
const yarnFilterStr = filterArgs.join(" ");
|
|
502
|
+
await $`yarn install ${yarnFilterStr}`;
|
|
503
|
+
break;
|
|
504
|
+
}
|
|
505
|
+
case "pnpm": {
|
|
506
|
+
const pnpmFilterStr = filterArgs.join(" ");
|
|
507
|
+
await $`pnpm install ${pnpmFilterStr}`;
|
|
508
|
+
break;
|
|
509
|
+
}
|
|
510
|
+
case "deno":
|
|
511
|
+
await $`deno cache --reload import_map.json`;
|
|
512
|
+
break;
|
|
513
|
+
default:
|
|
514
|
+
throw new Error(`Unsupported package manager: ${packageManager.name}`);
|
|
515
|
+
}
|
|
516
|
+
} catch (error) {
|
|
517
|
+
relinka("warn", `Failed to run install command for ${packageManager.name}: ${error}`);
|
|
518
|
+
throw error;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
export async function updateGlobalPackage(packageManager, packageName) {
|
|
522
|
+
try {
|
|
523
|
+
if (packageManager === "npm") {
|
|
524
|
+
await $`npm install -g ${packageName}@latest`;
|
|
525
|
+
} else if (packageManager === "yarn") {
|
|
526
|
+
await $`yarn global add ${packageName}@latest`;
|
|
527
|
+
} else if (packageManager === "pnpm") {
|
|
528
|
+
await $`pnpm add -g ${packageName}@latest`;
|
|
529
|
+
} else if (packageManager === "bun") {
|
|
530
|
+
await $`bun install -g ${packageName}@latest`;
|
|
531
|
+
} else {
|
|
532
|
+
throw new Error(`Unsupported package manager: ${packageManager}`);
|
|
533
|
+
}
|
|
534
|
+
return true;
|
|
535
|
+
} catch (error) {
|
|
536
|
+
relinka(
|
|
537
|
+
"warn",
|
|
538
|
+
`Failed to update global package ${packageName} with ${packageManager}: ${error}`
|
|
539
|
+
);
|
|
540
|
+
return false;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
export async function handleGlobalUpdates(args) {
|
|
544
|
+
const packageManagers = ["bun", "npm", "yarn", "pnpm"];
|
|
545
|
+
const availablePackageManagers = [];
|
|
546
|
+
for (const pm of packageManagers) {
|
|
547
|
+
if (await lookpath(pm)) {
|
|
548
|
+
availablePackageManagers.push(pm);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
if (availablePackageManagers.length === 0) {
|
|
552
|
+
relinka("error", "No supported package managers found");
|
|
553
|
+
return process.exit(1);
|
|
554
|
+
}
|
|
555
|
+
relinka("log", `Found package managers: ${availablePackageManagers.join(", ")}`);
|
|
556
|
+
const allGlobalPackages = {};
|
|
557
|
+
for (const pm of availablePackageManagers) {
|
|
558
|
+
const packages = await getGlobalPackages(pm);
|
|
559
|
+
for (const [name, version] of Object.entries(packages)) {
|
|
560
|
+
if (!allGlobalPackages[name] || semver.gt(version, allGlobalPackages[name].version)) {
|
|
561
|
+
allGlobalPackages[name] = { version, packageManager: pm };
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
const globalPackageNames = Object.keys(allGlobalPackages);
|
|
566
|
+
if (globalPackageNames.length === 0) {
|
|
567
|
+
relinka("warn", "No global packages found");
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
570
|
+
let filteredPackages = [];
|
|
571
|
+
if (args.name && args.name.length > 0) {
|
|
572
|
+
filteredPackages = args.name.filter((pkg) => pkg in allGlobalPackages);
|
|
573
|
+
const notFound = args.name.filter((pkg) => !(pkg in allGlobalPackages));
|
|
574
|
+
if (notFound.length > 0) {
|
|
575
|
+
relinka("warn", `Global packages not found: ${notFound.join(", ")}`);
|
|
576
|
+
}
|
|
577
|
+
} else {
|
|
578
|
+
const ignoreList = args.ignore || [];
|
|
579
|
+
filteredPackages = globalPackageNames.filter((pkg) => !ignoreList.includes(pkg));
|
|
580
|
+
}
|
|
581
|
+
if (filteredPackages.length === 0) {
|
|
582
|
+
relinka("warn", "No global packages to update");
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
relinka("log", `Checking ${filteredPackages.length} global packages for updates...`);
|
|
586
|
+
const results = await pMap(
|
|
587
|
+
filteredPackages,
|
|
588
|
+
async (packageName) => {
|
|
589
|
+
const globalPackage = allGlobalPackages[packageName];
|
|
590
|
+
if (!globalPackage) {
|
|
591
|
+
return {
|
|
592
|
+
package: packageName,
|
|
593
|
+
currentVersion: "unknown",
|
|
594
|
+
latestVersion: "unknown",
|
|
595
|
+
updated: false,
|
|
596
|
+
error: "Package not found in global packages",
|
|
597
|
+
location: "global"
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
try {
|
|
601
|
+
const latest = await getLatestVersion(packageName);
|
|
602
|
+
const needsUpdate = semver.gt(latest, globalPackage.version);
|
|
603
|
+
return {
|
|
604
|
+
package: packageName,
|
|
605
|
+
currentVersion: globalPackage.version,
|
|
606
|
+
latestVersion: latest,
|
|
607
|
+
updated: needsUpdate,
|
|
608
|
+
location: `global (${globalPackage.packageManager})`
|
|
609
|
+
};
|
|
610
|
+
} catch (error) {
|
|
611
|
+
return {
|
|
612
|
+
package: packageName,
|
|
613
|
+
currentVersion: globalPackage.version,
|
|
614
|
+
latestVersion: globalPackage.version,
|
|
615
|
+
updated: false,
|
|
616
|
+
error: error instanceof Error ? error.message : String(error),
|
|
617
|
+
location: `global (${globalPackage.packageManager})`
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
},
|
|
621
|
+
{ concurrency: args.concurrency }
|
|
622
|
+
);
|
|
623
|
+
let toUpdate = results.filter((r) => r.updated && !r.error);
|
|
624
|
+
const errors = results.filter((r) => r.error);
|
|
625
|
+
const upToDate = results.filter((r) => !r.updated && !r.error);
|
|
626
|
+
if (errors.length > 0) {
|
|
627
|
+
relinka("warn", `Failed to check ${errors.length} global packages:`);
|
|
628
|
+
for (const error of errors) {
|
|
629
|
+
relinka("warn", ` ${error.package} (${error.location}): ${error.error}`);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
if (upToDate.length > 0) {
|
|
633
|
+
relinka("log", `${upToDate.length} global packages are up to date`);
|
|
634
|
+
}
|
|
635
|
+
if (toUpdate.length === 0) {
|
|
636
|
+
relinka("log", "All global packages are up to date");
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
relinka("log", `${toUpdate.length} global packages can be updated:`);
|
|
640
|
+
for (const update of toUpdate) {
|
|
641
|
+
relinka(
|
|
642
|
+
"log",
|
|
643
|
+
` ${update.package} (${update.location}): ${update.currentVersion} \u2192 ${update.latestVersion}`
|
|
644
|
+
);
|
|
645
|
+
}
|
|
646
|
+
if (args.interactive) {
|
|
647
|
+
const allGlobalPackages2 = [
|
|
648
|
+
...toUpdate.map((pkg) => ({ ...pkg, canUpdate: true, isUpToDate: false, hasError: false })),
|
|
649
|
+
...upToDate.map((pkg) => ({ ...pkg, canUpdate: false, isUpToDate: true, hasError: false })),
|
|
650
|
+
...errors.map((pkg) => ({ ...pkg, canUpdate: false, isUpToDate: false, hasError: true }))
|
|
651
|
+
];
|
|
652
|
+
const selectedPackages = await multiselectPrompt({
|
|
653
|
+
title: "Select global packages to update",
|
|
654
|
+
options: [
|
|
655
|
+
{ label: "Exit", value: "exit" },
|
|
656
|
+
...allGlobalPackages2.map((pkg) => {
|
|
657
|
+
let label = `${pkg.package} (${pkg.location})`;
|
|
658
|
+
if (pkg.canUpdate) {
|
|
659
|
+
label += `: ${pkg.currentVersion} \u2192 ${pkg.latestVersion}`;
|
|
660
|
+
} else if (pkg.isUpToDate) {
|
|
661
|
+
label += `: ${pkg.currentVersion} (up-to-date)`;
|
|
662
|
+
} else if (pkg.hasError) {
|
|
663
|
+
label += `: ${pkg.currentVersion} (has errors)`;
|
|
664
|
+
}
|
|
665
|
+
return {
|
|
666
|
+
label,
|
|
667
|
+
value: pkg.package,
|
|
668
|
+
disabled: !pkg.canUpdate,
|
|
669
|
+
hint: pkg.hasError ? pkg.error : void 0
|
|
670
|
+
};
|
|
671
|
+
})
|
|
672
|
+
]
|
|
673
|
+
});
|
|
674
|
+
if (selectedPackages.length === 0 || selectedPackages.includes("exit")) {
|
|
675
|
+
relinka("log", "Exiting global update process");
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
const actualSelectedPackages = selectedPackages.filter((pkg) => pkg !== "exit");
|
|
679
|
+
toUpdate = toUpdate.filter((update) => actualSelectedPackages.includes(update.package));
|
|
680
|
+
relinka("log", `Updating ${actualSelectedPackages.length} selected global packages...`);
|
|
681
|
+
}
|
|
682
|
+
if (args["dry-run"]) {
|
|
683
|
+
relinka("log", "Dry run mode - no changes were made");
|
|
684
|
+
return;
|
|
685
|
+
}
|
|
686
|
+
let successCount = 0;
|
|
687
|
+
for (const update of toUpdate) {
|
|
688
|
+
const globalPackage = allGlobalPackages[update.package];
|
|
689
|
+
if (globalPackage && await updateGlobalPackage(globalPackage.packageManager, update.package)) {
|
|
690
|
+
successCount++;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
relinka("log", `Successfully updated ${successCount}/${toUpdate.length} global packages`);
|
|
694
|
+
}
|
|
695
|
+
export async function getPmOptions() {
|
|
696
|
+
const projectPath = getCurrentWorkingDirectory();
|
|
697
|
+
const detectedPMs = await getAllPkgManagers(projectPath);
|
|
698
|
+
const detectedPMMap = new Map(detectedPMs.map((pm) => [pm.packageManager, pm.source]));
|
|
699
|
+
const pmOptions = ["bun", "pnpm", "npm", "yarn"].map((pm) => {
|
|
700
|
+
const option = {
|
|
701
|
+
label: pm,
|
|
702
|
+
value: pm
|
|
703
|
+
};
|
|
704
|
+
const source = detectedPMMap.get(pm);
|
|
705
|
+
if (source && source !== "default") {
|
|
706
|
+
option.hint = "detected";
|
|
707
|
+
}
|
|
708
|
+
return option;
|
|
709
|
+
});
|
|
710
|
+
const defaultValue = [...detectedPMMap.keys()][0] ?? "npm";
|
|
711
|
+
return { pmOptions, defaultValue };
|
|
712
|
+
}
|
|
713
|
+
export async function upgradeDlerLocal() {
|
|
714
|
+
try {
|
|
715
|
+
const pkg = await readPackageJSON();
|
|
716
|
+
const hasDler = pkg.dependencies && "@reliverse/dler" in pkg.dependencies || pkg.devDependencies && "@reliverse/dler" in pkg.devDependencies;
|
|
717
|
+
if (!hasDler) {
|
|
718
|
+
return { tool: "dler (local)", status: "not-found" };
|
|
719
|
+
}
|
|
720
|
+
const packageManager = await detectPackageManager(process.cwd());
|
|
721
|
+
if (!packageManager) {
|
|
722
|
+
return { tool: "dler (local)", status: "error", message: "No package manager detected" };
|
|
723
|
+
}
|
|
724
|
+
const { exitCode } = await x(packageManager.command, ["update", "@reliverse/dler"], {
|
|
725
|
+
nodeOptions: { stdio: "pipe" }
|
|
726
|
+
});
|
|
727
|
+
return exitCode === 0 ? { tool: "dler (local)", status: "upgraded", message: `via ${packageManager.command}` } : { tool: "dler (local)", status: "error", message: "Upgrade failed" };
|
|
728
|
+
} catch (error) {
|
|
729
|
+
return {
|
|
730
|
+
tool: "dler (local)",
|
|
731
|
+
status: "not-found"
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
export async function upgradeDlerGlobal() {
|
|
736
|
+
try {
|
|
737
|
+
const dlerPath = await lookpath("dler");
|
|
738
|
+
if (!dlerPath) {
|
|
739
|
+
return { tool: "dler (global)", status: "not-found" };
|
|
740
|
+
}
|
|
741
|
+
const packageManagers = ["bun", "npm", "yarn", "pnpm"];
|
|
742
|
+
for (const pm of packageManagers) {
|
|
743
|
+
const pmPath = await lookpath(pm);
|
|
744
|
+
if (pmPath) {
|
|
745
|
+
try {
|
|
746
|
+
const args = pm === "npm" ? ["install", "-g", "@reliverse/dler@latest"] : pm === "yarn" ? ["global", "add", "@reliverse/dler@latest"] : ["install", "-g", "@reliverse/dler@latest"];
|
|
747
|
+
const { exitCode } = await x(pm, args, {
|
|
748
|
+
nodeOptions: { stdio: "pipe" }
|
|
749
|
+
});
|
|
750
|
+
if (exitCode === 0) {
|
|
751
|
+
return { tool: "dler (global)", status: "upgraded", message: `via ${pm}` };
|
|
752
|
+
}
|
|
753
|
+
} catch {
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
return { tool: "dler (global)", status: "error", message: "No suitable package manager found" };
|
|
758
|
+
} catch (error) {
|
|
759
|
+
return { tool: "dler (global)", status: "error", message: String(error) };
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
export async function upgradeGit() {
|
|
763
|
+
try {
|
|
764
|
+
const gitPath = await lookpath("git");
|
|
765
|
+
if (!gitPath) {
|
|
766
|
+
return { tool: "git", status: "not-found" };
|
|
767
|
+
}
|
|
768
|
+
const { stdout } = await x("git", ["--version"], {
|
|
769
|
+
nodeOptions: { stdio: "pipe" }
|
|
770
|
+
});
|
|
771
|
+
return {
|
|
772
|
+
tool: "git",
|
|
773
|
+
status: "up-to-date",
|
|
774
|
+
message: `${stdout.trim()} - manual upgrade required`
|
|
775
|
+
};
|
|
776
|
+
} catch (error) {
|
|
777
|
+
return { tool: "git", status: "error", message: String(error) };
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
export async function upgradeNode() {
|
|
781
|
+
try {
|
|
782
|
+
const nodePath = await lookpath("node");
|
|
783
|
+
if (!nodePath) {
|
|
784
|
+
return { tool: "node.js", status: "not-found" };
|
|
785
|
+
}
|
|
786
|
+
const { stdout } = await x("node", ["--version"], {
|
|
787
|
+
nodeOptions: { stdio: "pipe" }
|
|
788
|
+
});
|
|
789
|
+
return {
|
|
790
|
+
tool: "node.js",
|
|
791
|
+
status: "up-to-date",
|
|
792
|
+
message: `${stdout.trim()} - manual upgrade required`
|
|
793
|
+
};
|
|
794
|
+
} catch (error) {
|
|
795
|
+
return { tool: "node.js", status: "error", message: String(error) };
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
export async function upgradeNpm() {
|
|
799
|
+
try {
|
|
800
|
+
const npmPath = await lookpath("npm");
|
|
801
|
+
if (!npmPath) {
|
|
802
|
+
return { tool: "npm", status: "not-found" };
|
|
803
|
+
}
|
|
804
|
+
try {
|
|
805
|
+
const { exitCode, stdout, stderr } = await x("npm", ["install", "-g", "npm@latest"], {
|
|
806
|
+
nodeOptions: { stdio: "pipe" }
|
|
807
|
+
});
|
|
808
|
+
if (exitCode === 0) {
|
|
809
|
+
const output = (stdout + stderr).toLowerCase();
|
|
810
|
+
if (output.includes("unchanged") || output.includes("up-to-date") || output.includes("already")) {
|
|
811
|
+
return { tool: "npm", status: "up-to-date" };
|
|
812
|
+
}
|
|
813
|
+
return { tool: "npm", status: "upgraded" };
|
|
814
|
+
} else {
|
|
815
|
+
return { tool: "npm", status: "error", message: "Upgrade failed" };
|
|
816
|
+
}
|
|
817
|
+
} catch (pipeError) {
|
|
818
|
+
const { exitCode } = await x("npm", ["install", "-g", "npm@latest"], {
|
|
819
|
+
nodeOptions: { stdio: "inherit" }
|
|
820
|
+
});
|
|
821
|
+
return exitCode === 0 ? { tool: "npm", status: "upgraded" } : { tool: "npm", status: "error", message: "Upgrade failed" };
|
|
822
|
+
}
|
|
823
|
+
} catch (error) {
|
|
824
|
+
return { tool: "npm", status: "error", message: String(error) };
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
export async function upgradeBun() {
|
|
828
|
+
try {
|
|
829
|
+
const bunPath = await lookpath("bun");
|
|
830
|
+
if (!bunPath) {
|
|
831
|
+
return { tool: "bun", status: "not-found" };
|
|
832
|
+
}
|
|
833
|
+
const { exitCode, stdout, stderr } = await x("bun", ["upgrade"], {
|
|
834
|
+
nodeOptions: { stdio: "pipe" }
|
|
835
|
+
});
|
|
836
|
+
if (exitCode !== 0) {
|
|
837
|
+
return { tool: "bun", status: "error", message: "Upgrade failed" };
|
|
838
|
+
}
|
|
839
|
+
const output = (stdout + stderr).toLowerCase();
|
|
840
|
+
if (output.includes("already") || output.includes("up-to-date") || output.includes("latest")) {
|
|
841
|
+
return { tool: "bun", status: "up-to-date" };
|
|
842
|
+
}
|
|
843
|
+
return { tool: "bun", status: "upgraded" };
|
|
844
|
+
} catch (error) {
|
|
845
|
+
return { tool: "bun", status: "error", message: String(error) };
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
export async function upgradeYarn() {
|
|
849
|
+
try {
|
|
850
|
+
const yarnPath = await lookpath("yarn");
|
|
851
|
+
if (!yarnPath) {
|
|
852
|
+
return { tool: "yarn", status: "not-found" };
|
|
853
|
+
}
|
|
854
|
+
try {
|
|
855
|
+
const { exitCode: upgradeResult } = await x("yarn", ["self-update"], {
|
|
856
|
+
nodeOptions: { stdio: "pipe" }
|
|
857
|
+
});
|
|
858
|
+
if (upgradeResult === 0) {
|
|
859
|
+
return { tool: "yarn", status: "upgraded", message: "self-update" };
|
|
860
|
+
}
|
|
861
|
+
} catch {
|
|
862
|
+
}
|
|
863
|
+
const npmPath = await lookpath("npm");
|
|
864
|
+
if (npmPath) {
|
|
865
|
+
const { exitCode } = await x("npm", ["install", "-g", "yarn@latest"], {
|
|
866
|
+
nodeOptions: { stdio: "pipe" }
|
|
867
|
+
});
|
|
868
|
+
return exitCode === 0 ? { tool: "yarn", status: "upgraded", message: "via npm" } : { tool: "yarn", status: "error", message: "Upgrade failed" };
|
|
869
|
+
}
|
|
870
|
+
return { tool: "yarn", status: "error", message: "No upgrade method available" };
|
|
871
|
+
} catch (error) {
|
|
872
|
+
return { tool: "yarn", status: "error", message: String(error) };
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
export async function upgradePnpm() {
|
|
876
|
+
try {
|
|
877
|
+
const pnpmPath = await lookpath("pnpm");
|
|
878
|
+
if (!pnpmPath) {
|
|
879
|
+
return { tool: "pnpm", status: "not-found" };
|
|
880
|
+
}
|
|
881
|
+
try {
|
|
882
|
+
const { exitCode } = await x("pnpm", ["add", "-g", "pnpm@latest"], {
|
|
883
|
+
nodeOptions: { stdio: "pipe" }
|
|
884
|
+
});
|
|
885
|
+
return exitCode === 0 ? { tool: "pnpm", status: "upgraded" } : { tool: "pnpm", status: "error", message: "Upgrade failed" };
|
|
886
|
+
} catch {
|
|
887
|
+
const npmPath = await lookpath("npm");
|
|
888
|
+
if (npmPath) {
|
|
889
|
+
const { exitCode } = await x("npm", ["install", "-g", "pnpm@latest"], {
|
|
890
|
+
nodeOptions: { stdio: "pipe" }
|
|
891
|
+
});
|
|
892
|
+
return exitCode === 0 ? { tool: "pnpm", status: "upgraded", message: "via npm" } : { tool: "pnpm", status: "error", message: "Upgrade failed" };
|
|
893
|
+
}
|
|
894
|
+
return { tool: "pnpm", status: "error", message: "No upgrade method available" };
|
|
895
|
+
}
|
|
896
|
+
} catch (error) {
|
|
897
|
+
return { tool: "pnpm", status: "error", message: String(error) };
|
|
898
|
+
}
|
|
899
|
+
}
|