@rainy-updates/cli 0.4.0 → 0.5.0-rc.1

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.
@@ -6,21 +6,23 @@ export class NpmRegistryClient {
6
6
  constructor() {
7
7
  this.requesterPromise = createRequester();
8
8
  }
9
- async resolveLatestVersion(packageName, timeoutMs = DEFAULT_TIMEOUT_MS) {
9
+ async resolvePackageMetadata(packageName, timeoutMs = DEFAULT_TIMEOUT_MS) {
10
10
  const requester = await this.requesterPromise;
11
11
  let lastError = null;
12
12
  for (let attempt = 1; attempt <= 3; attempt += 1) {
13
13
  try {
14
14
  const response = await requester(packageName, timeoutMs);
15
- if (response.status === 404)
16
- return null;
15
+ if (response.status === 404) {
16
+ return { latestVersion: null, versions: [] };
17
+ }
17
18
  if (response.status === 429 || response.status >= 500) {
18
19
  throw new Error(`Registry temporary error: ${response.status}`);
19
20
  }
20
21
  if (response.status < 200 || response.status >= 300) {
21
22
  throw new Error(`Registry request failed: ${response.status}`);
22
23
  }
23
- return response.data?.["dist-tags"]?.latest ?? null;
24
+ const versions = Object.keys(response.data?.versions ?? {});
25
+ return { latestVersion: response.data?.["dist-tags"]?.latest ?? null, versions };
24
26
  }
25
27
  catch (error) {
26
28
  lastError = String(error);
@@ -31,18 +33,22 @@ export class NpmRegistryClient {
31
33
  }
32
34
  throw new Error(`Unable to resolve ${packageName}: ${lastError ?? "unknown error"}`);
33
35
  }
34
- async resolveManyLatestVersions(packageNames, options) {
36
+ async resolveLatestVersion(packageName, timeoutMs = DEFAULT_TIMEOUT_MS) {
37
+ const metadata = await this.resolvePackageMetadata(packageName, timeoutMs);
38
+ return metadata.latestVersion;
39
+ }
40
+ async resolveManyPackageMetadata(packageNames, options) {
35
41
  const unique = Array.from(new Set(packageNames));
36
- const versions = new Map();
42
+ const metadata = new Map();
37
43
  const errors = new Map();
38
44
  const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
39
45
  const results = await asyncPool(options.concurrency, unique.map((pkg) => async () => {
40
46
  try {
41
- const latest = await this.resolveLatestVersion(pkg, timeoutMs);
42
- return { pkg, latest, error: null };
47
+ const packageMetadata = await this.resolvePackageMetadata(pkg, timeoutMs);
48
+ return { pkg, packageMetadata, error: null };
43
49
  }
44
50
  catch (error) {
45
- return { pkg, latest: null, error: String(error) };
51
+ return { pkg, packageMetadata: null, error: String(error) };
46
52
  }
47
53
  }));
48
54
  for (const result of results) {
@@ -52,11 +58,22 @@ export class NpmRegistryClient {
52
58
  if (result.error) {
53
59
  errors.set(result.pkg, result.error);
54
60
  }
55
- else {
56
- versions.set(result.pkg, result.latest);
61
+ else if (result.packageMetadata) {
62
+ metadata.set(result.pkg, result.packageMetadata);
57
63
  }
58
64
  }
59
- return { versions, errors };
65
+ return { metadata, errors };
66
+ }
67
+ async resolveManyLatestVersions(packageNames, options) {
68
+ const metadataResult = await this.resolveManyPackageMetadata(packageNames, options);
69
+ const versions = new Map();
70
+ for (const [name, value] of metadataResult.metadata) {
71
+ versions.set(name, value.latestVersion);
72
+ }
73
+ return {
74
+ versions,
75
+ errors: metadataResult.errors,
76
+ };
60
77
  }
61
78
  }
62
79
  function sleep(ms) {
@@ -1,6 +1,7 @@
1
1
  export type DependencyKind = "dependencies" | "devDependencies" | "optionalDependencies" | "peerDependencies";
2
2
  export type TargetLevel = "patch" | "minor" | "major" | "latest";
3
3
  export type OutputFormat = "table" | "json" | "minimal" | "github";
4
+ export type FailOnLevel = "none" | "patch" | "minor" | "major" | "any";
4
5
  export interface RunOptions {
5
6
  cwd: string;
6
7
  target: TargetLevel;
@@ -18,6 +19,8 @@ export interface RunOptions {
18
19
  offline: boolean;
19
20
  policyFile?: string;
20
21
  prReportFile?: string;
22
+ failOn?: FailOnLevel;
23
+ maxUpdates?: number;
21
24
  }
22
25
  export interface CheckOptions extends RunOptions {
23
26
  }
@@ -26,6 +29,13 @@ export interface UpgradeOptions extends RunOptions {
26
29
  packageManager: "auto" | "npm" | "pnpm";
27
30
  sync: boolean;
28
31
  }
32
+ export interface BaselineOptions {
33
+ cwd: string;
34
+ workspace: boolean;
35
+ includeKinds: DependencyKind[];
36
+ filePath: string;
37
+ ci: boolean;
38
+ }
29
39
  export interface PackageDependency {
30
40
  name: string;
31
41
  range: string;
@@ -78,6 +88,7 @@ export interface CachedVersion {
78
88
  packageName: string;
79
89
  target: TargetLevel;
80
90
  latestVersion: string;
91
+ availableVersions: string[];
81
92
  fetchedAt: number;
82
93
  ttlSeconds: number;
83
94
  }
@@ -9,5 +9,6 @@ export declare function parseVersion(raw: string): ParsedVersion | null;
9
9
  export declare function compareVersions(a: ParsedVersion, b: ParsedVersion): number;
10
10
  export declare function classifyDiff(currentRange: string, nextVersion: string): TargetLevel;
11
11
  export declare function pickTargetVersion(currentRange: string, latestVersion: string, target: TargetLevel): string | null;
12
+ export declare function pickTargetVersionFromAvailable(currentRange: string, availableVersions: string[], latestVersion: string, target: TargetLevel): string | null;
12
13
  export declare function applyRangeStyle(previousRange: string, version: string): string;
13
14
  export declare function clampTarget(requested: TargetLevel, maxAllowed?: TargetLevel): TargetLevel;
@@ -64,6 +64,30 @@ export function pickTargetVersion(currentRange, latestVersion, target) {
64
64
  }
65
65
  return latestVersion;
66
66
  }
67
+ export function pickTargetVersionFromAvailable(currentRange, availableVersions, latestVersion, target) {
68
+ const current = parseVersion(currentRange);
69
+ if (!current || target === "latest")
70
+ return latestVersion;
71
+ const parsed = availableVersions
72
+ .map((version) => ({ raw: version, parsed: parseVersion(version) }))
73
+ .filter((item) => item.parsed !== null)
74
+ .filter((item) => compareVersions(item.parsed, current) > 0)
75
+ .sort((a, b) => compareVersions(a.parsed, b.parsed));
76
+ if (parsed.length === 0)
77
+ return null;
78
+ if (target === "major") {
79
+ return parsed[parsed.length - 1]?.raw ?? null;
80
+ }
81
+ if (target === "minor") {
82
+ const sameMajor = parsed.filter((item) => item.parsed.major === current.major);
83
+ return sameMajor.length > 0 ? sameMajor[sameMajor.length - 1].raw : null;
84
+ }
85
+ if (target === "patch") {
86
+ const sameLine = parsed.filter((item) => item.parsed.major === current.major && item.parsed.minor === current.minor);
87
+ return sameLine.length > 0 ? sameLine[sameLine.length - 1].raw : null;
88
+ }
89
+ return latestVersion;
90
+ }
67
91
  export function applyRangeStyle(previousRange, version) {
68
92
  const prefix = normalizeRangePrefix(previousRange);
69
93
  return `${prefix}${version}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rainy-updates/cli",
3
- "version": "0.4.0",
3
+ "version": "0.5.0-rc.1",
4
4
  "description": "Agentic CLI to check and upgrade npm/pnpm dependencies for CI workflows",
5
5
  "type": "module",
6
6
  "private": false,
@@ -36,7 +36,9 @@
36
36
  "dist",
37
37
  "README.md",
38
38
  "CHANGELOG.md",
39
- "LICENSE"
39
+ "LICENSE",
40
+ "SECURITY.md",
41
+ "CODE_OF_CONDUCT.md"
40
42
  ],
41
43
  "scripts": {
42
44
  "clean": "rm -rf dist",
@@ -60,7 +62,6 @@
60
62
  "typescript": "^5.9.3"
61
63
  },
62
64
  "optionalDependencies": {
63
- "better-sqlite3": "^12.6.2",
64
65
  "undici": "^7.22.0"
65
66
  }
66
67
  }