@reliverse/dler 2.3.3 → 2.3.4

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.
@@ -4,6 +4,42 @@ import fs from "@reliverse/relifso";
4
4
  import { logger } from "@reliverse/relinka";
5
5
  import { $ } from "bun";
6
6
  import semver from "semver";
7
+ import { loadCache, saveCache } from "../../utils/cache.js";
8
+ const versionCache = /* @__PURE__ */ new Map();
9
+ const CACHE_TTL = 5 * 60 * 1e3;
10
+ const PERSISTENT_CACHE_TTL = 24 * 60 * 60 * 1e3;
11
+ async function loadPersistentCache(verbose = false) {
12
+ try {
13
+ const cacheData = await loadCache("update");
14
+ if (cacheData) {
15
+ if (Date.now() - cacheData.lastUpdated < PERSISTENT_CACHE_TTL) {
16
+ for (const [pkg, data] of Object.entries(cacheData.packages)) {
17
+ versionCache.set(pkg, data);
18
+ }
19
+ if (verbose) {
20
+ logger.debug(`Loaded ${Object.keys(cacheData.packages).length} cached package versions`);
21
+ }
22
+ } else {
23
+ logger.debug("Persistent cache expired, ignoring");
24
+ }
25
+ }
26
+ } catch (error) {
27
+ logger.debug(
28
+ `Failed to load persistent cache: ${error instanceof Error ? error.message : String(error)}, continuing without it`
29
+ );
30
+ }
31
+ }
32
+ async function savePersistentCache() {
33
+ try {
34
+ const cacheData = {
35
+ packages: Object.fromEntries(versionCache.entries()),
36
+ lastUpdated: Date.now()
37
+ };
38
+ await saveCache("update", cacheData);
39
+ } catch (error) {
40
+ logger.debug("Failed to save persistent cache");
41
+ }
42
+ }
7
43
  export function isNpmAlias(versionSpec) {
8
44
  return versionSpec.startsWith("npm:");
9
45
  }
