@reliverse/dler 1.7.82 → 1.7.83
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/update/cmd.d.ts +12 -1
- package/bin/app/update/cmd.js +399 -247
- package/bin/libs/sdk/sdk-impl/config/info.js +1 -1
- package/package.json +3 -3
package/bin/app/update/cmd.d.ts
CHANGED
|
@@ -64,9 +64,20 @@ declare const _default: import("@reliverse/rempts").Command<{
|
|
|
64
64
|
type: "array";
|
|
65
65
|
description: string;
|
|
66
66
|
};
|
|
67
|
-
"
|
|
67
|
+
"all-workspaces": {
|
|
68
68
|
type: "boolean";
|
|
69
69
|
description: string;
|
|
70
70
|
};
|
|
71
|
+
"save-prefix": {
|
|
72
|
+
type: "string";
|
|
73
|
+
description: string;
|
|
74
|
+
allowed: string[];
|
|
75
|
+
default: string;
|
|
76
|
+
};
|
|
77
|
+
"allow-major": {
|
|
78
|
+
type: "boolean";
|
|
79
|
+
description: string;
|
|
80
|
+
default: true;
|
|
81
|
+
};
|
|
71
82
|
}>;
|
|
72
83
|
export default _default;
|
package/bin/app/update/cmd.js
CHANGED
|
@@ -7,16 +7,25 @@ import { lookpath } from "lookpath";
|
|
|
7
7
|
import pMap from "p-map";
|
|
8
8
|
import { readPackageJSON } from "pkg-types";
|
|
9
9
|
import semver from "semver";
|
|
10
|
+
import { glob } from "tinyglobby";
|
|
10
11
|
import { getConfigBunfig } from "../../libs/sdk/sdk-impl/config/load.js";
|
|
11
12
|
import { updateCatalogs, isCatalogSupported } from "../../libs/sdk/sdk-impl/utils/pm/pm-catalog.js";
|
|
12
13
|
import { detectPackageManager } from "../../libs/sdk/sdk-impl/utils/pm/pm-detect.js";
|
|
13
14
|
import { latestVersion } from "../../libs/sdk/sdk-impl/utils/pm/pm-meta.js";
|
|
15
|
+
const versionCache = /* @__PURE__ */ new Map();
|
|
16
|
+
const CACHE_TTL = 5 * 60 * 1e3;
|
|
14
17
|
function isNpmAlias(versionSpec) {
|
|
15
18
|
return versionSpec.startsWith("npm:");
|
|
16
19
|
}
|
|
17
20
|
function isWorkspaceDependency(versionSpec) {
|
|
18
21
|
return versionSpec.startsWith("workspace:");
|
|
19
22
|
}
|
|
23
|
+
function isCatalogReference(versionSpec) {
|
|
24
|
+
return versionSpec.startsWith("catalog:");
|
|
25
|
+
}
|
|
26
|
+
function isNonSemverSpecifier(versionSpec) {
|
|
27
|
+
return isNpmAlias(versionSpec) || isWorkspaceDependency(versionSpec) || isCatalogReference(versionSpec) || versionSpec.startsWith("git+") || versionSpec.startsWith("file:") || versionSpec.startsWith("link:") || versionSpec.startsWith("http:") || versionSpec.startsWith("https:");
|
|
28
|
+
}
|
|
20
29
|
function isSemverCompatible(currentVersionRange, latestVersion2) {
|
|
21
30
|
try {
|
|
22
31
|
if (isNpmAlias(currentVersionRange)) {
|
|
@@ -33,6 +42,157 @@ function isSemverCompatible(currentVersionRange, latestVersion2) {
|
|
|
33
42
|
return false;
|
|
34
43
|
}
|
|
35
44
|
}
|
|
45
|
+
function collectTargetDependencies(pkg, args) {
|
|
46
|
+
const map = {};
|
|
47
|
+
const dependencies = pkg.dependencies || {};
|
|
48
|
+
const devDependencies = pkg.devDependencies || {};
|
|
49
|
+
const peerDependencies = pkg.peerDependencies || {};
|
|
50
|
+
const optionalDependencies = pkg.optionalDependencies || {};
|
|
51
|
+
const includeDeps = !args["dev-only"] && !args["peer-only"] && !args["optional-only"] && !args["catalogs-only"];
|
|
52
|
+
const includeCatalogs = !args["dev-only"] && !args["peer-only"] && !args["optional-only"] && !args["prod-only"];
|
|
53
|
+
if (args["prod-only"] || includeDeps) {
|
|
54
|
+
for (const dep of Object.keys(dependencies)) {
|
|
55
|
+
const version = dependencies[dep];
|
|
56
|
+
if (!version) continue;
|
|
57
|
+
if (!map[dep]) map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
|
|
58
|
+
map[dep].versionSpec = version;
|
|
59
|
+
map[dep].locations.add("dependencies");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (args["dev-only"] || includeDeps) {
|
|
63
|
+
for (const dep of Object.keys(devDependencies)) {
|
|
64
|
+
const version = devDependencies[dep];
|
|
65
|
+
if (!version) continue;
|
|
66
|
+
if (!map[dep]) map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
|
|
67
|
+
map[dep].versionSpec = version;
|
|
68
|
+
map[dep].locations.add("devDependencies");
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (args["peer-only"] || includeDeps) {
|
|
72
|
+
for (const dep of Object.keys(peerDependencies)) {
|
|
73
|
+
const version = peerDependencies[dep];
|
|
74
|
+
if (!version) continue;
|
|
75
|
+
if (!map[dep]) map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
|
|
76
|
+
map[dep].versionSpec = version;
|
|
77
|
+
map[dep].locations.add("peerDependencies");
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (args["optional-only"] || includeDeps) {
|
|
81
|
+
for (const dep of Object.keys(optionalDependencies)) {
|
|
82
|
+
const version = optionalDependencies[dep];
|
|
83
|
+
if (!version) continue;
|
|
84
|
+
if (!map[dep]) map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
|
|
85
|
+
map[dep].versionSpec = version;
|
|
86
|
+
map[dep].locations.add("optionalDependencies");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (args["catalogs-only"] || includeCatalogs) {
|
|
90
|
+
const workspacesCatalog = pkg.workspaces?.catalog || {};
|
|
91
|
+
for (const dep of Object.keys(workspacesCatalog)) {
|
|
92
|
+
const version = workspacesCatalog[dep];
|
|
93
|
+
if (!version) continue;
|
|
94
|
+
if (!map[dep]) map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
|
|
95
|
+
map[dep].versionSpec = version;
|
|
96
|
+
map[dep].locations.add("catalog");
|
|
97
|
+
}
|
|
98
|
+
const workspacesCatalogs = pkg.workspaces?.catalogs || {};
|
|
99
|
+
for (const catalogName of Object.keys(workspacesCatalogs)) {
|
|
100
|
+
const catalog = workspacesCatalogs[catalogName] || {};
|
|
101
|
+
for (const dep of Object.keys(catalog)) {
|
|
102
|
+
const version = catalog[dep];
|
|
103
|
+
if (!version) continue;
|
|
104
|
+
if (!map[dep]) map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
|
|
105
|
+
map[dep].versionSpec = version;
|
|
106
|
+
map[dep].locations.add(`catalogs.${catalogName}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const topLevelCatalog = pkg.catalog || {};
|
|
110
|
+
for (const dep of Object.keys(topLevelCatalog)) {
|
|
111
|
+
const version = topLevelCatalog[dep];
|
|
112
|
+
if (!version) continue;
|
|
113
|
+
if (!map[dep]) map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
|
|
114
|
+
map[dep].versionSpec = version;
|
|
115
|
+
map[dep].locations.add("catalog");
|
|
116
|
+
}
|
|
117
|
+
const topLevelCatalogs = pkg.catalogs || {};
|
|
118
|
+
for (const catalogName of Object.keys(topLevelCatalogs)) {
|
|
119
|
+
const catalog = topLevelCatalogs[catalogName] || {};
|
|
120
|
+
for (const dep of Object.keys(catalog)) {
|
|
121
|
+
const version = catalog[dep];
|
|
122
|
+
if (!version) continue;
|
|
123
|
+
if (!map[dep]) map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
|
|
124
|
+
map[dep].versionSpec = version;
|
|
125
|
+
map[dep].locations.add(`catalogs.${catalogName}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return { map };
|
|
130
|
+
}
|
|
131
|
+
function applyVersionUpdate(pkg, depName, newVersion, locations) {
|
|
132
|
+
if (locations.has("dependencies")) {
|
|
133
|
+
if (!pkg.dependencies) pkg.dependencies = {};
|
|
134
|
+
pkg.dependencies[depName] = newVersion;
|
|
135
|
+
}
|
|
136
|
+
if (locations.has("devDependencies")) {
|
|
137
|
+
if (!pkg.devDependencies) pkg.devDependencies = {};
|
|
138
|
+
pkg.devDependencies[depName] = newVersion;
|
|
139
|
+
}
|
|
140
|
+
if (locations.has("peerDependencies")) {
|
|
141
|
+
if (!pkg.peerDependencies) pkg.peerDependencies = {};
|
|
142
|
+
pkg.peerDependencies[depName] = newVersion;
|
|
143
|
+
}
|
|
144
|
+
if (locations.has("optionalDependencies")) {
|
|
145
|
+
if (!pkg.optionalDependencies) pkg.optionalDependencies = {};
|
|
146
|
+
pkg.optionalDependencies[depName] = newVersion;
|
|
147
|
+
}
|
|
148
|
+
const ensureWorkspaces = () => {
|
|
149
|
+
if (!pkg.workspaces) pkg.workspaces = {};
|
|
150
|
+
};
|
|
151
|
+
if (locations.has("catalog")) {
|
|
152
|
+
ensureWorkspaces();
|
|
153
|
+
if (!pkg.workspaces.catalog) pkg.workspaces.catalog = {};
|
|
154
|
+
pkg.workspaces.catalog[depName] = newVersion;
|
|
155
|
+
if (pkg.catalog) pkg.catalog[depName] = newVersion;
|
|
156
|
+
}
|
|
157
|
+
for (const loc of locations) {
|
|
158
|
+
const match = /^catalogs\.(.+)$/.exec(loc);
|
|
159
|
+
if (match) {
|
|
160
|
+
const catalogName = match[1] ?? "";
|
|
161
|
+
if (!catalogName) continue;
|
|
162
|
+
ensureWorkspaces();
|
|
163
|
+
if (!pkg.workspaces.catalogs) pkg.workspaces.catalogs = {};
|
|
164
|
+
if (!pkg.workspaces.catalogs[catalogName])
|
|
165
|
+
pkg.workspaces.catalogs[catalogName] = {};
|
|
166
|
+
pkg.workspaces.catalogs[catalogName][depName] = newVersion;
|
|
167
|
+
if (pkg.catalogs && pkg.catalogs[catalogName]) {
|
|
168
|
+
pkg.catalogs[catalogName][depName] = newVersion;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
async function findWorkspacePackageJsons(cwd) {
|
|
174
|
+
const root = await readPackageJSON(cwd);
|
|
175
|
+
const ws = root.workspaces;
|
|
176
|
+
let patterns = [];
|
|
177
|
+
if (Array.isArray(ws)) {
|
|
178
|
+
patterns = ws;
|
|
179
|
+
} else if (ws && Array.isArray(ws.packages)) {
|
|
180
|
+
patterns = ws.packages;
|
|
181
|
+
}
|
|
182
|
+
if (!patterns.length) return [];
|
|
183
|
+
const dirs = await glob(patterns, {
|
|
184
|
+
cwd,
|
|
185
|
+
onlyDirectories: true,
|
|
186
|
+
absolute: true,
|
|
187
|
+
ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"]
|
|
188
|
+
});
|
|
189
|
+
const pkgJsonPaths = [];
|
|
190
|
+
for (const dir of dirs) {
|
|
191
|
+
const pj = path.join(dir, "package.json");
|
|
192
|
+
if (await fs.pathExists(pj)) pkgJsonPaths.push(pj);
|
|
193
|
+
}
|
|
194
|
+
return pkgJsonPaths;
|
|
195
|
+
}
|
|
36
196
|
async function fetchVersionFromRegistry(packageName) {
|
|
37
197
|
const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`);
|
|
38
198
|
if (!response.ok) {
|
|
@@ -42,12 +202,21 @@ async function fetchVersionFromRegistry(packageName) {
|
|
|
42
202
|
return data.version;
|
|
43
203
|
}
|
|
44
204
|
async function getLatestVersion(packageName) {
|
|
205
|
+
const cached = versionCache.get(packageName);
|
|
206
|
+
const now = Date.now();
|
|
207
|
+
if (cached && now - cached.timestamp < CACHE_TTL) {
|
|
208
|
+
return cached.version;
|
|
209
|
+
}
|
|
45
210
|
try {
|
|
46
|
-
|
|
211
|
+
const version = await latestVersion(packageName);
|
|
212
|
+
versionCache.set(packageName, { version, timestamp: now });
|
|
213
|
+
return version;
|
|
47
214
|
} catch (error) {
|
|
48
215
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
49
216
|
try {
|
|
50
|
-
|
|
217
|
+
const version = await fetchVersionFromRegistry(packageName);
|
|
218
|
+
versionCache.set(packageName, { version, timestamp: now });
|
|
219
|
+
return version;
|
|
51
220
|
} catch (fallbackError) {
|
|
52
221
|
throw new Error(
|
|
53
222
|
`Latest version main check and npm registry fallback failed. Main check error: ${errorMessage}. Registry error: ${fallbackError instanceof Error ? fallbackError.message : String(fallbackError)}`
|
|
@@ -55,6 +224,158 @@ async function getLatestVersion(packageName) {
|
|
|
55
224
|
}
|
|
56
225
|
}
|
|
57
226
|
}
|
|
227
|
+
async function checkPackageUpdate(packageName, versionSpec, locations, options) {
|
|
228
|
+
try {
|
|
229
|
+
const latest = await getLatestVersion(packageName);
|
|
230
|
+
const cleanCurrent = versionSpec.replace(/^[\^~]/, "");
|
|
231
|
+
let isCompatible = isSemverCompatible(versionSpec, latest);
|
|
232
|
+
const isExact = !versionSpec.startsWith("^") && !versionSpec.startsWith("~");
|
|
233
|
+
if (isExact || !isCompatible && options.allowMajor) {
|
|
234
|
+
isCompatible = true;
|
|
235
|
+
}
|
|
236
|
+
return {
|
|
237
|
+
package: packageName,
|
|
238
|
+
currentVersion: cleanCurrent,
|
|
239
|
+
latestVersion: latest,
|
|
240
|
+
updated: latest !== cleanCurrent && isCompatible,
|
|
241
|
+
semverCompatible: isCompatible,
|
|
242
|
+
location: Array.from(locations).join(", ")
|
|
243
|
+
};
|
|
244
|
+
} catch (error) {
|
|
245
|
+
return {
|
|
246
|
+
package: packageName,
|
|
247
|
+
currentVersion: versionSpec,
|
|
248
|
+
latestVersion: versionSpec,
|
|
249
|
+
updated: false,
|
|
250
|
+
error: error instanceof Error ? error.message : String(error),
|
|
251
|
+
semverCompatible: false,
|
|
252
|
+
location: Array.from(locations).join(", ")
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function prepareDependenciesForUpdate(allDepsMap, args) {
|
|
257
|
+
const depsToUpdate = Object.keys(allDepsMap);
|
|
258
|
+
let filteredDeps = [];
|
|
259
|
+
if (args.name && args.name.length > 0) {
|
|
260
|
+
filteredDeps = args.name.filter((dep) => dep in allDepsMap);
|
|
261
|
+
const notFound = args.name.filter((dep) => !(dep in allDepsMap));
|
|
262
|
+
if (notFound.length > 0) {
|
|
263
|
+
relinka("warn", `Dependencies not found: ${notFound.join(", ")}`);
|
|
264
|
+
}
|
|
265
|
+
} else {
|
|
266
|
+
const ignoreList = args.ignore || [];
|
|
267
|
+
filteredDeps = depsToUpdate.filter((dep) => !ignoreList.includes(dep));
|
|
268
|
+
}
|
|
269
|
+
return filteredDeps.filter((dep) => {
|
|
270
|
+
const versionSpec = allDepsMap[dep]?.versionSpec ?? "";
|
|
271
|
+
if (!versionSpec) return false;
|
|
272
|
+
if (isNonSemverSpecifier(versionSpec)) return false;
|
|
273
|
+
return true;
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
async function updatePackageJsonFile(packageJsonPath, dependencies, updatesToApply, savePrefix) {
|
|
277
|
+
if (updatesToApply.length === 0) return 0;
|
|
278
|
+
try {
|
|
279
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf8"));
|
|
280
|
+
const updatedPackageJson = { ...packageJson };
|
|
281
|
+
for (const update of updatesToApply) {
|
|
282
|
+
const prefix = savePrefix === "none" ? "" : savePrefix;
|
|
283
|
+
const newVersion = `${prefix}${update.latestVersion}`;
|
|
284
|
+
const locations = dependencies[update.package]?.locations || /* @__PURE__ */ new Set();
|
|
285
|
+
applyVersionUpdate(updatedPackageJson, update.package, newVersion, locations);
|
|
286
|
+
}
|
|
287
|
+
await fs.writeFile(packageJsonPath, JSON.stringify(updatedPackageJson, null, 2) + "\n", "utf8");
|
|
288
|
+
return updatesToApply.length;
|
|
289
|
+
} catch (error) {
|
|
290
|
+
relinka(
|
|
291
|
+
"warn",
|
|
292
|
+
`Failed to update ${packageJsonPath}: ${error instanceof Error ? error.message : String(error)}`
|
|
293
|
+
);
|
|
294
|
+
return 0;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
async function updateWorkspacePackages(workspacePaths, args, options) {
|
|
298
|
+
if (workspacePaths.length === 0) return 0;
|
|
299
|
+
relinka("info", `Scanning ${workspacePaths.length} workspace packages...`);
|
|
300
|
+
let totalWorkspaceUpdated = 0;
|
|
301
|
+
for (const packageJsonPath of workspacePaths) {
|
|
302
|
+
try {
|
|
303
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf8"));
|
|
304
|
+
const { map } = collectTargetDependencies(packageJson, args);
|
|
305
|
+
const candidates = prepareDependenciesForUpdate(map, args);
|
|
306
|
+
if (candidates.length === 0) continue;
|
|
307
|
+
const results = await pMap(
|
|
308
|
+
candidates,
|
|
309
|
+
(dep) => {
|
|
310
|
+
const depInfo = map[dep];
|
|
311
|
+
if (!depInfo?.versionSpec) {
|
|
312
|
+
return Promise.resolve({
|
|
313
|
+
package: dep,
|
|
314
|
+
currentVersion: "unknown",
|
|
315
|
+
latestVersion: "unknown",
|
|
316
|
+
updated: false,
|
|
317
|
+
error: "Current version not found",
|
|
318
|
+
semverCompatible: false,
|
|
319
|
+
location: Array.from(depInfo?.locations || ["unknown"]).join(", ")
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
return checkPackageUpdate(dep, depInfo.versionSpec, depInfo.locations, options);
|
|
323
|
+
},
|
|
324
|
+
{ concurrency: options.concurrency }
|
|
325
|
+
);
|
|
326
|
+
const toUpdate = results.filter((r) => r.updated && !r.error);
|
|
327
|
+
const updated = await updatePackageJsonFile(
|
|
328
|
+
packageJsonPath,
|
|
329
|
+
map,
|
|
330
|
+
toUpdate,
|
|
331
|
+
options.savePrefix
|
|
332
|
+
);
|
|
333
|
+
if (updated > 0) {
|
|
334
|
+
totalWorkspaceUpdated += updated;
|
|
335
|
+
relinka("log", `Updated ${updated} deps in ${packageJsonPath}`);
|
|
336
|
+
}
|
|
337
|
+
} catch (error) {
|
|
338
|
+
relinka(
|
|
339
|
+
"warn",
|
|
340
|
+
`Skipping ${packageJsonPath}: ${error instanceof Error ? error.message : String(error)}`
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
return totalWorkspaceUpdated;
|
|
345
|
+
}
|
|
346
|
+
function displayUpdateResults(results) {
|
|
347
|
+
const toUpdate = results.filter((r) => r.updated && !r.error);
|
|
348
|
+
const errors = results.filter((r) => r.error);
|
|
349
|
+
const upToDate = results.filter((r) => !r.updated && !r.error && r.semverCompatible);
|
|
350
|
+
if (errors.length > 0) {
|
|
351
|
+
relinka("warn", `Failed to check ${errors.length} dependencies:`);
|
|
352
|
+
for (const error of errors) {
|
|
353
|
+
relinka("warn", ` ${error.package} (${error.location}): ${error.error}`);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (upToDate.length > 0) {
|
|
357
|
+
relinka("success", `${upToDate.length} dependencies are up to date`);
|
|
358
|
+
}
|
|
359
|
+
if (toUpdate.length === 0) {
|
|
360
|
+
relinka("success", `All ${upToDate.length} deps are already up to date`);
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
relinka("info", `${toUpdate.length} dependencies can be updated:`);
|
|
364
|
+
const byLocation = /* @__PURE__ */ new Map();
|
|
365
|
+
for (const update of toUpdate) {
|
|
366
|
+
const location = update.location || "unknown";
|
|
367
|
+
if (!byLocation.has(location)) {
|
|
368
|
+
byLocation.set(location, []);
|
|
369
|
+
}
|
|
370
|
+
byLocation.get(location).push(update);
|
|
371
|
+
}
|
|
372
|
+
for (const [location, updates] of byLocation.entries()) {
|
|
373
|
+
relinka("log", ` ${location}:`);
|
|
374
|
+
for (const update of updates) {
|
|
375
|
+
relinka("log", ` ${update.package}: ${update.currentVersion} \u2192 ${update.latestVersion}`);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
58
379
|
async function getGlobalPackages(packageManager) {
|
|
59
380
|
try {
|
|
60
381
|
let result;
|
|
@@ -335,16 +656,16 @@ async function handleGlobalUpdates(args) {
|
|
|
335
656
|
export default defineCommand({
|
|
336
657
|
meta: {
|
|
337
658
|
name: "update",
|
|
338
|
-
description: "Update dependencies to
|
|
659
|
+
description: "Update all dependencies and catalogs to their latest available versions"
|
|
339
660
|
},
|
|
340
661
|
args: defineArgs({
|
|
341
662
|
name: {
|
|
342
663
|
type: "array",
|
|
343
|
-
description: "
|
|
664
|
+
description: "Specific dependencies to update (default: all dependencies)"
|
|
344
665
|
},
|
|
345
666
|
ignore: {
|
|
346
667
|
type: "array",
|
|
347
|
-
description: "
|
|
668
|
+
description: "Dependencies to exclude from updates"
|
|
348
669
|
},
|
|
349
670
|
"dev-only": {
|
|
350
671
|
type: "boolean",
|
|
@@ -364,11 +685,11 @@ export default defineCommand({
|
|
|
364
685
|
},
|
|
365
686
|
"catalogs-only": {
|
|
366
687
|
type: "boolean",
|
|
367
|
-
description: "Update
|
|
688
|
+
description: "Update ONLY catalog dependencies (catalogs are included by default)"
|
|
368
689
|
},
|
|
369
690
|
"dry-run": {
|
|
370
691
|
type: "boolean",
|
|
371
|
-
description: "
|
|
692
|
+
description: "Preview updates without making changes"
|
|
372
693
|
},
|
|
373
694
|
concurrency: {
|
|
374
695
|
type: "number",
|
|
@@ -377,43 +698,68 @@ export default defineCommand({
|
|
|
377
698
|
},
|
|
378
699
|
"with-check-script": {
|
|
379
700
|
type: "boolean",
|
|
380
|
-
description: "Run `bun check` after updating (
|
|
701
|
+
description: "Run `bun check` after updating (Bun only)"
|
|
381
702
|
},
|
|
382
703
|
linker: {
|
|
383
704
|
type: "string",
|
|
384
|
-
description: "Linker strategy
|
|
705
|
+
description: "Linker strategy: 'isolated' for monorepos, 'hoisted' for single packages",
|
|
385
706
|
allowed: ["isolated", "hoisted"],
|
|
386
707
|
default: "hoisted"
|
|
387
708
|
},
|
|
388
709
|
"with-install": {
|
|
389
710
|
type: "boolean",
|
|
390
|
-
description: "Run
|
|
711
|
+
description: "Run install after updating",
|
|
391
712
|
alias: "with-i"
|
|
392
713
|
},
|
|
393
714
|
global: {
|
|
394
715
|
type: "boolean",
|
|
395
|
-
description: "Update global packages
|
|
716
|
+
description: "Update global packages",
|
|
396
717
|
alias: "g"
|
|
397
718
|
},
|
|
398
719
|
interactive: {
|
|
399
720
|
type: "boolean",
|
|
400
|
-
description: "Interactively select
|
|
721
|
+
description: "Interactively select dependencies to update"
|
|
401
722
|
},
|
|
402
723
|
filter: {
|
|
403
724
|
type: "array",
|
|
404
|
-
description: "Filter workspaces
|
|
725
|
+
description: "Filter workspaces (e.g., 'pkg-*', '!pkg-c')"
|
|
405
726
|
},
|
|
406
|
-
"
|
|
727
|
+
"all-workspaces": {
|
|
407
728
|
type: "boolean",
|
|
408
|
-
description: "Update
|
|
729
|
+
description: "Update dependencies across all workspace packages"
|
|
730
|
+
},
|
|
731
|
+
"save-prefix": {
|
|
732
|
+
type: "string",
|
|
733
|
+
description: "Version prefix: '^', '~', or 'none' for exact",
|
|
734
|
+
allowed: ["^", "~", "none"],
|
|
735
|
+
default: "^"
|
|
736
|
+
},
|
|
737
|
+
"allow-major": {
|
|
738
|
+
type: "boolean",
|
|
739
|
+
description: "Allow major version updates to latest available (disable with --no-allow-major)",
|
|
740
|
+
default: true
|
|
409
741
|
}
|
|
410
742
|
}),
|
|
411
743
|
async run({ args }) {
|
|
412
744
|
try {
|
|
745
|
+
const exclusiveFlags = [
|
|
746
|
+
args["dev-only"],
|
|
747
|
+
args["prod-only"],
|
|
748
|
+
args["peer-only"],
|
|
749
|
+
args["optional-only"],
|
|
750
|
+
args["catalogs-only"]
|
|
751
|
+
];
|
|
752
|
+
if (exclusiveFlags.filter(Boolean).length > 1) {
|
|
753
|
+
relinka(
|
|
754
|
+
"error",
|
|
755
|
+
"Cannot specify multiple exclusive flags (--dev-only, --prod-only, --peer-only, --optional-only, --catalogs-only)"
|
|
756
|
+
);
|
|
757
|
+
return process.exit(1);
|
|
758
|
+
}
|
|
413
759
|
if (args.global) {
|
|
414
760
|
return await handleGlobalUpdates(args);
|
|
415
761
|
}
|
|
416
|
-
if (args["
|
|
762
|
+
if (args["catalogs-only"]) {
|
|
417
763
|
const packageManager2 = await detectPackageManager(process.cwd());
|
|
418
764
|
if (!packageManager2) {
|
|
419
765
|
relinka("error", "Could not detect package manager");
|
|
@@ -438,146 +784,34 @@ export default defineCommand({
|
|
|
438
784
|
let linkerSource = "CLI default";
|
|
439
785
|
if (typeof Bun !== "undefined") {
|
|
440
786
|
const bunfigConfig = await getConfigBunfig();
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
linkerSource = bunfigLinker === "hoisted" ? "bunfig.toml (same as default)" : "bunfig.toml";
|
|
446
|
-
}
|
|
787
|
+
const bunfigLinker = bunfigConfig?.install?.linker;
|
|
788
|
+
if (bunfigLinker && ["isolated", "hoisted"].includes(bunfigLinker) && args.linker === "hoisted") {
|
|
789
|
+
effectiveLinker = bunfigLinker;
|
|
790
|
+
linkerSource = bunfigLinker === "hoisted" ? "bunfig.toml (same as default)" : "bunfig.toml";
|
|
447
791
|
}
|
|
448
792
|
}
|
|
449
793
|
if (args.linker !== "hoisted") {
|
|
450
794
|
effectiveLinker = args.linker;
|
|
451
|
-
linkerSource = "CLI
|
|
795
|
+
linkerSource = "CLI override";
|
|
452
796
|
}
|
|
453
797
|
relinka("verbose", `Using linker strategy: ${effectiveLinker} (from ${linkerSource})`);
|
|
454
798
|
const packageJson = await readPackageJSON();
|
|
455
|
-
const
|
|
456
|
-
const
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
const workspaces = packageJson.workspaces || {};
|
|
460
|
-
const catalog = workspaces.catalog || packageJson.catalog || {};
|
|
461
|
-
const catalogs = workspaces.catalogs || packageJson.catalogs || {};
|
|
462
|
-
let targetDeps = {};
|
|
463
|
-
const depSources = {};
|
|
464
|
-
const exclusiveFlags = [
|
|
465
|
-
args["dev-only"],
|
|
466
|
-
args["prod-only"],
|
|
467
|
-
args["peer-only"],
|
|
468
|
-
args["optional-only"],
|
|
469
|
-
args["catalogs-only"]
|
|
470
|
-
].filter(Boolean);
|
|
471
|
-
if (exclusiveFlags.length > 1) {
|
|
472
|
-
relinka(
|
|
473
|
-
"error",
|
|
474
|
-
"Cannot specify multiple exclusive flags (--dev-only, --prod-only, --peer-only, --optional-only, --catalogs-only)"
|
|
475
|
-
);
|
|
476
|
-
return process.exit(1);
|
|
477
|
-
}
|
|
478
|
-
if (args["dev-only"]) {
|
|
479
|
-
targetDeps = { ...devDependencies };
|
|
480
|
-
Object.keys(devDependencies).forEach((dep) => {
|
|
481
|
-
depSources[dep] = "devDependencies";
|
|
482
|
-
});
|
|
483
|
-
} else if (args["prod-only"]) {
|
|
484
|
-
targetDeps = { ...dependencies };
|
|
485
|
-
Object.keys(dependencies).forEach((dep) => {
|
|
486
|
-
depSources[dep] = "dependencies";
|
|
487
|
-
});
|
|
488
|
-
} else if (args["peer-only"]) {
|
|
489
|
-
targetDeps = { ...peerDependencies };
|
|
490
|
-
Object.keys(peerDependencies).forEach((dep) => {
|
|
491
|
-
depSources[dep] = "peerDependencies";
|
|
492
|
-
});
|
|
493
|
-
} else if (args["optional-only"]) {
|
|
494
|
-
targetDeps = { ...optionalDependencies };
|
|
495
|
-
Object.keys(optionalDependencies).forEach((dep) => {
|
|
496
|
-
depSources[dep] = "optionalDependencies";
|
|
497
|
-
});
|
|
498
|
-
} else if (args["catalogs-only"]) {
|
|
499
|
-
Object.keys(catalog).forEach((dep) => {
|
|
500
|
-
targetDeps[dep] = catalog[dep];
|
|
501
|
-
depSources[dep] = "catalog";
|
|
502
|
-
});
|
|
503
|
-
Object.keys(catalogs).forEach((catalogName) => {
|
|
504
|
-
Object.keys(catalogs[catalogName]).forEach((dep) => {
|
|
505
|
-
targetDeps[dep] = catalogs[catalogName][dep];
|
|
506
|
-
depSources[dep] = `catalogs.${catalogName}`;
|
|
507
|
-
});
|
|
508
|
-
});
|
|
509
|
-
} else {
|
|
510
|
-
const allDeps = {};
|
|
511
|
-
const allDepSources = {};
|
|
512
|
-
Object.keys(dependencies).forEach((dep) => {
|
|
513
|
-
const version = dependencies[dep];
|
|
514
|
-
if (version) {
|
|
515
|
-
allDeps[dep] = version;
|
|
516
|
-
allDepSources[dep] = "dependencies";
|
|
517
|
-
}
|
|
518
|
-
});
|
|
519
|
-
Object.keys(devDependencies).forEach((dep) => {
|
|
520
|
-
const version = devDependencies[dep];
|
|
521
|
-
if (version) {
|
|
522
|
-
allDeps[dep] = version;
|
|
523
|
-
allDepSources[dep] = "devDependencies";
|
|
524
|
-
}
|
|
525
|
-
});
|
|
526
|
-
Object.keys(peerDependencies).forEach((dep) => {
|
|
527
|
-
const version = peerDependencies[dep];
|
|
528
|
-
if (version) {
|
|
529
|
-
allDeps[dep] = version;
|
|
530
|
-
allDepSources[dep] = "peerDependencies";
|
|
531
|
-
}
|
|
532
|
-
});
|
|
533
|
-
Object.keys(optionalDependencies).forEach((dep) => {
|
|
534
|
-
const version = optionalDependencies[dep];
|
|
535
|
-
if (version) {
|
|
536
|
-
allDeps[dep] = version;
|
|
537
|
-
allDepSources[dep] = "optionalDependencies";
|
|
538
|
-
}
|
|
539
|
-
});
|
|
540
|
-
Object.keys(catalog).forEach((dep) => {
|
|
541
|
-
allDeps[dep] = catalog[dep];
|
|
542
|
-
allDepSources[dep] = "catalog";
|
|
543
|
-
});
|
|
544
|
-
Object.keys(catalogs).forEach((catalogName) => {
|
|
545
|
-
Object.keys(catalogs[catalogName]).forEach((dep) => {
|
|
546
|
-
allDeps[dep] = catalogs[catalogName][dep];
|
|
547
|
-
allDepSources[dep] = `catalogs.${catalogName}`;
|
|
548
|
-
});
|
|
549
|
-
});
|
|
550
|
-
targetDeps = allDeps;
|
|
551
|
-
Object.assign(depSources, allDepSources);
|
|
552
|
-
}
|
|
553
|
-
const depsToUpdate = Object.keys(targetDeps);
|
|
554
|
-
let filteredDeps = [];
|
|
555
|
-
if (args.name && args.name.length > 0) {
|
|
556
|
-
filteredDeps = args.name.filter((dep) => dep in targetDeps);
|
|
557
|
-
const notFound = args.name.filter((dep) => !(dep in targetDeps));
|
|
558
|
-
if (notFound.length > 0) {
|
|
559
|
-
relinka("warn", `Dependencies not found: ${notFound.join(", ")}`);
|
|
560
|
-
}
|
|
561
|
-
} else {
|
|
562
|
-
const ignoreList = args.ignore || [];
|
|
563
|
-
filteredDeps = depsToUpdate.filter((dep) => !ignoreList.includes(dep));
|
|
564
|
-
}
|
|
565
|
-
const semverDeps = filteredDeps.filter((dep) => {
|
|
566
|
-
const versionSpec = targetDeps[dep];
|
|
567
|
-
return versionSpec && (versionSpec.startsWith("^") || versionSpec.startsWith("~"));
|
|
568
|
-
});
|
|
569
|
-
if (semverDeps.length === 0) {
|
|
570
|
-
relinka(
|
|
571
|
-
"warn",
|
|
572
|
-
"No dependencies to update (only semver-compatible dependencies with ^ or ~ prefixes are supported)"
|
|
573
|
-
);
|
|
799
|
+
const { map: allDepsMap } = collectTargetDependencies(packageJson, args);
|
|
800
|
+
const candidates = prepareDependenciesForUpdate(allDepsMap, args);
|
|
801
|
+
if (candidates.length === 0) {
|
|
802
|
+
relinka("warn", "No dependencies to update based on provided filters");
|
|
574
803
|
return;
|
|
575
804
|
}
|
|
805
|
+
const options = {
|
|
806
|
+
allowMajor: !!args["allow-major"],
|
|
807
|
+
savePrefix: args["save-prefix"],
|
|
808
|
+
concurrency: args.concurrency
|
|
809
|
+
};
|
|
576
810
|
const results = await pMap(
|
|
577
|
-
|
|
811
|
+
candidates,
|
|
578
812
|
async (dep) => {
|
|
579
|
-
const
|
|
580
|
-
if (!
|
|
813
|
+
const depInfo = allDepsMap[dep];
|
|
814
|
+
if (!depInfo?.versionSpec) {
|
|
581
815
|
return {
|
|
582
816
|
package: dep,
|
|
583
817
|
currentVersion: "unknown",
|
|
@@ -585,63 +819,21 @@ export default defineCommand({
|
|
|
585
819
|
updated: false,
|
|
586
820
|
error: "Current version not found",
|
|
587
821
|
semverCompatible: false,
|
|
588
|
-
location:
|
|
589
|
-
};
|
|
590
|
-
}
|
|
591
|
-
try {
|
|
592
|
-
const latest = await getLatestVersion(dep);
|
|
593
|
-
const cleanCurrent = currentVersion.replace(/^[\^~]/, "");
|
|
594
|
-
const isCompatible = isSemverCompatible(currentVersion, latest);
|
|
595
|
-
return {
|
|
596
|
-
package: dep,
|
|
597
|
-
currentVersion: cleanCurrent,
|
|
598
|
-
latestVersion: latest,
|
|
599
|
-
updated: latest !== cleanCurrent && isCompatible,
|
|
600
|
-
semverCompatible: isCompatible,
|
|
601
|
-
location: depSources[dep]
|
|
602
|
-
};
|
|
603
|
-
} catch (error) {
|
|
604
|
-
return {
|
|
605
|
-
package: dep,
|
|
606
|
-
currentVersion,
|
|
607
|
-
latestVersion: currentVersion,
|
|
608
|
-
updated: false,
|
|
609
|
-
error: error instanceof Error ? error.message : String(error),
|
|
610
|
-
semverCompatible: false,
|
|
611
|
-
location: depSources[dep]
|
|
822
|
+
location: Array.from(depInfo?.locations || ["unknown"]).join(", ")
|
|
612
823
|
};
|
|
613
824
|
}
|
|
825
|
+
return checkPackageUpdate(dep, depInfo.versionSpec, depInfo.locations, options);
|
|
614
826
|
},
|
|
615
827
|
{ concurrency: args.concurrency }
|
|
616
828
|
);
|
|
829
|
+
displayUpdateResults(results);
|
|
617
830
|
let toUpdate = results.filter((r) => r.updated && !r.error);
|
|
618
|
-
const errors = results.filter((r) => r.error);
|
|
619
|
-
const upToDate = results.filter((r) => !r.updated && !r.error && r.semverCompatible);
|
|
620
|
-
if (errors.length > 0) {
|
|
621
|
-
relinka("warn", `Failed to check ${errors.length} dependencies:`);
|
|
622
|
-
for (const error of errors) {
|
|
623
|
-
relinka("warn", ` ${error.package} (${error.location}): ${error.error}`);
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
if (toUpdate.length === 0) {
|
|
627
|
-
relinka("success", `All ${upToDate.length} deps are already up to date`);
|
|
628
|
-
return;
|
|
629
|
-
}
|
|
630
|
-
if (upToDate.length > 0) {
|
|
631
|
-
relinka("success", `${upToDate.length} dependencies are up to date`);
|
|
632
|
-
}
|
|
633
831
|
if (toUpdate.length === 0) {
|
|
634
|
-
relinka("success", `All ${upToDate.length} deps are already up to date`);
|
|
635
832
|
return;
|
|
636
833
|
}
|
|
637
|
-
relinka("info", `${toUpdate.length} dependencies can be updated:`);
|
|
638
|
-
for (const update of toUpdate) {
|
|
639
|
-
relinka(
|
|
640
|
-
"log",
|
|
641
|
-
` ${update.package} (${update.location}): ${update.currentVersion} \u2192 ${update.latestVersion}`
|
|
642
|
-
);
|
|
643
|
-
}
|
|
644
834
|
if (args.interactive) {
|
|
835
|
+
const errors = results.filter((r) => r.error);
|
|
836
|
+
const upToDate = results.filter((r) => !r.updated && !r.error && r.semverCompatible);
|
|
645
837
|
const allPackages = [
|
|
646
838
|
...toUpdate.map((pkg) => ({
|
|
647
839
|
...pkg,
|
|
@@ -691,68 +883,28 @@ export default defineCommand({
|
|
|
691
883
|
relinka("info", "Dry run mode - no changes were made");
|
|
692
884
|
return;
|
|
693
885
|
}
|
|
694
|
-
const
|
|
695
|
-
for (const update of toUpdate) {
|
|
696
|
-
const dep = update.package;
|
|
697
|
-
const newVersion = `^${update.latestVersion}`;
|
|
698
|
-
if (dependencies[dep]) {
|
|
699
|
-
if (!updatedPackageJson.dependencies) updatedPackageJson.dependencies = {};
|
|
700
|
-
updatedPackageJson.dependencies[dep] = newVersion;
|
|
701
|
-
}
|
|
702
|
-
if (devDependencies[dep]) {
|
|
703
|
-
if (!updatedPackageJson.devDependencies) updatedPackageJson.devDependencies = {};
|
|
704
|
-
updatedPackageJson.devDependencies[dep] = newVersion;
|
|
705
|
-
}
|
|
706
|
-
if (peerDependencies[dep]) {
|
|
707
|
-
if (!updatedPackageJson.peerDependencies) updatedPackageJson.peerDependencies = {};
|
|
708
|
-
updatedPackageJson.peerDependencies[dep] = newVersion;
|
|
709
|
-
}
|
|
710
|
-
if (optionalDependencies[dep]) {
|
|
711
|
-
if (!updatedPackageJson.optionalDependencies)
|
|
712
|
-
updatedPackageJson.optionalDependencies = {};
|
|
713
|
-
updatedPackageJson.optionalDependencies[dep] = newVersion;
|
|
714
|
-
}
|
|
715
|
-
if (catalog[dep]) {
|
|
716
|
-
if (!updatedPackageJson.workspaces) updatedPackageJson.workspaces = {};
|
|
717
|
-
if (!updatedPackageJson.workspaces.catalog)
|
|
718
|
-
updatedPackageJson.workspaces.catalog = {};
|
|
719
|
-
updatedPackageJson.workspaces.catalog[dep] = newVersion;
|
|
720
|
-
if (updatedPackageJson.catalog) {
|
|
721
|
-
updatedPackageJson.catalog[dep] = newVersion;
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
Object.keys(catalogs).forEach((catalogName) => {
|
|
725
|
-
if (catalogs[catalogName][dep]) {
|
|
726
|
-
if (!updatedPackageJson.workspaces)
|
|
727
|
-
updatedPackageJson.workspaces = {};
|
|
728
|
-
if (!updatedPackageJson.workspaces.catalogs)
|
|
729
|
-
updatedPackageJson.workspaces.catalogs = {};
|
|
730
|
-
if (!updatedPackageJson.workspaces.catalogs[catalogName]) {
|
|
731
|
-
updatedPackageJson.workspaces.catalogs[catalogName] = {};
|
|
732
|
-
}
|
|
733
|
-
updatedPackageJson.workspaces.catalogs[catalogName][dep] = newVersion;
|
|
734
|
-
if (updatedPackageJson.catalogs && updatedPackageJson.catalogs[catalogName]) {
|
|
735
|
-
updatedPackageJson.catalogs[catalogName][dep] = newVersion;
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
});
|
|
739
|
-
}
|
|
740
|
-
await fs.writeFile(
|
|
886
|
+
const rootUpdated = await updatePackageJsonFile(
|
|
741
887
|
packageJsonPath,
|
|
742
|
-
|
|
743
|
-
|
|
888
|
+
allDepsMap,
|
|
889
|
+
toUpdate,
|
|
890
|
+
args["save-prefix"]
|
|
744
891
|
);
|
|
745
|
-
|
|
746
|
-
if (args["
|
|
747
|
-
const
|
|
748
|
-
const
|
|
892
|
+
let totalUpdated = rootUpdated;
|
|
893
|
+
if (args["all-workspaces"]) {
|
|
894
|
+
const workspacePkgJsons = await findWorkspacePackageJsons(process.cwd());
|
|
895
|
+
const workspaceUpdated = await updateWorkspacePackages(workspacePkgJsons, args, options);
|
|
896
|
+
totalUpdated += workspaceUpdated;
|
|
897
|
+
}
|
|
898
|
+
relinka("success", `Updated ${totalUpdated} dependencies across workspace`);
|
|
899
|
+
const packageManager = await detectPackageManager(process.cwd());
|
|
900
|
+
if (!args["with-install"]) {
|
|
901
|
+
const installCommand = packageManager?.command || "your package manager";
|
|
749
902
|
relinka(
|
|
750
903
|
"info",
|
|
751
|
-
`Skipped install step. Use --with-install
|
|
904
|
+
`Skipped install step. Use --with-install to run '${installCommand} install'.`
|
|
752
905
|
);
|
|
753
906
|
return;
|
|
754
907
|
}
|
|
755
|
-
const packageManager = await detectPackageManager(process.cwd());
|
|
756
908
|
if (packageManager) {
|
|
757
909
|
try {
|
|
758
910
|
if (args.filter && args.filter.length > 0) {
|
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"bun-plugin-tailwind": "^0.0.15",
|
|
18
18
|
"cssnano": "^7.1.0",
|
|
19
19
|
"defu": "^6.1.4",
|
|
20
|
-
"esbuild": "^0.25.
|
|
20
|
+
"esbuild": "^0.25.9",
|
|
21
21
|
"execa": "^9.6.0",
|
|
22
22
|
"file-type": "^21.0.0",
|
|
23
23
|
"fix-dts-default-cjs-exports": "^1.0.1",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"pkg-types": "^2.2.0",
|
|
34
34
|
"postcss": "^8.5.6",
|
|
35
35
|
"postcss-nested": "^7.0.2",
|
|
36
|
-
"pretty-bytes": "^7.0.
|
|
36
|
+
"pretty-bytes": "^7.0.1",
|
|
37
37
|
"pretty-ms": "^9.2.0",
|
|
38
38
|
"registry-auth-token": "^5.1.0",
|
|
39
39
|
"registry-url": "^7.2.0",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"license": "MIT",
|
|
53
53
|
"name": "@reliverse/dler",
|
|
54
54
|
"type": "module",
|
|
55
|
-
"version": "1.7.
|
|
55
|
+
"version": "1.7.83",
|
|
56
56
|
"keywords": [
|
|
57
57
|
"reliverse",
|
|
58
58
|
"cli",
|