inup 1.6.6 → 1.6.8

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.
Files changed (110) hide show
  1. package/README.md +25 -2
  2. package/dist/{interactive-ui.js → app/interactive-ui.js} +34 -21
  3. package/dist/{core → app}/upgrade-runner.js +18 -22
  4. package/dist/cli.js +19 -18
  5. package/dist/{services → features/audit}/background-audit.js +2 -2
  6. package/dist/features/{headless/vulnerability-audit.js → audit/headless-audit.js} +8 -11
  7. package/dist/features/audit/index.js +36 -0
  8. package/dist/{ui/presenters/vulnerability.js → features/audit/presenter.js} +1 -3
  9. package/dist/{ui/controllers → features/audit}/vulnerability-audit-controller.js +14 -8
  10. package/dist/{services → features/audit}/vulnerability-checker.js +9 -10
  11. package/dist/features/changelog/clients/github-client.js +41 -21
  12. package/dist/features/changelog/clients/npm-registry-client.js +16 -2
  13. package/dist/features/changelog/index.js +1 -1
  14. package/dist/features/changelog/services/package-metadata-service.js +6 -2
  15. package/dist/features/changelog/services/release-notes-service.js +9 -12
  16. package/dist/features/changelog/types.js +3 -0
  17. package/dist/features/debug/index.js +3 -4
  18. package/dist/features/debug/{services/perf-logger.js → perf-logger.js} +15 -15
  19. package/dist/features/debug/types.js +3 -0
  20. package/dist/features/headless/headless-runner.js +32 -19
  21. package/dist/features/headless/index.js +2 -5
  22. package/dist/features/headless/report.js +2 -0
  23. package/dist/features/interactive/controllers/index.js +6 -0
  24. package/dist/{ui → features/interactive}/controllers/package-info-modal-controller.js +3 -3
  25. package/dist/features/interactive/index.js +21 -0
  26. package/dist/{ui → features/interactive}/input-handler.js +6 -6
  27. package/dist/{ui → features/interactive}/modal/index.js +1 -1
  28. package/dist/{ui → features/interactive}/modal/layout.js +5 -5
  29. package/dist/{ui/renderer/package-list.js → features/interactive/modal/package-info-sections/index.js} +3 -3
  30. package/dist/{ui → features/interactive}/modal/package-info-sections/release-notes.js +1 -1
  31. package/dist/{ui → features/interactive}/modal/package-info-sections/sections.js +55 -24
  32. package/dist/{ui → features/interactive}/modal/package-info-sections/text.js +6 -6
  33. package/dist/{ui → features/interactive}/modal/package-info.js +33 -18
  34. package/dist/features/interactive/modal/types.js +3 -0
  35. package/dist/{ui → features/interactive}/presenters/health.js +2 -2
  36. package/dist/{ui → features/interactive}/renderer/confirmation.js +6 -3
  37. package/dist/{ui → features/interactive}/renderer/help-modal.js +3 -3
  38. package/dist/{ui → features/interactive}/renderer/index.js +3 -4
  39. package/dist/{types.js → features/interactive/renderer/package-list/index.js} +3 -4
  40. package/dist/{ui → features/interactive}/renderer/package-list/interface.js +15 -16
  41. package/dist/{ui → features/interactive}/renderer/package-list/rows.js +31 -25
  42. package/dist/features/{debug → interactive}/renderer/performance-modal.js +3 -3
  43. package/dist/{ui/utils/version.js → features/interactive/renderer/version-format.js} +9 -13
  44. package/dist/{ui → features/interactive}/session/action-dispatcher.js +2 -2
  45. package/dist/{ui → features/interactive}/session/index.js +5 -4
  46. package/dist/{ui → features/interactive}/session/interactive-session.js +44 -23
  47. package/dist/{ui → features/interactive}/session/selection-state-builder.js +25 -9
  48. package/dist/{ui → features/interactive}/state/filter-manager.js +3 -3
  49. package/dist/{ui → features/interactive}/state/index.js +7 -7
  50. package/dist/{ui → features/interactive}/state/state-manager.js +10 -8
  51. package/dist/{ui → features/interactive}/state/theme-manager.js +7 -5
  52. package/dist/{ui → features/interactive}/themes-colors.js +3 -1
  53. package/dist/features/upgrade/index.js +8 -0
  54. package/dist/{core → features/upgrade}/package-detector.js +96 -37
  55. package/dist/{core → features/upgrade}/upgrader.js +84 -35
  56. package/dist/index.js +2 -2
  57. package/dist/{config → shared/config}/package-meta.js +1 -1
  58. package/dist/{config → shared/config}/project-config.js +10 -8
  59. package/dist/{utils/config.js → shared/config/user-config.js} +11 -11
  60. package/dist/{utils → shared}/debug-logger.js +9 -9
  61. package/dist/{utils → shared}/exec.js +4 -4
  62. package/dist/{ui/modal/package-info-sections.js → shared/fs/index.js} +4 -3
  63. package/dist/{utils/filesystem → shared/fs}/io.js +3 -4
  64. package/dist/shared/fs/paths.js +19 -0
  65. package/dist/{utils/filesystem → shared/fs}/scan.js +23 -20
  66. package/dist/{utils → shared}/git.js +3 -3
  67. package/dist/{services → shared}/http/etag-store.js +56 -4
  68. package/dist/{services → shared}/http/resizable-semaphore.js +3 -1
  69. package/dist/{utils → shared}/local-env.js +8 -8
  70. package/dist/{services/package-manager-detector.js → shared/package-manager.js} +26 -25
  71. package/dist/shared/pnpm-catalogs.js +138 -0
  72. package/dist/{services → shared/registry}/npm-registry.js +54 -33
  73. package/dist/shared/registry/registry-config.js +76 -0
  74. package/dist/{services → shared/registry}/version-checker.js +25 -26
  75. package/dist/{ui/utils → shared/terminal}/cursor.js +1 -1
  76. package/dist/{ui/utils → shared/terminal}/index.js +5 -7
  77. package/dist/{ui/utils → shared/terminal}/terminal-input.js +5 -0
  78. package/dist/shared/terminal/text.js +48 -0
  79. package/dist/shared/types/index.js +20 -0
  80. package/dist/{utils/version.js → shared/versions.js} +45 -30
  81. package/package.json +21 -8
  82. package/dist/core/index.js +0 -23
  83. package/dist/features/changelog/types/changelog.types.js +0 -3
  84. package/dist/features/debug/types/debug.types.js +0 -3
  85. package/dist/services/index.js +0 -25
  86. package/dist/ui/controllers/index.js +0 -8
  87. package/dist/ui/index.js +0 -27
  88. package/dist/ui/presenters/index.js +0 -11
  89. package/dist/ui/utils/text.js +0 -76
  90. package/dist/utils/filesystem/paths.js +0 -19
  91. package/dist/utils/filesystem.js +0 -20
  92. package/dist/utils/index.js +0 -34
  93. /package/dist/{ui/modal → features/audit}/types.js +0 -0
  94. /package/dist/features/debug/{services/performance-tracker.js → performance-tracker.js} +0 -0
  95. /package/dist/{ui → features/interactive}/keymap.js +0 -0
  96. /package/dist/{ui → features/interactive}/modal/theme-selector.js +0 -0
  97. /package/dist/{ui → features/interactive}/state/modal-manager.js +0 -0
  98. /package/dist/{ui → features/interactive}/state/navigation-manager.js +0 -0
  99. /package/dist/{ui → features/interactive}/themes.js +0 -0
  100. /package/dist/{config → shared/config}/constants.js +0 -0
  101. /package/dist/{config → shared/config}/index.js +0 -0
  102. /package/dist/{utils → shared}/engines.js +0 -0
  103. /package/dist/{services → shared}/http/adaptive-controller.js +0 -0
  104. /package/dist/{services → shared}/http/inflight.js +0 -0
  105. /package/dist/{services → shared}/http/retry.js +0 -0
  106. /package/dist/{utils → shared}/manifest.js +0 -0
  107. /package/dist/{utils → shared/terminal}/color.js +0 -0
  108. /package/dist/{types → shared/types}/domain.js +0 -0
  109. /package/dist/{types → shared/types}/streaming.js +0 -0
  110. /package/dist/{types → shared/types}/ui.js +0 -0
