@reliverse/dler 1.7.82 → 1.7.84

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.
@@ -64,9 +64,24 @@ declare const _default: import("@reliverse/rempts").Command<{
64
64
  type: "array";
65
65
  description: string;
66
66
  };
67
- "update-catalogs": {
67
+ "all-workspaces": {
68
68
  type: "boolean";
69
69
  description: string;
70
70
  };
71
+ "root-only": {
72
+ type: "boolean";
73
+ description: string;
74
+ };
75
+ "save-prefix": {
76
+ type: "string";
77
+ description: string;
78
+ allowed: string[];
79
+ default: string;
80
+ };
81
+ "allow-major": {
82
+ type: "boolean";
83
+ description: string;
84
+ default: true;
85
+ };
71
86
  }>;
72
87
  export default _default;
@@ -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,172 @@ 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
+ }
196
+ async function isMonorepo(cwd) {
197
+ try {
198
+ const root = await readPackageJSON(cwd);
199
+ const ws = root.workspaces;
200
+ if (Array.isArray(ws) && ws.length > 0) {
201
+ return true;
202
+ }
203
+ if (ws && Array.isArray(ws.packages) && ws.packages.length > 0) {
204
+ return true;
205
+ }
206
+ return false;
207
+ } catch {
208
+ return false;
209
+ }
210
+ }
36
211
  async function fetchVersionFromRegistry(packageName) {
37
212
  const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`);
38
213
  if (!response.ok) {
@@ -42,12 +217,21 @@ async function fetchVersionFromRegistry(packageName) {
42
217
  return data.version;
43
218
  }
44
219
  async function getLatestVersion(packageName) {
220
+ const cached = versionCache.get(packageName);
221
+ const now = Date.now();
222
+ if (cached && now - cached.timestamp < CACHE_TTL) {
223
+ return cached.version;
224
+ }
45
225
  try {
46
- return await latestVersion(packageName);
226
+ const version = await latestVersion(packageName);
227
+ versionCache.set(packageName, { version, timestamp: now });
228
+ return version;
47
229
  } catch (error) {
48
230
  const errorMessage = error instanceof Error ? error.message : String(error);
49
231
  try {
50
- return await fetchVersionFromRegistry(packageName);
232
+ const version = await fetchVersionFromRegistry(packageName);
233
+ versionCache.set(packageName, { version, timestamp: now });
234
+ return version;
51
235
  } catch (fallbackError) {
52
236
  throw new Error(
53
237
  `Latest version main check and npm registry fallback failed. Main check error: ${errorMessage}. Registry error: ${fallbackError instanceof Error ? fallbackError.message : String(fallbackError)}`
@@ -55,6 +239,158 @@ async function getLatestVersion(packageName) {
55
239
  }
56
240
  }
57
241
  }
242
+ async function checkPackageUpdate(packageName, versionSpec, locations, options) {
243
+ try {
244
+ const latest = await getLatestVersion(packageName);
245
+ const cleanCurrent = versionSpec.replace(/^[\^~]/, "");
246
+ let isCompatible = isSemverCompatible(versionSpec, latest);
247
+ const isExact = !versionSpec.startsWith("^") && !versionSpec.startsWith("~");
248
+ if (isExact || !isCompatible && options.allowMajor) {
249
+ isCompatible = true;
250
+ }
251
+ return {
252
+ package: packageName,
253
+ currentVersion: cleanCurrent,
254
+ latestVersion: latest,
255
+ updated: latest !== cleanCurrent && isCompatible,
256
+ semverCompatible: isCompatible,
257
+ location: Array.from(locations).join(", ")
258
+ };
259
+ } catch (error) {
260
+ return {
261
+ package: packageName,
262
+ currentVersion: versionSpec,
263
+ latestVersion: versionSpec,
264
+ updated: false,
265
+ error: error instanceof Error ? error.message : String(error),
266
+ semverCompatible: false,
267
+ location: Array.from(locations).join(", ")
268
+ };
269
+ }
270
+ }
271
+ function prepareDependenciesForUpdate(allDepsMap, args) {
272
+ const depsToUpdate = Object.keys(allDepsMap);
273
+ let filteredDeps = [];
274
+ if (args.name && args.name.length > 0) {
275
+ filteredDeps = args.name.filter((dep) => dep in allDepsMap);
276
+ const notFound = args.name.filter((dep) => !(dep in allDepsMap));
277
+ if (notFound.length > 0) {
278
+ relinka("warn", `Dependencies not found: ${notFound.join(", ")}`);
279
+ }
280
+ } else {
281
+ const ignoreList = args.ignore || [];
282
+ filteredDeps = depsToUpdate.filter((dep) => !ignoreList.includes(dep));
283
+ }
284
+ return filteredDeps.filter((dep) => {
285
+ const versionSpec = allDepsMap[dep]?.versionSpec ?? "";
286
+ if (!versionSpec) return false;
287
+ if (isNonSemverSpecifier(versionSpec)) return false;
288
+ return true;
289
+ });
290
+ }
291
+ async function updatePackageJsonFile(packageJsonPath, dependencies, updatesToApply, savePrefix) {
292
+ if (updatesToApply.length === 0) return 0;
293
+ try {
294
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf8"));
295
+ const updatedPackageJson = { ...packageJson };
296
+ for (const update of updatesToApply) {
297
+ const prefix = savePrefix === "none" ? "" : savePrefix;
298
+ const newVersion = `${prefix}${update.latestVersion}`;
299
+ const locations = dependencies[update.package]?.locations || /* @__PURE__ */ new Set();
300
+ applyVersionUpdate(updatedPackageJson, update.package, newVersion, locations);
301
+ }
302
+ await fs.writeFile(packageJsonPath, JSON.stringify(updatedPackageJson, null, 2) + "\n", "utf8");
303
+ return updatesToApply.length;
304
+ } catch (error) {
305
+ relinka(
306
+ "warn",
307
+ `Failed to update ${packageJsonPath}: ${error instanceof Error ? error.message : String(error)}`
308
+ );
309
+ return 0;
310
+ }
311
+ }
312
+ async function updateWorkspacePackages(workspacePaths, args, options) {
313
+ if (workspacePaths.length === 0) return 0;
314
+ relinka("info", `Scanning ${workspacePaths.length} workspace packages...`);
315
+ let totalWorkspaceUpdated = 0;
316
+ for (const packageJsonPath of workspacePaths) {
317
+ try {
318
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf8"));
319
+ const { map } = collectTargetDependencies(packageJson, args);
320
+ const candidates = prepareDependenciesForUpdate(map, args);
321
+ if (candidates.length === 0) continue;
322
+ const results = await pMap(
323
+ candidates,
324
+ (dep) => {
325
+ const depInfo = map[dep];
326
+ if (!depInfo?.versionSpec) {
327
+ return Promise.resolve({
328
+ package: dep,
329
+ currentVersion: "unknown",
330
+ latestVersion: "unknown",
331
+ updated: false,
332
+ error: "Current version not found",
333
+ semverCompatible: false,
334
+ location: Array.from(depInfo?.locations || ["unknown"]).join(", ")
335
+ });
336
+ }
337
+ return checkPackageUpdate(dep, depInfo.versionSpec, depInfo.locations, options);
338
+ },
339
+ { concurrency: options.concurrency }
340
+ );
341
+ const toUpdate = results.filter((r) => r.updated && !r.error);
342
+ const updated = await updatePackageJsonFile(
343
+ packageJsonPath,
344
+ map,
345
+ toUpdate,
346
+ options.savePrefix
347
+ );
348
+ if (updated > 0) {
349
+ totalWorkspaceUpdated += updated;
350
+ relinka("log", `Updated ${updated} deps in ${packageJsonPath}`);
351
+ }
352
+ } catch (error) {
353
+ relinka(
354
+ "warn",
355
+ `Skipping ${packageJsonPath}: ${error instanceof Error ? error.message : String(error)}`
356
+ );
357
+ }
358
+ }
359
+ return totalWorkspaceUpdated;
360
+ }
361
+ function displayUpdateResults(results) {
362
+ const toUpdate = results.filter((r) => r.updated && !r.error);
363
+ const errors = results.filter((r) => r.error);
364
+ const upToDate = results.filter((r) => !r.updated && !r.error && r.semverCompatible);
365
+ if (errors.length > 0) {
366
+ relinka("warn", `Failed to check ${errors.length} dependencies:`);
367
+ for (const error of errors) {
368
+ relinka("warn", ` ${error.package} (${error.location}): ${error.error}`);
369
+ }
370
+ }
371
+ if (upToDate.length > 0) {
372
+ relinka("success", `${upToDate.length} dependencies are up to date`);
373
+ }
374
+ if (toUpdate.length === 0) {
375
+ relinka("success", `All ${upToDate.length} deps are already up to date`);
376
+ return;
377
+ }
378
+ relinka("info", `${toUpdate.length} dependencies can be updated:`);
379
+ const byLocation = /* @__PURE__ */ new Map();
380
+ for (const update of toUpdate) {
381
+ const location = update.location || "unknown";
382
+ if (!byLocation.has(location)) {
383
+ byLocation.set(location, []);
384
+ }
385
+ byLocation.get(location).push(update);
386
+ }
387
+ for (const [location, updates] of byLocation.entries()) {
388
+ relinka("log", ` ${location}:`);
389
+ for (const update of updates) {
390
+ relinka("log", ` ${update.package}: ${update.currentVersion} \u2192 ${update.latestVersion}`);
391
+ }
392
+ }
393
+ }
58
394
  async function getGlobalPackages(packageManager) {
59
395
  try {
60
396
  let result;
@@ -335,16 +671,16 @@ async function handleGlobalUpdates(args) {
335
671
  export default defineCommand({
336
672
  meta: {
337
673
  name: "update",
338
- description: "Update dependencies to the latest version"
674
+ description: "Update all dependencies and catalogs to their latest available versions (includes workspaces in monorepos)"
339
675
  },
340
676
  args: defineArgs({
341
677
  name: {
342
678
  type: "array",
343
- description: "The names of the dependencies to update (leave empty to update all)"
679
+ description: "Specific dependencies to update (default: all dependencies)"
344
680
  },
345
681
  ignore: {
346
682
  type: "array",
347
- description: "The names of the dependencies to ignore when --name is not provided"
683
+ description: "Dependencies to exclude from updates"
348
684
  },
349
685
  "dev-only": {
350
686
  type: "boolean",
@@ -364,11 +700,11 @@ export default defineCommand({
364
700
  },
365
701
  "catalogs-only": {
366
702
  type: "boolean",
367
- description: "Update only catalog dependencies"
703
+ description: "Update ONLY catalog dependencies (catalogs are included by default)"
368
704
  },
369
705
  "dry-run": {
370
706
  type: "boolean",
371
- description: "Show what would be updated without making changes"
707
+ description: "Preview updates without making changes"
372
708
  },
373
709
  concurrency: {
374
710
  type: "number",
@@ -377,43 +713,76 @@ export default defineCommand({
377
713
  },
378
714
  "with-check-script": {
379
715
  type: "boolean",
380
- description: "Run `bun check` after updating (exclusive for bun environment at the moment)"
716
+ description: "Run `bun check` after updating (Bun only)"
381
717
  },
382
718
  linker: {
383
719
  type: "string",
384
- description: "Linker strategy (pro tip: use 'isolated' in a monorepo project, 'hoisted' (default) in a project where you have only one package.json). When this option is explicitly set, it takes precedence over bunfig.toml install.linker setting.",
720
+ description: "Linker strategy: 'isolated' for monorepos, 'hoisted' for single packages",
385
721
  allowed: ["isolated", "hoisted"],
386
722
  default: "hoisted"
387
723
  },
388
724
  "with-install": {
389
725
  type: "boolean",
390
- description: "Run the install step after updating dependencies",
726
+ description: "Run install after updating",
391
727
  alias: "with-i"
392
728
  },
393
729
  global: {
394
730
  type: "boolean",
395
- description: "Update global packages instead of local dependencies",
731
+ description: "Update global packages",
396
732
  alias: "g"
397
733
  },
398
734
  interactive: {
399
735
  type: "boolean",
400
- description: "Interactively select which dependencies to update"
736
+ description: "Interactively select dependencies to update"
401
737
  },
402
738
  filter: {
403
739
  type: "array",
404
- description: "Filter workspaces to operate on (e.g., 'pkg-*', '!pkg-c', './packages/pkg-*')"
740
+ description: "Filter workspaces (e.g., 'pkg-*', '!pkg-c')"
741
+ },
742
+ "all-workspaces": {
743
+ type: "boolean",
744
+ description: "Update dependencies across all workspace packages (automatic in monorepos)"
745
+ },
746
+ "root-only": {
747
+ type: "boolean",
748
+ description: "Update only the root package.json (skip workspace packages in monorepos)"
405
749
  },
406
- "update-catalogs": {
750
+ "save-prefix": {
751
+ type: "string",
752
+ description: "Version prefix: '^', '~', or 'none' for exact",
753
+ allowed: ["^", "~", "none"],
754
+ default: "^"
755
+ },
756
+ "allow-major": {
407
757
  type: "boolean",
408
- description: "Update catalog dependencies to latest versions"
758
+ description: "Allow major version updates to latest available (disable with --no-allow-major)",
759
+ default: true
409
760
  }
410
761
  }),
411
762
  async run({ args }) {
412
763
  try {
764
+ const exclusiveFlags = [
765
+ args["dev-only"],
766
+ args["prod-only"],
767
+ args["peer-only"],
768
+ args["optional-only"],
769
+ args["catalogs-only"]
770
+ ];
771
+ if (exclusiveFlags.filter(Boolean).length > 1) {
772
+ relinka(
773
+ "error",
774
+ "Cannot specify multiple exclusive flags (--dev-only, --prod-only, --peer-only, --optional-only, --catalogs-only)"
775
+ );
776
+ return process.exit(1);
777
+ }
778
+ if (args["all-workspaces"] && args["root-only"]) {
779
+ relinka("error", "Cannot specify both --all-workspaces and --root-only flags");
780
+ return process.exit(1);
781
+ }
413
782
  if (args.global) {
414
783
  return await handleGlobalUpdates(args);
415
784
  }
416
- if (args["update-catalogs"]) {
785
+ if (args["catalogs-only"]) {
417
786
  const packageManager2 = await detectPackageManager(process.cwd());
418
787
  if (!packageManager2) {
419
788
  relinka("error", "Could not detect package manager");
@@ -438,146 +807,34 @@ export default defineCommand({
438
807
  let linkerSource = "CLI default";
439
808
  if (typeof Bun !== "undefined") {
440
809
  const bunfigConfig = await getConfigBunfig();
441
- if (bunfigConfig?.install?.linker) {
442
- const bunfigLinker = bunfigConfig.install.linker;
443
- if ((bunfigLinker === "isolated" || bunfigLinker === "hoisted") && args.linker === "hoisted") {
444
- effectiveLinker = bunfigLinker;
445
- linkerSource = bunfigLinker === "hoisted" ? "bunfig.toml (same as default)" : "bunfig.toml";
446
- }
810
+ const bunfigLinker = bunfigConfig?.install?.linker;
811
+ if (bunfigLinker && ["isolated", "hoisted"].includes(bunfigLinker) && args.linker === "hoisted") {
812
+ effectiveLinker = bunfigLinker;
813
+ linkerSource = bunfigLinker === "hoisted" ? "bunfig.toml (same as default)" : "bunfig.toml";
447
814
  }
448
815
  }
449
816
  if (args.linker !== "hoisted") {
450
817
  effectiveLinker = args.linker;
451
- linkerSource = "CLI argument (explicit override)";
818
+ linkerSource = "CLI override";
452
819
  }
453
820
  relinka("verbose", `Using linker strategy: ${effectiveLinker} (from ${linkerSource})`);
454
821
  const packageJson = await readPackageJSON();
455
- const dependencies = packageJson.dependencies || {};
456
- const devDependencies = packageJson.devDependencies || {};
457
- const peerDependencies = packageJson.peerDependencies || {};
458
- const optionalDependencies = packageJson.optionalDependencies || {};
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
- );
822
+ const { map: allDepsMap } = collectTargetDependencies(packageJson, args);
823
+ const candidates = prepareDependenciesForUpdate(allDepsMap, args);
824
+ if (candidates.length === 0) {
825
+ relinka("warn", "No dependencies to update based on provided filters");
574
826
  return;
575
827
  }
828
+ const options = {
829
+ allowMajor: !!args["allow-major"],
830
+ savePrefix: args["save-prefix"],
831
+ concurrency: args.concurrency
832
+ };
576
833
  const results = await pMap(
577
- semverDeps,
834
+ candidates,
578
835
  async (dep) => {
579
- const currentVersion = targetDeps[dep];
580
- if (!currentVersion) {
836
+ const depInfo = allDepsMap[dep];
837
+ if (!depInfo?.versionSpec) {
581
838
  return {
582
839
  package: dep,
583
840
  currentVersion: "unknown",
@@ -585,63 +842,21 @@ export default defineCommand({
585
842
  updated: false,
586
843
  error: "Current version not found",
587
844
  semverCompatible: false,
588
- location: depSources[dep]
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]
845
+ location: Array.from(depInfo?.locations || ["unknown"]).join(", ")
612
846
  };
613
847
  }
848
+ return checkPackageUpdate(dep, depInfo.versionSpec, depInfo.locations, options);
614
849
  },
615
850
  { concurrency: args.concurrency }
616
851
  );
852
+ displayUpdateResults(results);
617
853
  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
854
  if (toUpdate.length === 0) {
627
- relinka("success", `All ${upToDate.length} deps are already up to date`);
628
855
  return;
629
856
  }
630
- if (upToDate.length > 0) {
631
- relinka("success", `${upToDate.length} dependencies are up to date`);
632
- }
633
- if (toUpdate.length === 0) {
634
- relinka("success", `All ${upToDate.length} deps are already up to date`);
635
- return;
636
- }
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
857
  if (args.interactive) {
858
+ const errors = results.filter((r) => r.error);
859
+ const upToDate = results.filter((r) => !r.updated && !r.error && r.semverCompatible);
645
860
  const allPackages = [
646
861
  ...toUpdate.map((pkg) => ({
647
862
  ...pkg,
@@ -691,68 +906,46 @@ export default defineCommand({
691
906
  relinka("info", "Dry run mode - no changes were made");
692
907
  return;
693
908
  }
694
- const updatedPackageJson = { ...packageJson };
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(
909
+ const rootUpdated = await updatePackageJsonFile(
741
910
  packageJsonPath,
742
- JSON.stringify(updatedPackageJson, null, 2) + "\n",
743
- "utf8"
911
+ allDepsMap,
912
+ toUpdate,
913
+ args["save-prefix"]
744
914
  );
745
- relinka("success", `Updated ${toUpdate.length} dependencies in package.json`);
746
- if (args["with-install"] !== true) {
747
- const packageManager2 = await detectPackageManager(process.cwd());
748
- const installCommand = packageManager2 ? `${packageManager2.command} install` : "your package manager's install command";
915
+ let totalUpdated = rootUpdated;
916
+ const shouldUpdateWorkspaces = args["all-workspaces"] || // Explicit flag
917
+ !args["root-only"] && await isMonorepo(process.cwd());
918
+ if (shouldUpdateWorkspaces) {
919
+ const workspacePkgJsons = await findWorkspacePackageJsons(process.cwd());
920
+ if (workspacePkgJsons.length > 0) {
921
+ const workspaceUpdated = await updateWorkspacePackages(workspacePkgJsons, args, options);
922
+ totalUpdated += workspaceUpdated;
923
+ } else if (args["all-workspaces"]) {
924
+ relinka("warn", "No workspace packages found but --all-workspaces flag was provided");
925
+ }
926
+ } else if (await isMonorepo(process.cwd())) {
927
+ relinka("info", "Skipping workspace packages due to --root-only flag");
928
+ }
929
+ const isMonorepoProject = await isMonorepo(process.cwd());
930
+ if (isMonorepoProject && shouldUpdateWorkspaces) {
931
+ relinka(
932
+ "success",
933
+ `Updated ${totalUpdated} dependencies across workspace (root + workspaces)`
934
+ );
935
+ } else if (isMonorepoProject && !shouldUpdateWorkspaces) {
936
+ relinka("success", `Updated ${totalUpdated} dependencies in root package.json only`);
937
+ } else {
938
+ relinka("success", `Updated ${totalUpdated} dependencies`);
939
+ }
940
+ const packageManager = await detectPackageManager(process.cwd());
941
+ if (!args["with-install"]) {
942
+ const installCommand = packageManager?.command || "your package manager";
749
943
  relinka(
750
944
  "info",
751
- `Skipped install step. Use --with-install flag to run '${installCommand}' after updating.`
945
+ `Skipped install step. Use --with-install to run '${installCommand} install'.`
752
946
  );
753
947
  return;
754
948
  }
755
- const packageManager = await detectPackageManager(process.cwd());
756
949
  if (packageManager) {
757
950
  try {
758
951
  if (args.filter && args.filter.length > 0) {
@@ -13,13 +13,13 @@ export async function mkdist(options = {}) {
13
13
  options.srcDir = resolve(options.rootDir, options.srcDir || "src");
14
14
  options.distDir = resolve(options.rootDir, options.distDir || "dist");
15
15
  if (options.cleanDist !== false) {
16
- relinka("info", "Cleaning distribution directory...");
16
+ relinka("verbose", "Cleaning distribution directory...");
17
17
  await fsp.unlink(options.distDir).catch(() => {
18
18
  });
19
19
  await fsp.rm(options.distDir, { recursive: true, force: true });
20
20
  await fsp.mkdir(options.distDir, { recursive: true });
21
21
  }
22
- relinka("info", "Scanning input files...");
22
+ relinka("verbose", "Scanning input files...");
23
23
  const filePaths = await glob(options.pattern || "**", {
24
24
  absolute: false,
25
25
  ignore: ["**/node_modules", "**/coverage", "**/.git"],
@@ -36,10 +36,10 @@ export async function mkdist(options = {}) {
36
36
  getContents: () => fsp.readFile(sourcePath, { encoding: "utf8" })
37
37
  };
38
38
  });
39
- relinka("info", `Found ${files.length} files to process`);
39
+ relinka("verbose", `Found ${files.length} files to process`);
40
40
  options.typescript ||= {};
41
41
  if (options.typescript.compilerOptions) {
42
- relinka("info", "Normalizing TypeScript compiler options...");
42
+ relinka("verbose", "Normalizing TypeScript compiler options...");
43
43
  options.typescript.compilerOptions = await normalizeCompilerOptions(
44
44
  options.typescript.compilerOptions
45
45
  );
@@ -57,9 +57,9 @@ export async function mkdist(options = {}) {
57
57
  allowNonTsExtensions: true
58
58
  }
59
59
  );
60
- relinka("info", "Creating file loaders...");
60
+ relinka("verbose", "Creating file loaders...");
61
61
  const { loadFile } = createLoader(options);
62
- relinka("info", "Processing files with loaders...");
62
+ relinka("verbose", "Processing files with loaders...");
63
63
  const outputs = [];
64
64
  let processedCount = 0;
65
65
  await Promise.all(
@@ -71,7 +71,7 @@ export async function mkdist(options = {}) {
71
71
  processedCount++;
72
72
  })
73
73
  );
74
- relinka("info", "Normalizing output extensions...");
74
+ relinka("verbose", "Normalizing output extensions...");
75
75
  const pathConflicts = [];
76
76
  for (const output of outputs.filter((o) => o.extension)) {
77
77
  const renamed = basename(output.path, extname(output.path)) + output.extension;
@@ -88,7 +88,7 @@ export async function mkdist(options = {}) {
88
88
  }
89
89
  const dtsOutputs = outputs.filter((o) => o.declaration && !o.skip);
90
90
  if (dtsOutputs.length > 0) {
91
- relinka("info", `Generating TypeScript declarations for ${dtsOutputs.length} files...`);
91
+ relinka("verbose", `Generating TypeScript declarations for ${dtsOutputs.length} files...`);
92
92
  const vfs = new Map(dtsOutputs.map((o) => [o.srcPath, o.contents || ""]));
93
93
  const declarations = /* @__PURE__ */ Object.create(null);
94
94
  for (const loader of [getVueDeclarations, getDeclarations]) {
@@ -104,7 +104,7 @@ export async function mkdist(options = {}) {
104
104
  dtsProcessed++;
105
105
  }
106
106
  }
107
- relinka("info", "Resolving relative imports...");
107
+ relinka("verbose", "Resolving relative imports...");
108
108
  const outPaths = new Set(outputs.map((o) => o.path));
109
109
  const resolveId = (from, id = "", resolveExtensions) => {
110
110
  if (!id.startsWith(".")) {
@@ -137,7 +137,7 @@ export async function mkdist(options = {}) {
137
137
  );
138
138
  }
139
139
  const outputsToWrite = outputs.filter((o) => !o.skip);
140
- relinka("info", `Writing ${outputsToWrite.length} output files...`);
140
+ relinka("verbose", `Writing ${outputsToWrite.length} output files...`);
141
141
  const writtenFiles = [];
142
142
  const errors = [];
143
143
  let writtenCount = 0;
@@ -1,5 +1,5 @@
1
1
  import { endPrompt, startPrompt } from "@reliverse/rempts";
2
- const version = "1.7.82";
2
+ const version = "1.7.84";
3
3
  export async function showStartPrompt(isDev) {
4
4
  await startPrompt({
5
5
  titleColor: "inverse",
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.8",
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.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.82",
55
+ "version": "1.7.84",
56
56
  "keywords": [
57
57
  "reliverse",
58
58
  "cli",