@@ -24,9 +60,6 @@ export function isSemverCompatible(currentVersionRange, latestVersion) {
24
60
  if (isWorkspaceDependency(currentVersionRange)) {
25
61
  return false;
26
62
  }
27
- if (!(currentVersionRange.startsWith("^") || currentVersionRange.startsWith("~"))) {
28
- return false;
29
- }
30
63
  return semver.satisfies(latestVersion, currentVersionRange);
31
64
  } catch {
32
65
  return false;
@@ -38,75 +71,54 @@ export function collectTargetDependencies(pkg) {
38
71
  const devDependencies = pkg.devDependencies || {};
39
72
  const peerDependencies = pkg.peerDependencies || {};
40
73
  const optionalDependencies = pkg.optionalDependencies || {};
41
- for (const dep of Object.keys(dependencies)) {
42
- const version = dependencies[dep];
43
- if (!version) {
44
- continue;
45
- }
74
+ const addDependency = (dep, version, location) => {
75
+ if (!version) return;
76
+ if (isNonSemverSpecifier(version)) return;
46
77
  if (!map[dep]) {
47
78
  map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
48
79
  }
49
80
  map[dep].versionSpec = version;
50
- map[dep].locations.add("dependencies");
81
+ map[dep].locations.add(location);
82
+ };
83
+ for (const dep of Object.keys(dependencies)) {
84
+ const version = dependencies[dep];
85
+ if (version) {
86
+ addDependency(dep, version, "dependencies");
87
+ }
51
88
  }
52
89
  for (const dep of Object.keys(devDependencies)) {
53
90
  const version = devDependencies[dep];
54
- if (!version) {
55
- continue;
56
- }
57
- if (!map[dep]) {
58
- map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
91
+ if (version) {
92
+ addDependency(dep, version, "devDependencies");
59
93
  }
60
- map[dep].versionSpec = version;
61
- map[dep].locations.add("devDependencies");
62
94
  }
63
95
  for (const dep of Object.keys(peerDependencies)) {
64
96
  const version = peerDependencies[dep];
65
- if (!version) {
66
- continue;
67
- }
68
- if (!map[dep]) {
69
- map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
97
+ if (version) {
98
+ addDependency(dep, version, "peerDependencies");
70
99
  }
71
- map[dep].versionSpec = version;
72
- map[dep].locations.add("peerDependencies");
73
100
  }
74
101
  for (const dep of Object.keys(optionalDependencies)) {
75
102
  const version = optionalDependencies[dep];
76
- if (!version) {
77
- continue;
78
- }
79
- if (!map[dep]) {
80
- map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
103
+ if (version) {
104
+ addDependency(dep, version, "optionalDependencies");
81
105
  }
82
- map[dep].versionSpec = version;
83
- map[dep].locations.add("optionalDependencies");
84
106
  }
85
107
  const workspacesCatalog = pkg.workspaces?.catalog || {};
86
108
  for (const dep of Object.keys(workspacesCatalog)) {
87
109
  const version = workspacesCatalog[dep];
88
- if (!version) {
89
- continue;
110
+ if (version) {
111
+ addDependency(dep, version, "catalog");
90
112
  }
91
- if (!map[dep]) {
92
- map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
93
- }
94
- map[dep].versionSpec = version;
95
- map[dep].locations.add("catalog");
96
113
  }
97
114
  const workspacesCatalogs = pkg.workspaces?.catalogs || {};
98
115
  for (const catalogName of Object.keys(workspacesCatalogs)) {
99
116
  const catalog = workspacesCatalogs[catalogName] || {};
100
117
  for (const dep of Object.keys(catalog)) {
101
118
  const version = catalog[dep];
102
- if (!version) {
103
- continue;
119
+ if (version) {
120
+ addDependency(dep, version, `catalogs.${catalogName}`);
104
121
  }
105
- if (!map[dep]) {
106
- map[dep] = { versionSpec: version, locations: /* @__PURE__ */ new Set() };
107
- }
108
- map[dep].versionSpec = version;
109
- map[dep].locations.add(`catalogs.${catalogName}`);
110
122
  }
111
123
  }
112
124
  const topLevelCatalog = pkg.catalog || {};
@@ -206,26 +218,51 @@ export function applyVersionUpdate(pkg, depName, newVersion, locations) {
206
218
  }
207
219
  }
208
220
  export async function fetchVersionFromRegistry(packageName) {
209
- const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`);
221
+ const normalizedName = packageName.toLowerCase();
222
+ const response = await fetch(`https://registry.npmjs.org/${normalizedName}/latest`, {
223
+ headers: {
224
+ // Use npm install headers for better compatibility and potentially faster responses
225
+ accept: "application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*"
226
+ }
227
+ });
210
228
  if (!response.ok) {
211
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
229
+ if (response.status === 404) {
230
+ throw new Error(`Package '${packageName}' not found in npm registry`);
231
+ }
232
+ throw new Error(
233
+ `Failed to fetch version for '${packageName}': HTTP ${response.status} ${response.statusText}`
234
+ );
212
235
  }
213
236
  const data = await response.json();
237
+ if (!data.version) {
238
+ throw new Error(`No version found for package '${packageName}'`);
239
+ }
214
240
  return data.version;
215
241
  }
216
242
  export async function getLatestVersion(packageName) {
243
+ const cached = versionCache.get(packageName);
244
+ if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
245
+ return cached.version;
246
+ }
217
247
  try {
218
- return await fetchVersionFromRegistry(packageName);
248
+ const version = await fetchVersionFromRegistry(packageName);
249
+ versionCache.set(packageName, { version, timestamp: Date.now() });
250
+ savePersistentCache().catch(() => {
251
+ });
252
+ return version;
219
253
  } catch (error) {
220
254
  throw new Error(`Failed to get latest version for ${packageName}: ${error}`);
221
255
  }
222
256
  }
257
+ export async function initializeCache(verbose = false) {
258
+ await loadPersistentCache(verbose);
259
+ }
223
260
  export async function checkPackageUpdate(packageName, versionSpec, locations, options) {
224
261
  try {
225
262
  const latest = await getLatestVersion(packageName);
226
- const cleanCurrent = versionSpec.replace(/^[\^~]/, "");
263
+ const cleanCurrent = versionSpec.replace(/^[\^~>=<]+/, "");
227
264
  let isCompatible = isSemverCompatible(versionSpec, latest);
228
- const isExact = !(versionSpec.startsWith("^") || versionSpec.startsWith("~"));
265
+ const isExact = !(versionSpec.startsWith("^") || versionSpec.startsWith("~") || versionSpec.startsWith(">=") || versionSpec.startsWith(">") || versionSpec.startsWith("<=") || versionSpec.startsWith("<") || versionSpec.startsWith("="));
229
266
  if (isExact || !isCompatible && options.allowMajor) {
230
267
  isCompatible = true;
231
268
  }
@@ -249,6 +286,60 @@ export async function checkPackageUpdate(packageName, versionSpec, locations, op
249
286
  };
250
287
  }
251
288
  }
289
+ export function prepareDependenciesForUpdateFromMap(allDepsMap, args) {
290
+ const depsToUpdate = Array.from(allDepsMap.keys());
291
+ let filteredDeps = [];
292
+ if (args.name && args.name.length > 0) {
293
+ const namePatterns = args.name;
294
+ filteredDeps = depsToUpdate.filter((dep) => {
295
+ return namePatterns.some((pattern) => {
296
+ if (pattern.includes("*") || pattern.includes("?") || pattern.includes("[") || pattern.includes("{")) {
297
+ return zeptomatch.isMatch(pattern, dep);
298
+ }
299
+ return dep === pattern;
300
+ });
301
+ });
302
+ const exactMatches = filteredDeps.filter((dep) => namePatterns.includes(dep));
303
+ const patternMatches = filteredDeps.length - exactMatches.length;
304
+ if (patternMatches > 0) {
305
+ logger.debug(
306
+ `Found ${exactMatches.length} exact matches and ${patternMatches} pattern matches`
307
+ );
308
+ }
309
+ if (filteredDeps.length === 0) {
310
+ logger.warn(`No dependencies found matching patterns: ${namePatterns.join(", ")}`);
311
+ }
312
+ } else {
313
+ const ignoreList = args.ignore || [];
314
+ filteredDeps = depsToUpdate.filter((dep) => {
315
+ return !ignoreList.some((ignorePattern) => {
316
+ if (ignorePattern.includes("*") || ignorePattern.includes("?") || ignorePattern.includes("[") || ignorePattern.includes("{")) {
317
+ return zeptomatch.isMatch(ignorePattern, dep);
318
+ }
319
+ return dep === ignorePattern;
320
+ });
321
+ });
322
+ const ignoredCount = depsToUpdate.length - filteredDeps.length;
323
+ if (ignoredCount > 0 && ignoreList.length > 0) {
324
+ logger.debug(`Ignored ${ignoredCount} dependencies matching ignore patterns`);
325
+ }
326
+ }
327
+ const ignoreFields = args.ignoreFields || [];
328
+ if (ignoreFields.length > 0) {
329
+ filteredDeps = filteredDeps.filter((dep) => {
330
+ const depInfo = allDepsMap.get(dep);
331
+ if (!depInfo) return false;
332
+ return !Array.from(depInfo.locations).some((location) => ignoreFields.includes(location));
333
+ });
334
+ const ignoredFieldsCount = depsToUpdate.length - filteredDeps.length;
335
+ if (ignoredFieldsCount > 0) {
336
+ logger.debug(
337
+ `Ignored ${ignoredFieldsCount} dependencies in ignored fields: ${ignoreFields.join(", ")}`
338
+ );
339
+ }
340
+ }
341
+ return filteredDeps;
342
+ }
252
343
  export function prepareDependenciesForUpdate(allDepsMap, args) {
253
344
  const depsToUpdate = Object.keys(allDepsMap);
254
345
  let filteredDeps = [];
@@ -369,13 +460,6 @@ export function displayStructuredUpdateResults(results, packageJsonFiles, fileDe
369
460
  logger.log("");
370
461
  }
371
462
  if (!showDetails) {
372
- if (toUpdate.length === 0) {
373
- logger.log(`All ${upToDate.length} dependencies are already up to date`);
374
- } else {
375
- logger.log(
376
- `${toUpdate.length} dependencies can be updated across ${packageJsonFiles.length} package.json files`
377
- );
378
- }
379
463
  return;
380
464
  }
381
465
  const resultsByFile = /* @__PURE__ */ new Map();
@@ -460,13 +544,17 @@ export function displayStructuredUpdateResults(results, packageJsonFiles, fileDe
460
544
  );
461
545
  }
462
546
  }
463
- export async function runInstallCommand() {
547
+ export async function runInstallCommand(verbose = false) {
464
548
  try {
465
- await $`bun install`.quiet();
549
+ const cmd = $`bun install`;
550
+ await cmd;
466
551
  } catch (error) {
467
- logger.warn(
468
- `Failed to run install command: ${error instanceof Error ? error.message : String(error)}`
469
- );
552
+ logger.warn("Failed to run install command:");
553
+ if (error instanceof Error) {
554
+ logger.warn(error.message);
555
+ } else {
556
+ logger.warn(String(error));
557
+ }
470
558
  throw error;
471
559
  }
472
560
  }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Get the cache file path for a specific command
3
+ */
4
+ export declare function getCacheFilePath(commandName: string): string;
5
+ /**
6
+ * Ensure the cache directory exists
7
+ */
8
+ export declare function ensureCacheDir(): Promise<void>;
9
+ /**
10
+ * Load JSON data from cache file
11
+ */
12
+ export declare function loadCache<T>(commandName: string): Promise<T | null>;
13
+ /**
14
+ * Save JSON data to cache file
15
+ */
16
+ export declare function saveCache<T>(commandName: string, data: T): Promise<void>;
17
+ /**
18
+ * Check if cache file exists and get its modification time
19
+ */
20
+ export declare function getCacheFileInfo(commandName: string): {
21
+ exists: boolean;
22
+ mtime?: number;
23
+ };
24
+ /**
25
+ * Clear cache for a specific command
26
+ */
27
+ export declare function clearCommandCache(commandName: string): Promise<void>;
28
+ /**
29
+ * Clear all dler caches
30
+ */
31
+ export declare function clearAllCaches(): Promise<void>;
@@ -0,0 +1,60 @@
1
+ import { existsSync, statSync } from "node:fs";
2
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ const CACHE_BASE_DIR = "node_modules/.cache/dler";
5
+ export function getCacheFilePath(commandName) {
6
+ return join(CACHE_BASE_DIR, `${commandName}.json`);
7
+ }
8
+ export async function ensureCacheDir() {
9
+ try {
10
+ await mkdir(CACHE_BASE_DIR, { recursive: true });
11
+ } catch {
12
+ }
13
+ }
14
+ export async function loadCache(commandName) {
15
+ const cachePath = getCacheFilePath(commandName);
16
+ try {
17
+ if (!existsSync(cachePath)) {
18
+ return null;
19
+ }
20
+ const content = await readFile(cachePath, "utf-8");
21
+ return JSON.parse(content);
22
+ } catch {
23
+ return null;
24
+ }
25
+ }
26
+ export async function saveCache(commandName, data) {
27
+ const cachePath = getCacheFilePath(commandName);
28
+ try {
29
+ await ensureCacheDir();
30
+ await writeFile(cachePath, JSON.stringify(data, null, 2), "utf-8");
31
+ } catch {
32
+ }
33
+ }
34
+ export function getCacheFileInfo(commandName) {
35
+ const cachePath = getCacheFilePath(commandName);
36
+ if (!existsSync(cachePath)) {
37
+ return { exists: false };
38
+ }
39
+ try {
40
+ const stats = statSync(cachePath);
41
+ return { exists: true, mtime: stats.mtime.getTime() };
42
+ } catch {
43
+ return { exists: false };
44
+ }
45
+ }
46
+ export async function clearCommandCache(commandName) {
47
+ const cachePath = getCacheFilePath(commandName);
48
+ try {
49
+ if (existsSync(cachePath)) {
50
+ await writeFile(cachePath, "{}", "utf-8");
51
+ }
52
+ } catch {
53
+ }
54
+ }
55
+ export async function clearAllCaches() {
56
+ try {
57
+ await ensureCacheDir();
58
+ } catch {
59
+ }
60
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reliverse/dler",
3
- "version": "2.3.3",
3
+ "version": "2.3.4",
4
4
  "description": "@reliverse/dler is a framework which helps TypeScript and JavaScript developers create their libraries and CLI tools. It provides ready-to-use primitives, so you don't have to write them from scratch.",
5
5
  "keywords": [
6
6
  "build-tool",
@@ -31,7 +31,7 @@
31
31
  ],
32
32
  "type": "module",
33
33
  "module": "./dist/mod.js",
34
- "types": "./dist/mod.d.d.ts",
34
+ "types": "./dist/mod.d.d.d.ts",
35
35
  "exports": {
36
36
  ".": {
37
37
  "types": "./dist/mod.d.ts",
@@ -39,26 +39,27 @@
39
39
  }
40
40
  },
41
41
  "dependencies": {
42
- "@reliverse/build": "2.3.3",
43
- "@reliverse/bump": "2.3.3",
44
- "@reliverse/config": "2.3.3",
45
- "@reliverse/datetime": "2.3.3",
46
- "@reliverse/helpers": "2.3.3",
47
- "@reliverse/mapkit": "2.3.3",
48
- "@reliverse/matcha": "2.3.3",
49
- "@reliverse/pathkit": "2.3.3",
50
- "@reliverse/publish": "2.3.3",
51
- "@reliverse/relico": "2.3.3",
52
- "@reliverse/relifso": "2.3.3",
53
- "@reliverse/relinka": "2.3.3",
54
- "@reliverse/rempts-core": "2.3.3",
55
- "@reliverse/rempts-utils": "2.3.3",
56
- "@reliverse/typerso": "2.3.3",
42
+ "@reliverse/build": "2.3.4",
43
+ "@reliverse/bump": "2.3.4",
44
+ "@reliverse/config": "2.3.4",
45
+ "@reliverse/datetime": "2.3.4",
46
+ "@reliverse/helpers": "2.3.4",
47
+ "@reliverse/mapkit": "2.3.4",
48
+ "@reliverse/matcha": "2.3.4",
49
+ "@reliverse/pathkit": "2.3.4",
50
+ "@reliverse/publish": "2.3.4",
51
+ "@reliverse/relico": "2.3.4",
52
+ "@reliverse/relifso": "2.3.4",
53
+ "@reliverse/relinka": "2.3.4",
54
+ "@reliverse/rempts-core": "2.3.4",
55
+ "@reliverse/rempts-utils": "2.3.4",
56
+ "@reliverse/typerso": "2.3.4",
57
57
  "c12": "^3.3.3",
58
58
  "clipboardy": "^5.0.2",
59
59
  "lookpath": "^1.2.3",
60
60
  "semver": "^7.7.3",
61
- "arktype": "^2.1.29"
61
+ "arktype": "^2.1.29",
62
+ "lodash": "^4.17.21"
62
63
  },
63
64
  "publishConfig": {
64
65
  "access": "public"