@@ -1,9 +1,41 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GitHubClient = void 0;
4
+ const config_1 = require("../../../shared/config");
4
5
  const repository_ref_1 = require("../parsers/repository-ref");
5
- const config_1 = require("../../../config");
6
6
  const GITHUB_RELEASES_PAGE_LIMIT = 3;
7
+ /**
8
+ * Headers for api.github.com requests. Honors an ambient token (GitHub Actions
9
+ * sets GITHUB_TOKEN, gh CLI users often export GH_TOKEN): authenticated requests
10
+ * get 5,000 req/hr instead of the 60 req/hr anonymous limit, which large upgrade
11
+ * sessions can exhaust while fetching release notes.
12
+ */
13
+ function githubApiHeaders() {
14
+ const headers = {
15
+ accept: 'application/vnd.github.v3+json',
16
+ 'user-agent': `${config_1.PACKAGE_NAME}-cli`,
17
+ };
18
+ const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
19
+ if (token) {
20
+ headers.authorization = `Bearer ${token}`;
21
+ }
22
+ return headers;
23
+ }
24
+ /**
25
+ * GET an api.github.com URL, retrying anonymously when the ambient token is
26
+ * rejected (401). A stale/revoked GITHUB_TOKEN sitting in the environment must
27
+ * never make release notes *worse* than having no token at all — public-repo
28
+ * requests that used to succeed anonymously keep succeeding.
29
+ */
30
+ async function fetchGitHubApi(url, signal) {
31
+ const headers = githubApiHeaders();
32
+ const response = await fetch(url, { method: 'GET', headers, signal });
33
+ if (response.status === 401 && headers.authorization) {
34
+ const { authorization: _rejected, ...anonymousHeaders } = headers;
35
+ return fetch(url, { method: 'GET', headers: anonymousHeaders, signal });
36
+ }
37
+ return response;
38
+ }
7
39
  class GitHubClient {
8
40
  releasesCache = new Map();
9
41
  rawChangelogCache = new Map();
@@ -16,14 +48,7 @@ class GitHubClient {
16
48
  if (!repo)
17
49
  return null;
18
50
  try {
19
- const response = await fetch(`https://api.github.com/repos/${repo.owner}/${repo.repo}/releases/tags/${tag}`, {
20
- method: 'GET',
21
- headers: {
22
- accept: 'application/vnd.github.v3+json',
23
- 'user-agent': `${config_1.PACKAGE_NAME}-cli`,
24
- },
25
- signal,
26
- });
51
+ const response = await fetchGitHubApi(`https://api.github.com/repos/${repo.owner}/${repo.repo}/releases/tags/${tag}`, signal);
27
52
  if (!response.ok)
28
53
  return null;
29
54
  const data = (await response.json());
@@ -61,20 +86,14 @@ class GitHubClient {
61
86
  if (!repo)
62
87
  return null;
63
88
  const cacheKey = `${repo.owner}/${repo.repo}`;
64
- if (this.releasesCache.has(cacheKey)) {
65
- return this.releasesCache.get(cacheKey);
89
+ const cached = this.releasesCache.get(cacheKey);
90
+ if (cached !== undefined) {
91
+ return cached;
66
92
  }
67
93
  const releases = [];
68
94
  for (let page = 1; page <= GITHUB_RELEASES_PAGE_LIMIT; page += 1) {
69
95
  try {
70
- const response = await fetch(`https://api.github.com/repos/${repo.owner}/${repo.repo}/releases?per_page=100&page=${page}`, {
71
- method: 'GET',
72
- headers: {
73
- accept: 'application/vnd.github.v3+json',
74
- 'user-agent': `${config_1.PACKAGE_NAME}-cli`,
75
- },
76
- signal,
77
- });
96
+ const response = await fetchGitHubApi(`https://api.github.com/repos/${repo.owner}/${repo.repo}/releases?per_page=100&page=${page}`, signal);
78
97
  if (!response.ok)
79
98
  break;
80
99
  const pageReleases = (await response.json());
@@ -100,8 +119,9 @@ class GitHubClient {
100
119
  if (!repo)
101
120
  return null;
102
121
  const cacheKey = `${repo.owner}/${repo.repo}`;
103
- if (this.rawChangelogCache.has(cacheKey)) {
104
- return this.rawChangelogCache.get(cacheKey);
122
+ const cached = this.rawChangelogCache.get(cacheKey);
123
+ if (cached !== undefined) {
124
+ return cached;
105
125
  }
106
126
  const branches = ['main', 'master'];
107
127
  const filenames = ['CHANGELOG.md', 'CHANGES.md', 'HISTORY.md'];
@@ -1,14 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NpmRegistryClient = void 0;
4
- const constants_1 = require("../../../config/constants");
4
+ const constants_1 = require("../../../shared/config/constants");
5
+ const registry_config_1 = require("../../../shared/registry/registry-config");
6
+ const PUBLIC_REGISTRY_ORIGIN = new URL(constants_1.NPM_REGISTRY_URL).origin;
5
7
  class NpmRegistryClient {
8
+ resolveRegistryTarget;
9
+ constructor(resolveRegistryTarget = registry_config_1.registryTargetFor) {
10
+ this.resolveRegistryTarget = resolveRegistryTarget;
11
+ }
6
12
  async fetchPackageManifest(packageName, version, signal) {
7
13
  try {
8
- const response = await fetch(`${constants_1.NPM_REGISTRY_URL}/${encodeURIComponent(packageName)}/${encodeURIComponent(version)}`, {
14
+ const target = this.resolveRegistryTarget(packageName);
15
+ const response = await fetch(`${target.origin}${target.pathPrefix}/${encodeURIComponent(packageName)}/${encodeURIComponent(version)}`, {
9
16
  method: 'GET',
10
17
  headers: {
11
18
  accept: 'application/json',
19
+ ...(target.authHeader ? { authorization: target.authHeader } : {}),
12
20
  },
13
21
  signal,
14
22
  });
@@ -25,6 +33,12 @@ class NpmRegistryClient {
25
33
  }
26
34
  }
27
35
  async fetchDownloadStats(packageName, signal) {
36
+ // Download counts only exist for the public registry. Skip the call for
37
+ // packages that resolve elsewhere — no stats there, and private package
38
+ // names should not be sent to api.npmjs.org.
39
+ if (this.resolveRegistryTarget(packageName).origin !== PUBLIC_REGISTRY_ORIGIN) {
40
+ return null;
41
+ }
28
42
  try {
29
43
  const response = await fetch(`https://api.npmjs.org/downloads/point/last-week/${encodeURIComponent(packageName)}`, {
30
44
  method: 'GET',
@@ -14,6 +14,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./types/changelog.types"), exports);
18
17
  __exportStar(require("./services/changelog-service"), exports);
18
+ __exportStar(require("./types"), exports);
19
19
  //# sourceMappingURL=index.js.map
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PackageMetadataService = void 0;
4
+ const inflight_1 = require("../../../shared/http/inflight");
4
5
  const npm_registry_client_1 = require("../clients/npm-registry-client");
5
6
  const package_metadata_1 = require("../parsers/package-metadata");
6
- const inflight_1 = require("../../../services/http/inflight");
7
7
  class PackageMetadataService {
8
8
  npmRegistryClient;
9
9
  cache = new Map();
@@ -16,7 +16,11 @@ class PackageMetadataService {
16
16
  this.inFlight.clear();
17
17
  }
18
18
  getCached(packageName, version) {
19
- for (const key of [this.getCacheKey(packageName, version), this.getCacheKey(packageName), packageName]) {
19
+ for (const key of [
20
+ this.getCacheKey(packageName, version),
21
+ this.getCacheKey(packageName),
22
+ packageName,
23
+ ]) {
20
24
  if (this.cache.has(key)) {
21
25
  return this.cache.get(key) ?? null;
22
26
  }
@@ -39,7 +39,6 @@ const github_client_1 = require("../clients/github-client");
39
39
  const changelog_parser_1 = require("../parsers/changelog-parser");
40
40
  const github_release_html_parser_1 = require("../parsers/github-release-html-parser");
41
41
  const RELEASE_NOTES_FETCH_TIMEOUT_MS = 5000;
42
- const PREFER_GITHUB_RELEASE_PAGE = true;
43
42
  class ReleaseNotesService {
44
43
  metadataService;
45
44
  githubClient;
@@ -56,8 +55,9 @@ class ReleaseNotesService {
56
55
  }
57
56
  async fetchReleaseNotesForVersion(packageName, version, signal) {
58
57
  const cacheKey = `release-notes:${packageName}@${version}`;
59
- if (this.releaseNotesCache.has(cacheKey)) {
60
- return this.releaseNotesCache.get(cacheKey);
58
+ const cached = this.releaseNotesCache.get(cacheKey);
59
+ if (cached !== undefined) {
60
+ return cached;
61
61
  }
62
62
  const inFlight = this.releaseNotesInFlight.get(cacheKey);
63
63
  if (inFlight) {
@@ -91,15 +91,12 @@ class ReleaseNotesService {
91
91
  return null;
92
92
  }
93
93
  getGitHubSources(repoUrl, version, signal) {
94
- const directReleaseSources = PREFER_GITHUB_RELEASE_PAGE
95
- ? [
96
- () => this.fetchGitHubReleasePageNotes(repoUrl, version, signal),
97
- () => this.fetchGitHubReleaseNotes(repoUrl, version, signal),
98
- ]
99
- : [
100
- () => this.fetchGitHubReleaseNotes(repoUrl, version, signal),
101
- () => this.fetchGitHubReleasePageNotes(repoUrl, version, signal),
102
- ];
94
+ // Scraped release page first (richer content than the API body), then the
95
+ // release API by tag.
96
+ const directReleaseSources = [
97
+ () => this.fetchGitHubReleasePageNotes(repoUrl, version, signal),
98
+ () => this.fetchGitHubReleaseNotes(repoUrl, version, signal),
99
+ ];
103
100
  return [
104
101
  ...directReleaseSources,
105
102
  () => this.fetchGitHubReleaseListNotes(repoUrl, version, signal),
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -14,8 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./types/debug.types"), exports);
18
- __exportStar(require("./services/performance-tracker"), exports);
19
- __exportStar(require("./services/perf-logger"), exports);
20
- __exportStar(require("./renderer/performance-modal"), exports);
17
+ __exportStar(require("./perf-logger"), exports);
18
+ __exportStar(require("./performance-tracker"), exports);
19
+ __exportStar(require("./types"), exports);
21
20
  //# sourceMappingURL=index.js.map
@@ -4,9 +4,9 @@ exports.isPerfLoggingEnabled = isPerfLoggingEnabled;
4
4
  exports.perfEnv = perfEnv;
5
5
  exports.getPerfDir = getPerfDir;
6
6
  exports.writePerfLog = writePerfLog;
7
- const fs_1 = require("fs");
8
- const path_1 = require("path");
9
- const adaptive_controller_1 = require("../../../services/http/adaptive-controller");
7
+ const node_fs_1 = require("node:fs");
8
+ const node_path_1 = require("node:path");
9
+ const adaptive_controller_1 = require("../../shared/http/adaptive-controller");
10
10
  /**
11
11
  * Performance debug logger.
12
12
  *
@@ -27,7 +27,7 @@ const adaptive_controller_1 = require("../../../services/http/adaptive-controlle
27
27
  const PERF_DIR_NAME = '.inup-perf';
28
28
  /** Filesystem-safe slug of a project name for use in filenames. */
29
29
  function projectSlug(cwd) {
30
- const name = (0, path_1.basename)((0, path_1.resolve)(cwd)) || 'root';
30
+ const name = (0, node_path_1.basename)((0, node_path_1.resolve)(cwd)) || 'root';
31
31
  return name.replace(/[^a-zA-Z0-9._-]/g, '-').slice(0, 40);
32
32
  }
33
33
  function isPerfLoggingEnabled() {
@@ -53,12 +53,12 @@ function perfEnv() {
53
53
  function getPerfDir(cwd = process.cwd()) {
54
54
  const override = process.env.INUP_PERF_DIR;
55
55
  const dir = override
56
- ? (0, path_1.isAbsolute)(override)
56
+ ? (0, node_path_1.isAbsolute)(override)
57
57
  ? override
58
- : (0, path_1.resolve)(cwd, override)
59
- : (0, path_1.join)(cwd, PERF_DIR_NAME);
60
- if (!(0, fs_1.existsSync)(dir)) {
61
- (0, fs_1.mkdirSync)(dir, { recursive: true });
58
+ : (0, node_path_1.resolve)(cwd, override)
59
+ : (0, node_path_1.join)(cwd, PERF_DIR_NAME);
60
+ if (!(0, node_fs_1.existsSync)(dir)) {
61
+ (0, node_fs_1.mkdirSync)(dir, { recursive: true });
62
62
  }
63
63
  return dir;
64
64
  }
@@ -92,10 +92,10 @@ function writePerfLog(config, snapshot) {
92
92
  // Project name in the filename keeps multi-project runs distinct when many
93
93
  // collect into one centralized INUP_PERF_DIR.
94
94
  const fileName = `run-${fileStamp(now)}-${projectSlug(config.cwd)}-${adaptiveTag}-${modeTag}.json`;
95
- const filePath = (0, path_1.join)(dir, fileName);
96
- (0, fs_1.writeFileSync)(filePath, JSON.stringify(record, null, 2));
95
+ const filePath = (0, node_path_1.join)(dir, fileName);
96
+ (0, node_fs_1.writeFileSync)(filePath, JSON.stringify(record, null, 2));
97
97
  // Maintain a stable pointer to the most recent run for quick reads.
98
- (0, fs_1.writeFileSync)((0, path_1.join)(dir, 'latest.json'), JSON.stringify(record, null, 2));
98
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(dir, 'latest.json'), JSON.stringify(record, null, 2));
99
99
  // And a cheap one-line-per-run index for fast scanning.
100
100
  appendPerfIndex(dir, record);
101
101
  if (process.env.INUP_DEBUG === '1') {
@@ -111,7 +111,7 @@ function writePerfLog(config, snapshot) {
111
111
  /** Append a single line to a NDJSON index for ultra-cheap scanning, best-effort. */
112
112
  function appendPerfIndex(dir, record) {
113
113
  try {
114
- const line = JSON.stringify({
114
+ const line = `${JSON.stringify({
115
115
  timestamp: record.timestamp,
116
116
  wallMs: record.wallMs,
117
117
  adaptive: record.config.adaptive,
@@ -119,8 +119,8 @@ function appendPerfIndex(dir, record) {
119
119
  uniquePackages: record.snapshot.counts.uniquePackages,
120
120
  registryFetch: record.snapshot.phases.registryFetch,
121
121
  controlTicks: record.snapshot.controlTicks.length,
122
- }) + '\n';
123
- (0, fs_1.appendFileSync)((0, path_1.join)(dir, 'index.ndjson'), line);
122
+ })}\n`;
123
+ (0, node_fs_1.appendFileSync)((0, node_path_1.join)(dir, 'index.ndjson'), line);
124
124
  }
125
125
  catch {
126
126
  /* best-effort */
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -5,13 +5,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.HeadlessRunner = void 0;
7
7
  const chalk_1 = __importDefault(require("chalk"));
8
- const package_detector_1 = require("../../core/package-detector");
9
- const upgrader_1 = require("../../core/upgrader");
10
- const package_manager_detector_1 = require("../../services/package-manager-detector");
11
- const version_1 = require("../../ui/utils/version");
12
- const vulnerability_audit_1 = require("./vulnerability-audit");
13
- const report_1 = require("./report");
14
8
  const debug_1 = require("../../features/debug");
9
+ const package_manager_1 = require("../../shared/package-manager");
10
+ const versions_1 = require("../../shared/versions");
11
+ const audit_1 = require("../audit");
12
+ const upgrade_1 = require("../upgrade");
13
+ const report_1 = require("./report");
15
14
  /**
16
15
  * Non-interactive entry point. Resolves the outdated list without rendering the TUI, then either
17
16
  * emits a JSON report (--json) or a plain line-based report. With --check, sets a non-zero exit
@@ -26,7 +25,7 @@ class HeadlessRunner {
26
25
  options;
27
26
  constructor(options) {
28
27
  this.options = options;
29
- this.detector = new package_detector_1.PackageDetector(options);
28
+ this.detector = new upgrade_1.PackageDetector(options);
30
29
  }
31
30
  async run(options) {
32
31
  try {
@@ -52,7 +51,7 @@ class HeadlessRunner {
52
51
  }
53
52
  // Audit the current versions (one bulk request, best-effort) and cross-reference each
54
53
  // advisory against the upgrade targets, so the report says whether upgrading *fixes* it.
55
- const vulnerabilities = await (0, vulnerability_audit_1.auditVulnerabilities)(outdated);
54
+ const vulnerabilities = await (0, audit_1.auditVulnerabilities)(outdated);
56
55
  // Build the report from the *pre-apply* outdated set: it describes what this run addressed.
57
56
  const report = (0, report_1.buildHeadlessReport)(packages, outdated, vulnerabilities);
58
57
  // --apply writes the bumps + lockfile. The scan above already honored .inuprc
@@ -89,48 +88,62 @@ class HeadlessRunner {
89
88
  const packageManager = this.resolvePackageManager();
90
89
  // With --json, run the upgrader quietly: its own progress + the install child's stdout go to
91
90
  // stderr, leaving stdout for the JSON document only.
92
- const upgrader = new upgrader_1.PackageUpgrader(packageManager, { quiet: json });
91
+ const upgrader = new upgrade_1.PackageUpgrader(packageManager, { quiet: json });
93
92
  await upgrader.upgradePackages(choices, outdated);
94
93
  }
95
94
  /**
96
95
  * Build `PackageUpgradeChoice[]` from the outdated set per the version policy. Mirrors
97
96
  * `createUpgradeChoices` in the TUI: preserves the original range prefix (^/~) unless --save-exact.
98
97
  *
99
- * - minor/patch: take the in-range target (`rangeVersion`); skip packages whose only update is a
98
+ * - minor: take the in-range target (`rangeVersion`); skip packages whose only update is a
100
99
  * major (no in-range bump). Uses upgradeType 'range'.
100
+ * - patch: take the highest patch in the current major.minor line; skip packages whose only
101
+ * update crosses a minor (or major) boundary. Uses upgradeType 'range'.
101
102
  * - latest: take `latestVersion`; uses upgradeType 'latest' (majors included).
102
103
  */
103
104
  buildChoices(outdated, target) {
104
105
  const saveExact = this.options?.saveExact ?? false;
105
106
  const choices = [];
106
107
  for (const pkg of outdated) {
107
- const useLatest = target === 'latest';
108
- // minor/patch only act on packages with an in-range bump; major-only updates are skipped.
109
- if (!useLatest && !pkg.hasRangeUpdate)
110
- continue;
111
- const targetVersion = useLatest ? pkg.latestVersion : pkg.rangeVersion;
108
+ const targetVersion = this.resolveTargetVersion(pkg, target);
112
109
  if (!targetVersion)
113
110
  continue;
114
111
  const targetVersionWithPrefix = saveExact
115
112
  ? targetVersion
116
- : (0, version_1.applyVersionPrefix)(pkg.currentVersion, targetVersion);
113
+ : (0, versions_1.applyVersionPrefix)(pkg.currentVersion, targetVersion);
117
114
  choices.push({
118
115
  name: pkg.name,
119
116
  packageJsonPath: pkg.packageJsonPath,
120
117
  dependencyType: pkg.type,
121
- upgradeType: useLatest ? 'latest' : 'range',
118
+ upgradeType: target === 'latest' ? 'latest' : 'range',
122
119
  targetVersion: targetVersionWithPrefix,
123
120
  currentVersionSpecifier: pkg.currentVersion,
121
+ catalog: pkg.catalog,
124
122
  });
125
123
  }
126
124
  return choices;
127
125
  }
126
+ /** Resolve the version a package should be bumped to under the given policy, or null to skip. */
127
+ resolveTargetVersion(pkg, target) {
128
+ if (target === 'latest') {
129
+ return pkg.latestVersion || null;
130
+ }
131
+ if (target === 'patch') {
132
+ // Strictly patch-level: computed from the full version list, not `rangeVersion` (which may
133
+ // be a minor bump). Null when the only updates cross a minor boundary.
134
+ return (0, versions_1.findHighestPatchVersion)(pkg.currentVersion, pkg.allVersions ?? []);
135
+ }
136
+ // minor: in-range bump only; major-only updates are skipped.
137
+ if (!pkg.hasRangeUpdate)
138
+ return null;
139
+ return pkg.rangeVersion || null;
140
+ }
128
141
  /** Resolve the package manager the same way the interactive runner does. */
129
142
  resolvePackageManager() {
130
143
  const cwd = this.options?.cwd || process.cwd();
131
144
  return this.options?.packageManager
132
- ? package_manager_detector_1.PackageManagerDetector.getInfo(this.options.packageManager)
133
- : package_manager_detector_1.PackageManagerDetector.detect(cwd);
145
+ ? package_manager_1.PackageManagerDetector.getInfo(this.options.packageManager)
146
+ : package_manager_1.PackageManagerDetector.detect(cwd);
134
147
  }
135
148
  }
136
149
  exports.HeadlessRunner = HeadlessRunner;
@@ -14,14 +14,11 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.renderPlainReport = exports.buildHeadlessReport = exports.upgradeClears = exports.auditVulnerabilities = exports.HeadlessRunner = void 0;
18
- __exportStar(require("./types"), exports);
17
+ exports.renderPlainReport = exports.buildHeadlessReport = exports.HeadlessRunner = void 0;
19
18
  var headless_runner_1 = require("./headless-runner");
20
19
  Object.defineProperty(exports, "HeadlessRunner", { enumerable: true, get: function () { return headless_runner_1.HeadlessRunner; } });
21
- var vulnerability_audit_1 = require("./vulnerability-audit");
22
- Object.defineProperty(exports, "auditVulnerabilities", { enumerable: true, get: function () { return vulnerability_audit_1.auditVulnerabilities; } });
23
- Object.defineProperty(exports, "upgradeClears", { enumerable: true, get: function () { return vulnerability_audit_1.upgradeClears; } });
24
20
  var report_1 = require("./report");
25
21
  Object.defineProperty(exports, "buildHeadlessReport", { enumerable: true, get: function () { return report_1.buildHeadlessReport; } });
26
22
  Object.defineProperty(exports, "renderPlainReport", { enumerable: true, get: function () { return report_1.renderPlainReport; } });
23
+ __exportStar(require("./types"), exports);
27
24
  //# sourceMappingURL=index.js.map
@@ -23,6 +23,8 @@ function buildHeadlessReport(all, outdated, vulnerabilities) {
23
23
  packageJsonPath: pkg.packageJsonPath,
24
24
  hasMajorUpdate: pkg.hasMajorUpdate,
25
25
  };
26
+ if (pkg.catalog)
27
+ entry.catalog = pkg.catalog;
26
28
  if (pkg.deprecated)
27
29
  entry.deprecated = pkg.deprecated;
28
30
  if (pkg.enginesNode)
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PackageInfoModalController = void 0;
4
+ var package_info_modal_controller_1 = require("./package-info-modal-controller");
5
+ Object.defineProperty(exports, "PackageInfoModalController", { enumerable: true, get: function () { return package_info_modal_controller_1.PackageInfoModalController; } });
6
+ //# sourceMappingURL=index.js.map
@@ -35,7 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.PackageInfoModalController = void 0;
37
37
  const semver = __importStar(require("semver"));
38
- const services_1 = require("../../services");
38
+ const changelog_1 = require("../../changelog");
39
39
  const RELEASE_NOTES_LOAD_DEBOUNCE_MS = 120;
40
40
  class PackageInfoModalController {
41
41
  abortController = null;
@@ -62,7 +62,7 @@ class PackageInfoModalController {
62
62
  this.cancel();
63
63
  const controller = new AbortController();
64
64
  this.abortController = controller;
65
- const metadata = await services_1.changelogFetcher.fetchPackageMetadata(state.name, state.latestVersion, controller.signal);
65
+ const metadata = await changelog_1.changelogFetcher.fetchPackageMetadata(state.name, state.latestVersion, controller.signal);
66
66
  if (!metadata) {
67
67
  return null;
68
68
  }
@@ -142,7 +142,7 @@ class PackageInfoModalController {
142
142
  state.releaseNotesLoadingVersion = version;
143
143
  onLoaded(); // Re-render to show loading indicator
144
144
  try {
145
- const notes = await services_1.changelogFetcher.fetchReleaseNotesForVersion(state.name, version, this.abortController?.signal);
145
+ const notes = await changelog_1.changelogFetcher.fetchReleaseNotesForVersion(state.name, version, this.abortController?.signal);
146
146
  loadedNotes.set(version, notes);
147
147
  return true;
148
148
  }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StateManager = exports.selectionKey = exports.runInteractiveSession = exports.createUpgradeChoices = exports.createSelectionStates = exports.createPendingSelectionStates = exports.UIRenderer = exports.renderReadmeKeyTable = exports.InputHandler = exports.ConfirmationInputHandler = exports.PackageInfoModalController = void 0;
4
+ var controllers_1 = require("./controllers");
5
+ Object.defineProperty(exports, "PackageInfoModalController", { enumerable: true, get: function () { return controllers_1.PackageInfoModalController; } });
6
+ var input_handler_1 = require("./input-handler");
7
+ Object.defineProperty(exports, "ConfirmationInputHandler", { enumerable: true, get: function () { return input_handler_1.ConfirmationInputHandler; } });
8
+ Object.defineProperty(exports, "InputHandler", { enumerable: true, get: function () { return input_handler_1.InputHandler; } });
9
+ var keymap_1 = require("./keymap");
10
+ Object.defineProperty(exports, "renderReadmeKeyTable", { enumerable: true, get: function () { return keymap_1.renderReadmeKeyTable; } });
11
+ var renderer_1 = require("./renderer");
12
+ Object.defineProperty(exports, "UIRenderer", { enumerable: true, get: function () { return renderer_1.UIRenderer; } });
13
+ var session_1 = require("./session");
14
+ Object.defineProperty(exports, "createPendingSelectionStates", { enumerable: true, get: function () { return session_1.createPendingSelectionStates; } });
15
+ Object.defineProperty(exports, "createSelectionStates", { enumerable: true, get: function () { return session_1.createSelectionStates; } });
16
+ Object.defineProperty(exports, "createUpgradeChoices", { enumerable: true, get: function () { return session_1.createUpgradeChoices; } });
17
+ Object.defineProperty(exports, "runInteractiveSession", { enumerable: true, get: function () { return session_1.runInteractiveSession; } });
18
+ Object.defineProperty(exports, "selectionKey", { enumerable: true, get: function () { return session_1.selectionKey; } });
19
+ var state_1 = require("./state");
20
+ Object.defineProperty(exports, "StateManager", { enumerable: true, get: function () { return state_1.StateManager; } });
21
+ //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ConfirmationInputHandler = exports.InputHandler = void 0;
4
- const utils_1 = require("./utils");
4
+ const terminal_1 = require("../../shared/terminal");
5
5
  const keymap_1 = require("./keymap");
6
6
  class InputHandler {
7
7
  stateManager;
@@ -21,7 +21,7 @@ class InputHandler {
21
21
  if (!key && !str) {
22
22
  return;
23
23
  }
24
- if (key && key.ctrl && key.name === 'c') {
24
+ if (key?.ctrl && key.name === 'c') {
25
25
  this.onCancel();
26
26
  process.exit(0);
27
27
  }
@@ -201,7 +201,7 @@ class InputHandler {
201
201
  }
202
202
  // Normal mode (not in filter mode). Keys resolve through the keymap so that
203
203
  // dispatch, the help overlay, the footer, and the README share one source.
204
- if (!key || !key.name) {
204
+ if (!key?.name) {
205
205
  return;
206
206
  }
207
207
  // Enter confirms the selection (guarding against an empty selection). It runs
@@ -235,7 +235,7 @@ class InputHandler {
235
235
  this.onAction({ type: 'resize', height });
236
236
  }
237
237
  cleanup() {
238
- utils_1.CursorUtils.cleanup();
238
+ terminal_1.CursorUtils.cleanup();
239
239
  }
240
240
  }
241
241
  exports.InputHandler = InputHandler;
@@ -249,7 +249,7 @@ class ConfirmationInputHandler {
249
249
  if (!key && !str) {
250
250
  return;
251
251
  }
252
- if (key && key.ctrl && key.name === 'c') {
252
+ if (key?.ctrl && key.name === 'c') {
253
253
  // onConfirm runs the normal cleanup path (cursor show, raw-mode off, listener
254
254
  // removal). The 'exit' listener registered by confirmUpgrade is a final backstop.
255
255
  this.onConfirm(false);
@@ -275,7 +275,7 @@ class ConfirmationInputHandler {
275
275
  }
276
276
  }
277
277
  cleanup() {
278
- utils_1.CursorUtils.cleanup();
278
+ terminal_1.CursorUtils.cleanup();
279
279
  }
280
280
  }
281
281
  exports.ConfirmationInputHandler = ConfirmationInputHandler;
@@ -14,9 +14,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./types"), exports);
18
17
  __exportStar(require("./layout"), exports);
19
18
  __exportStar(require("./package-info"), exports);
20
19
  __exportStar(require("./package-info-sections"), exports);
21
20
  __exportStar(require("./theme-selector"), exports);
21
+ __exportStar(require("./types"), exports);
22
22
  //# sourceMappingURL=index.js.map
@@ -11,12 +11,12 @@ exports.getModalSectionRowCount = getModalSectionRowCount;
11
11
  exports.getModalFrameHeight = getModalFrameHeight;
12
12
  exports.renderModalFrame = renderModalFrame;
13
13
  const chalk_1 = __importDefault(require("chalk"));
14
- const utils_1 = require("../utils");
14
+ const terminal_1 = require("../../../shared/terminal");
15
15
  function getModalWidth(terminalWidth, minWidth, maxWidth) {
16
16
  return Math.min(Math.max(minWidth, terminalWidth - 6), maxWidth);
17
17
  }
18
18
  function renderModalRow(padding, modalWidth, text) {
19
- const rowLength = (0, utils_1.getVisualLength)(text);
19
+ const rowLength = (0, terminal_1.getVisualLength)(text);
20
20
  const rowPadding = Math.max(0, modalWidth - 4 - rowLength);
21
21
  return (' '.repeat(padding) +
22
22
  chalk_1.default.gray('│') +
@@ -27,7 +27,7 @@ function renderModalRow(padding, modalWidth, text) {
27
27
  chalk_1.default.gray('│'));
28
28
  }
29
29
  function renderModalSeparator(padding, modalWidth) {
30
- return ' '.repeat(padding) + chalk_1.default.gray('├' + '─'.repeat(modalWidth - 2) + '┤');
30
+ return ' '.repeat(padding) + chalk_1.default.gray(`├${'─'.repeat(modalWidth - 2)}┤`);
31
31
  }
32
32
  function fitModalSections(sections, maxHeight, trimOrder) {
33
33
  const activeSections = sections.map((section) => ({ ...section, rows: [...section.rows] }));
@@ -69,7 +69,7 @@ function renderModalFrame(sections, options) {
69
69
  for (let i = 0; i < topPadding; i++) {
70
70
  lines.push('');
71
71
  }
72
- lines.push(' '.repeat(padding) + chalk_1.default.gray('╭' + '─'.repeat(modalWidth - 2) + '╮'));
72
+ lines.push(' '.repeat(padding) + chalk_1.default.gray(`╭${'─'.repeat(modalWidth - 2)}╮`));
73
73
  sections.forEach((section, index) => {
74
74
  if (index > 0) {
75
75
  lines.push(renderModalSeparator(padding, modalWidth));
@@ -78,7 +78,7 @@ function renderModalFrame(sections, options) {
78
78
  lines.push(renderModalRow(padding, modalWidth, row));
79
79
  });
80
80
  });
81
- lines.push(' '.repeat(padding) + chalk_1.default.gray('╰' + '─'.repeat(modalWidth - 2) + '╯'));
81
+ lines.push(' '.repeat(padding) + chalk_1.default.gray(`╰${'─'.repeat(modalWidth - 2)}╯`));
82
82
  return lines;
83
83
  }
84
84
  //# sourceMappingURL=layout.js.map
@@ -14,6 +14,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./package-list/rows"), exports);
18
- __exportStar(require("./package-list/interface"), exports);
19
- //# sourceMappingURL=package-list.js.map
17
+ __exportStar(require("./release-notes"), exports);
18
+ __exportStar(require("./sections"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -114,7 +114,7 @@ function buildReleaseNotesSections(state, modalWidth) {
114
114
  });
115
115
  return sections;
116
116
  }
117
- if (!loaded || !loaded.has(currentVersion)) {
117
+ if (!loaded?.has(currentVersion)) {
118
118
  sections.push({
119
119
  key: 'release-pending',
120
120
  rows: [chalk_1.default.gray(`Press ←/→ to load release notes for v${currentVersion}`)],