inup 1.4.12 → 1.5.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.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +39 -30
  3. package/dist/cli.js +29 -14
  4. package/dist/config/project-config.js +6 -0
  5. package/dist/core/package-detector.js +3 -2
  6. package/dist/core/upgrade-runner.js +6 -3
  7. package/dist/features/changelog/clients/github-client.js +134 -0
  8. package/dist/features/changelog/clients/npm-registry-client.js +53 -0
  9. package/dist/features/changelog/index.js +19 -0
  10. package/dist/features/changelog/parsers/changelog-parser.js +68 -0
  11. package/dist/features/changelog/parsers/github-release-html-parser.js +61 -0
  12. package/dist/features/changelog/parsers/package-metadata.js +34 -0
  13. package/dist/features/changelog/parsers/repository-ref.js +26 -0
  14. package/dist/features/changelog/services/changelog-service.js +30 -0
  15. package/dist/features/changelog/services/package-metadata-service.js +108 -0
  16. package/dist/features/changelog/services/release-notes-service.js +180 -0
  17. package/dist/features/changelog/types/changelog.types.js +3 -0
  18. package/dist/interactive-ui.js +242 -114
  19. package/dist/services/background-audit.js +60 -0
  20. package/dist/services/index.js +3 -1
  21. package/dist/services/vulnerability-checker.js +133 -0
  22. package/dist/ui/controllers/index.js +8 -0
  23. package/dist/ui/controllers/package-info-modal-controller.js +237 -0
  24. package/dist/ui/controllers/vulnerability-audit-controller.js +82 -0
  25. package/dist/ui/index.js +3 -0
  26. package/dist/ui/input-handler.js +40 -9
  27. package/dist/ui/modal/index.js +22 -0
  28. package/dist/ui/modal/layout.js +84 -0
  29. package/dist/ui/modal/package-info-sections.js +327 -0
  30. package/dist/ui/modal/package-info.js +147 -0
  31. package/dist/ui/modal/theme-selector.js +46 -0
  32. package/dist/ui/modal/types.js +3 -0
  33. package/dist/ui/presenters/index.js +11 -0
  34. package/dist/ui/presenters/vulnerability.js +76 -0
  35. package/dist/ui/renderer/index.js +9 -11
  36. package/dist/ui/renderer/package-list.js +135 -62
  37. package/dist/ui/state/filter-manager.js +17 -2
  38. package/dist/ui/state/modal-manager.js +48 -6
  39. package/dist/ui/state/state-manager.js +42 -7
  40. package/dist/ui/utils/cursor.js +18 -0
  41. package/dist/ui/utils/index.js +8 -1
  42. package/dist/ui/utils/terminal-input.js +125 -0
  43. package/dist/ui/utils/text.js +75 -0
  44. package/dist/ui/utils/version.js +3 -2
  45. package/dist/utils/git.js +33 -0
  46. package/dist/utils/index.js +1 -0
  47. package/package.json +22 -19
  48. package/dist/services/changelog-fetcher.js +0 -215
  49. package/dist/ui/renderer/modal.js +0 -190
  50. package/dist/ui/renderer/theme-selector.js +0 -83
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Donfear
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,49 +1,45 @@
1
- # 🚀 inup
1
+ # inup — Interactive Dependency Upgrader
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/inup?logo=npm&logoColor=%23CB3837&style=for-the-badge&color=crimson)](https://www.npmjs.com/package/inup)
4
4
  [![Downloads](https://img.shields.io/npm/dm/inup?style=for-the-badge&color=646CFF&logoColor=white)](https://www.npmjs.com/package/inup)
5
5
  [![Total downloads](https://img.shields.io/npm/dt/inup?style=for-the-badge&color=informational)](https://www.npmjs.com/package/inup)
6
+ [![CI](https://img.shields.io/github/actions/workflow/status/donfear/inup/ci.yml?branch=main&style=for-the-badge&label=CI)](https://github.com/donfear/inup/actions/workflows/ci.yml)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=for-the-badge)](https://github.com/donfear/inup/blob/main/LICENSE)
6
8
 
7
- Upgrade your dependencies interactively. Works with npm, yarn, pnpm, and bun.
9
+ Interactively upgrade outdated dependencies across npm, yarn, pnpm, and bun. Auto-detects your package manager, works in monorepos and workspaces, and requires zero configuration.
8
10
 
9
11
  ![Interactive Upgrade Demo](docs/demo/interactive-upgrade.gif)
10
12
 
11
- ## 🚀 Usage
13
+ ## Quick Start
12
14
 
13
15
  ```bash
14
16
  npx inup
15
17
  ```
16
18
 
17
- Or install globally:
19
+ Or install globally with your preferred package manager:
18
20
 
19
21
  ```bash
20
22
  npm install -g inup
23
+ pnpm add -g inup
24
+ yarn global add inup
25
+ bun add -g inup
21
26
  ```
22
27
 
23
- That's it. The tool scans your project, finds outdated packages, and lets you pick what to upgrade.
28
+ Run `inup` in any project it scans for outdated packages and lets you pick what to upgrade.
24
29
 
25
- ## 💡 Why inup?
30
+ ## Why inup?
26
31
 
27
- - **Inclusive by Default**: We load Dev, Peer, and Optional dependencies automatically. No more restarting the tool because you forgot a `--peer` flag.
28
- - **Live Toggles**: Toggle dependency types (`d`, `p`, `o`) on the fly without exiting.
29
- - **Zero Config**: Auto-detects your package manager.
30
- - **Monorepo Ready**: Seamlessly handles workspaces.
31
- - **Modern UX**: Search with `/`, view package details with `i`, and swap themes with `t`.
32
+ - **All Dependencies at Once** Dev, peer, and optional dependencies load automatically. No more re-running with `--peer` or `--dev` flags.
33
+ - **Live Toggles** Filter dependency types (`d`, `p`, `o`) on the fly without restarting.
34
+ - **Zero Config** Auto-detects npm, yarn, pnpm, or bun from your lockfile.
35
+ - **Monorepo Ready** Discovers and upgrades across workspaces seamlessly.
36
+ - **Vulnerability Audit** Flags known security vulnerabilities right in the package list so you know what's risky before upgrading.
37
+ - **Changelog Viewer** — Read release notes and changelogs inline without leaving the terminal.
38
+ - **Built-in Search** — Press `/` to filter packages instantly.
39
+ - **Package Details** — Press `i` to view package info, download stats, and more.
40
+ - **Themes** — Press `t` to switch between color themes.
32
41
 
33
- ## ⌨️ Keyboard Shortcuts
34
-
35
- - `↑/↓` - Navigate packages
36
- - `←/→` - Select version (current, patch, minor, major)
37
- - `Space` - Toggle selection
38
- - `m` - Select all minor updates
39
- - `l` - Select all latest updates
40
- - `u` - Unselect all
41
- - `/` - Search packages
42
- - `t` - Change theme
43
- - `i` - View package info
44
- - `Enter` - Confirm and upgrade
45
-
46
- ## ⚙️ Options
42
+ ## Options
47
43
 
48
44
  ```bash
49
45
  inup [options]
@@ -56,12 +52,25 @@ inup [options]
56
52
  --debug Write verbose debug logs
57
53
  ```
58
54
 
59
- ## 🔒 Privacy
55
+ ## Keyboard Shortcuts
56
+
57
+ | Key | Action |
58
+ |-----|--------|
59
+ | `↑` `↓` | Navigate packages |
60
+ | `←` `→` | Select version (current, patch, minor, major) |
61
+ | `Space` | Toggle selection |
62
+ | `m` | Select all minor updates |
63
+ | `l` | Select all latest updates |
64
+ | `u` | Unselect all |
65
+ | `/` | Search packages |
66
+ | `i` | View package info |
67
+ | `t` | Change theme |
68
+ | `Enter` | Confirm and upgrade |
60
69
 
61
- We don't track anything. Ever.
70
+ ## Privacy
62
71
 
63
- Version checks and package metadata are fetched from the npm registry. When needed for immutable exact-version manifests, inup may also fetch a pinned `package.json` from jsDelivr. Weekly download counts come from the npm downloads API.
72
+ No tracking, no telemetry, no data collection. Package metadata is fetched directly from the npm registry. Download counts come from the npm downloads API. When needed for exact-version manifests, inup may fetch a pinned `package.json` from jsDelivr.
64
73
 
65
- ## 📄 License
74
+ ## License
66
75
 
67
- MIT
76
+ [MIT](LICENSE)
package/dist/cli.js CHANGED
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
5
5
  };
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.runCli = runCli;
7
8
  const commander_1 = require("commander");
8
9
  const chalk_1 = __importDefault(require("chalk"));
9
10
  const fs_1 = require("fs");
@@ -12,24 +13,23 @@ const index_1 = require("./index");
12
13
  const services_1 = require("./services");
13
14
  const config_1 = require("./config");
14
15
  const utils_1 = require("./utils");
16
+ const git_1 = require("./utils/git");
17
+ const terminal_input_1 = require("./ui/utils/terminal-input");
15
18
  const packageJson = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, '../package.json'), 'utf-8'));
16
19
  const program = new commander_1.Command();
17
- program
18
- .name('inup')
19
- .description('Interactive upgrade tool for package managers. Auto-detects and works with npm, yarn, pnpm, and bun.')
20
- .version(packageJson.version)
21
- .option('-d, --dir <directory>', 'specify directory to run in', process.cwd())
22
- .option('-e, --exclude <patterns>', 'exclude paths matching regex patterns (comma-separated)', '')
23
- .option('-i, --ignore <packages>', 'ignore packages (comma-separated, supports glob patterns like @babel/*)')
24
- .option('--max-depth <number>', 'maximum directory depth for package.json discovery', '10')
25
- .option('--package-manager <name>', 'manually specify package manager (npm, yarn, pnpm, bun)')
26
- .option('--debug', 'write verbose debug log to /tmp/inup-debug-YYYY-MM-DD.log')
27
- .action(async (options) => {
28
- console.log(chalk_1.default.bold.blue(`🚀 `) + chalk_1.default.bold.red(`i`) + chalk_1.default.bold.yellow(`n`) + chalk_1.default.bold.blue(`u`) + chalk_1.default.bold.magenta(`p`) + `\n`);
20
+ async function runCli(options) {
29
21
  const cwd = (0, path_1.resolve)(options.dir);
30
22
  if (options.debug || process.env.INUP_DEBUG === '1') {
31
23
  (0, utils_1.enableDebugLogging)();
32
24
  }
25
+ const gitState = (0, git_1.getGitWorkingTreeState)(cwd);
26
+ if (gitState.isRepo && gitState.isDirty) {
27
+ const shouldProceed = await terminal_input_1.TerminalInput.promptForImmediateConfirmation(`${chalk_1.default.yellow('Warning:')} dirty working tree. Proceed anyway? ${chalk_1.default.dim('[y/N]')} `, false);
28
+ if (!shouldProceed) {
29
+ console.log(chalk_1.default.yellow('Upgrade cancelled.'));
30
+ return;
31
+ }
32
+ }
33
33
  // Load project config from .inuprc
34
34
  const projectConfig = (0, config_1.loadProjectConfig)(cwd);
35
35
  // Merge CLI exclude patterns with config
@@ -73,6 +73,8 @@ program
73
73
  maxDepth,
74
74
  ignorePackages,
75
75
  packageManager,
76
+ showPeerDependencyVulnerabilities: projectConfig.showPeerDependencyVulnerabilities ?? false,
77
+ showOptionalDependencyVulnerabilities: projectConfig.showOptionalDependencyVulnerabilities ?? false,
76
78
  debug: options.debug || process.env.INUP_DEBUG === '1',
77
79
  });
78
80
  await upgrader.run();
@@ -98,7 +100,18 @@ program
98
100
  console.log(chalk_1.default.yellow('└' + '─'.repeat(78) + '┘'));
99
101
  console.log('');
100
102
  }
101
- });
103
+ }
104
+ program
105
+ .name('inup')
106
+ .description('Interactive upgrade tool for package managers. Auto-detects and works with npm, yarn, pnpm, and bun.')
107
+ .version(packageJson.version)
108
+ .option('-d, --dir <directory>', 'specify directory to run in', process.cwd())
109
+ .option('-e, --exclude <patterns>', 'exclude paths matching regex patterns (comma-separated)', '')
110
+ .option('-i, --ignore <packages>', 'ignore packages (comma-separated, supports glob patterns like @babel/*)')
111
+ .option('--max-depth <number>', 'maximum directory depth for package.json discovery', '10')
112
+ .option('--package-manager <name>', 'manually specify package manager (npm, yarn, pnpm, bun)')
113
+ .option('--debug', 'write verbose debug log to /tmp/inup-debug-YYYY-MM-DD.log')
114
+ .action(runCli);
102
115
  // Handle uncaught errors gracefully
103
116
  process.on('uncaughtException', (error) => {
104
117
  console.error(chalk_1.default.red('Uncaught Exception:'), error.message);
@@ -127,5 +140,7 @@ process.on('SIGTERM', () => {
127
140
  console.log(chalk_1.default.yellow('\n\nOperation cancelled.'));
128
141
  process.exit(0);
129
142
  });
130
- program.parse();
143
+ if (require.main === module) {
144
+ program.parse();
145
+ }
131
146
  //# sourceMappingURL=cli.js.map
@@ -49,6 +49,12 @@ function normalizeConfig(config) {
49
49
  normalized.exclude = config.exclude.filter((item) => typeof item === 'string');
50
50
  }
51
51
  }
52
+ if (typeof config.showPeerDependencyVulnerabilities === 'boolean') {
53
+ normalized.showPeerDependencyVulnerabilities = config.showPeerDependencyVulnerabilities;
54
+ }
55
+ if (typeof config.showOptionalDependencyVulnerabilities === 'boolean') {
56
+ normalized.showOptionalDependencyVulnerabilities = config.showOptionalDependencyVulnerabilities;
57
+ }
52
58
  return normalized;
53
59
  }
54
60
  /**
@@ -44,7 +44,7 @@ class PackageDetector {
44
44
  constructor(options) {
45
45
  this.packageJsonPath = null;
46
46
  this.packageJson = null;
47
- this.batchSizes = [10, 15, 20, 25];
47
+ this.batchSize = 25;
48
48
  this.batchConcurrency = 5;
49
49
  this.cwd = options?.cwd || process.cwd();
50
50
  this.excludePatterns = options?.excludePatterns || [];
@@ -115,7 +115,7 @@ class PackageDetector {
115
115
  },
116
116
  });
117
117
  }, prepared.currentVersions, {
118
- batchSizes: this.batchSizes,
118
+ batchSize: this.batchSize,
119
119
  concurrency: this.batchConcurrency,
120
120
  });
121
121
  utils_3.debugLog.perf('PackageDetector', `registry fetch (${resolved}/${prepared.uniquePackages.length} resolved)`, tFetch);
@@ -245,6 +245,7 @@ class PackageDetector {
245
245
  isOutdated,
246
246
  hasRangeUpdate,
247
247
  hasMajorUpdate,
248
+ allVersions,
248
249
  };
249
250
  }
250
251
  catch (error) {
@@ -9,6 +9,7 @@ const package_detector_1 = require("./package-detector");
9
9
  const interactive_ui_1 = require("../interactive-ui");
10
10
  const upgrader_1 = require("./upgrader");
11
11
  const package_manager_detector_1 = require("../services/package-manager-detector");
12
+ const utils_1 = require("../ui/utils");
12
13
  /**
13
14
  * Main orchestrator for the inup upgrade process
14
15
  */
@@ -24,7 +25,10 @@ class UpgradeRunner {
24
25
  this.packageManager = package_manager_detector_1.PackageManagerDetector.detect(cwd);
25
26
  }
26
27
  this.detector = new package_detector_1.PackageDetector(options);
27
- this.ui = new interactive_ui_1.InteractiveUI(this.packageManager);
28
+ this.ui = new interactive_ui_1.InteractiveUI(this.packageManager, {
29
+ showPeerDependencyVulnerabilities: options?.showPeerDependencyVulnerabilities ?? false,
30
+ showOptionalDependencyVulnerabilities: options?.showOptionalDependencyVulnerabilities ?? false,
31
+ });
28
32
  this.upgrader = new upgrader_1.PackageUpgrader(this.packageManager);
29
33
  }
30
34
  async run() {
@@ -114,8 +118,7 @@ class UpgradeRunner {
114
118
  shouldProceed = await this.ui.confirmUpgrade(selectedChoices);
115
119
  if (shouldProceed === null) {
116
120
  // User pressed N or ESC - go back to selection with current selections preserved
117
- console.clear();
118
- console.log(chalk_1.default.bold.blue('🚀 inup\n'));
121
+ utils_1.ConsoleUtils.clearProgress();
119
122
  selectedChoices = progress.isLoading
120
123
  ? await this.ui.selectPackagesToUpgradeProgressive(selectionStates, progress, (refresh) => {
121
124
  refreshUI = refresh;
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GitHubClient = void 0;
4
+ const repository_ref_1 = require("../parsers/repository-ref");
5
+ const GITHUB_RELEASES_PAGE_LIMIT = 3;
6
+ class GitHubClient {
7
+ constructor() {
8
+ this.releasesCache = new Map();
9
+ this.rawChangelogCache = new Map();
10
+ }
11
+ clearCache() {
12
+ this.releasesCache.clear();
13
+ this.rawChangelogCache.clear();
14
+ }
15
+ async fetchReleaseByTag(repoUrl, tag, signal) {
16
+ const repo = (0, repository_ref_1.parseGitHubRepo)(repoUrl);
17
+ if (!repo)
18
+ return null;
19
+ try {
20
+ const response = await fetch(`https://api.github.com/repos/${repo.owner}/${repo.repo}/releases/tags/${tag}`, {
21
+ method: 'GET',
22
+ headers: {
23
+ accept: 'application/vnd.github.v3+json',
24
+ 'user-agent': 'inup-cli',
25
+ },
26
+ signal,
27
+ });
28
+ if (!response.ok)
29
+ return null;
30
+ const data = (await response.json());
31
+ return data.body?.trim() ? data.body.trim() : null;
32
+ }
33
+ catch (error) {
34
+ if (error instanceof DOMException && error.name === 'AbortError') {
35
+ throw error;
36
+ }
37
+ return null;
38
+ }
39
+ }
40
+ async fetchReleasePageHtml(repoUrl, tag, signal) {
41
+ const repo = (0, repository_ref_1.parseGitHubRepo)(repoUrl);
42
+ if (!repo)
43
+ return null;
44
+ try {
45
+ const response = await fetch(`https://github.com/${repo.owner}/${repo.repo}/releases/tag/${tag}`, {
46
+ method: 'GET',
47
+ signal,
48
+ });
49
+ if (!response.ok)
50
+ return null;
51
+ return await response.text();
52
+ }
53
+ catch (error) {
54
+ if (error instanceof DOMException && error.name === 'AbortError') {
55
+ throw error;
56
+ }
57
+ return null;
58
+ }
59
+ }
60
+ async fetchReleases(repoUrl, signal) {
61
+ const repo = (0, repository_ref_1.parseGitHubRepo)(repoUrl);
62
+ if (!repo)
63
+ return null;
64
+ const cacheKey = `${repo.owner}/${repo.repo}`;
65
+ if (this.releasesCache.has(cacheKey)) {
66
+ return this.releasesCache.get(cacheKey);
67
+ }
68
+ const releases = [];
69
+ for (let page = 1; page <= GITHUB_RELEASES_PAGE_LIMIT; page += 1) {
70
+ try {
71
+ const response = await fetch(`https://api.github.com/repos/${repo.owner}/${repo.repo}/releases?per_page=100&page=${page}`, {
72
+ method: 'GET',
73
+ headers: {
74
+ accept: 'application/vnd.github.v3+json',
75
+ 'user-agent': 'inup-cli',
76
+ },
77
+ signal,
78
+ });
79
+ if (!response.ok)
80
+ break;
81
+ const pageReleases = (await response.json());
82
+ if (!Array.isArray(pageReleases) || pageReleases.length === 0)
83
+ break;
84
+ releases.push(...pageReleases);
85
+ if (pageReleases.length < 100)
86
+ break;
87
+ }
88
+ catch (error) {
89
+ if (error instanceof DOMException && error.name === 'AbortError') {
90
+ throw error;
91
+ }
92
+ break;
93
+ }
94
+ }
95
+ const result = releases.length > 0 ? releases : null;
96
+ this.releasesCache.set(cacheKey, result);
97
+ return result;
98
+ }
99
+ async fetchRawChangelog(repoUrl, signal) {
100
+ const repo = (0, repository_ref_1.parseGitHubRepo)(repoUrl);
101
+ if (!repo)
102
+ return null;
103
+ const cacheKey = `${repo.owner}/${repo.repo}`;
104
+ if (this.rawChangelogCache.has(cacheKey)) {
105
+ return this.rawChangelogCache.get(cacheKey);
106
+ }
107
+ const branches = ['main', 'master'];
108
+ const filenames = ['CHANGELOG.md', 'CHANGES.md', 'HISTORY.md'];
109
+ for (const branch of branches) {
110
+ for (const filename of filenames) {
111
+ try {
112
+ const response = await fetch(`https://raw.githubusercontent.com/${repo.owner}/${repo.repo}/${branch}/${filename}`, {
113
+ method: 'GET',
114
+ signal,
115
+ });
116
+ if (response.ok) {
117
+ const text = await response.text();
118
+ this.rawChangelogCache.set(cacheKey, text);
119
+ return text;
120
+ }
121
+ }
122
+ catch (error) {
123
+ if (error instanceof DOMException && error.name === 'AbortError') {
124
+ throw error;
125
+ }
126
+ }
127
+ }
128
+ }
129
+ this.rawChangelogCache.set(cacheKey, null);
130
+ return null;
131
+ }
132
+ }
133
+ exports.GitHubClient = GitHubClient;
134
+ //# sourceMappingURL=github-client.js.map
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NpmRegistryClient = void 0;
4
+ const constants_1 = require("../../../config/constants");
5
+ class NpmRegistryClient {
6
+ async fetchPackageManifest(packageName, version, signal) {
7
+ try {
8
+ const response = await fetch(`${constants_1.NPM_REGISTRY_URL}/${encodeURIComponent(packageName)}/${encodeURIComponent(version)}`, {
9
+ method: 'GET',
10
+ headers: {
11
+ accept: 'application/json',
12
+ },
13
+ signal,
14
+ });
15
+ if (!response.ok) {
16
+ return null;
17
+ }
18
+ return (await response.json());
19
+ }
20
+ catch (error) {
21
+ if (error instanceof DOMException && error.name === 'AbortError') {
22
+ throw error;
23
+ }
24
+ return null;
25
+ }
26
+ }
27
+ async fetchDownloadStats(packageName, signal) {
28
+ try {
29
+ const response = await fetch(`https://api.npmjs.org/downloads/point/last-week/${encodeURIComponent(packageName)}`, {
30
+ method: 'GET',
31
+ headers: {
32
+ accept: 'application/json',
33
+ },
34
+ signal,
35
+ });
36
+ if (!response.ok) {
37
+ return null;
38
+ }
39
+ const data = (await response.json());
40
+ return {
41
+ downloads: data.downloads || 0,
42
+ };
43
+ }
44
+ catch (error) {
45
+ if (error instanceof DOMException && error.name === 'AbortError') {
46
+ throw error;
47
+ }
48
+ return null;
49
+ }
50
+ }
51
+ }
52
+ exports.NpmRegistryClient = NpmRegistryClient;
53
+ //# sourceMappingURL=npm-registry-client.js.map
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./types/changelog.types"), exports);
18
+ __exportStar(require("./services/changelog-service"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.normalizeReleaseTag = normalizeReleaseTag;
37
+ exports.extractVersionSection = extractVersionSection;
38
+ const semver = __importStar(require("semver"));
39
+ function normalizeReleaseTag(tagName) {
40
+ if (!tagName)
41
+ return null;
42
+ const cleanedTag = semver.clean(tagName);
43
+ if (cleanedTag)
44
+ return cleanedTag;
45
+ const semverMatch = tagName.match(/\d+\.\d+\.\d+(?:-[0-9A-Za-z-.]+)?(?:\+[0-9A-Za-z-.]+)?/);
46
+ if (!semverMatch)
47
+ return null;
48
+ return semver.clean(semverMatch[0]);
49
+ }
50
+ function extractVersionSection(changelog, version) {
51
+ const escapedVersion = version.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
52
+ const sectionRegex = new RegExp(`^##\\s+\\[?v?${escapedVersion}\\]?[^\\n]*\\n`, 'm');
53
+ const match = sectionRegex.exec(changelog);
54
+ if (!match)
55
+ return null;
56
+ const startIndex = match.index + match[0].length;
57
+ const nextSectionMatch = /^## /m.exec(changelog.slice(startIndex));
58
+ const endIndex = nextSectionMatch ? startIndex + nextSectionMatch.index : changelog.length;
59
+ const section = changelog.slice(startIndex, endIndex).trim();
60
+ if (section.length === 0)
61
+ return null;
62
+ const lines = section.split('\n');
63
+ if (lines.length > 100) {
64
+ return `${lines.slice(0, 100).join('\n')}\n...`;
65
+ }
66
+ return section;
67
+ }
68
+ //# sourceMappingURL=changelog-parser.js.map
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractReleaseNotesFromHtml = extractReleaseNotesFromHtml;
4
+ function extractReleaseNotesFromHtml(html) {
5
+ const bodyContentIndex = html.indexOf('data-test-selector="body-content"');
6
+ if (bodyContentIndex === -1)
7
+ return null;
8
+ const markdownBodyIndex = html.indexOf('class="markdown-body', bodyContentIndex);
9
+ if (markdownBodyIndex === -1)
10
+ return null;
11
+ const contentStart = html.indexOf('>', markdownBodyIndex);
12
+ if (contentStart === -1)
13
+ return null;
14
+ let depth = 1;
15
+ let cursor = contentStart + 1;
16
+ while (depth > 0 && cursor < html.length) {
17
+ const nextOpen = html.indexOf('<div', cursor);
18
+ const nextClose = html.indexOf('</div>', cursor);
19
+ if (nextClose === -1)
20
+ return null;
21
+ if (nextOpen !== -1 && nextOpen < nextClose) {
22
+ depth += 1;
23
+ cursor = nextOpen + 4;
24
+ }
25
+ else {
26
+ depth -= 1;
27
+ cursor = nextClose + 6;
28
+ }
29
+ }
30
+ if (depth !== 0)
31
+ return null;
32
+ const normalized = html
33
+ .slice(contentStart + 1, cursor - 6)
34
+ .replace(/<svg[\s\S]*?<\/svg>/g, '')
35
+ .replace(/<h([1-6])[^>]*>/g, (_full, level) => `${'#'.repeat(Number(level))} `)
36
+ .replace(/<\/h[1-6]>/g, '\n\n')
37
+ .replace(/<li[^>]*>/g, '- ')
38
+ .replace(/<\/li>/g, '\n')
39
+ .replace(/<p[^>]*>/g, '')
40
+ .replace(/<\/p>/g, '\n\n')
41
+ .replace(/<br\s*\/?>/g, '\n')
42
+ .replace(/<a\b[^>]*>([\s\S]*?)<\/a>/g, '$1')
43
+ .replace(/<strong[^>]*>([\s\S]*?)<\/strong>/g, '**$1**')
44
+ .replace(/<code[^>]*>([\s\S]*?)<\/code>/g, '`$1`')
45
+ .replace(/<[^>]+>/g, '');
46
+ const decoded = normalized
47
+ .replace(/&amp;/g, '&')
48
+ .replace(/&lt;/g, '<')
49
+ .replace(/&gt;/g, '>')
50
+ .replace(/&quot;/g, '"')
51
+ .replace(/&#39;/g, "'")
52
+ .replace(/&nbsp;/g, ' ');
53
+ const cleaned = decoded
54
+ .split('\n')
55
+ .map((line) => line.trimEnd())
56
+ .join('\n')
57
+ .replace(/\n{3,}/g, '\n\n')
58
+ .trim();
59
+ return cleaned.length > 0 ? cleaned : null;
60
+ }
61
+ //# sourceMappingURL=github-release-html-parser.js.map
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mapPackageManifestToMetadata = mapPackageManifestToMetadata;
4
+ const repository_ref_1 = require("./repository-ref");
5
+ function mapPackageManifestToMetadata(packageName, rawData) {
6
+ const repository = rawData.repository;
7
+ const bugs = rawData.bugs;
8
+ const keywords = Array.isArray(rawData.keywords) ? rawData.keywords : [];
9
+ const author = typeof rawData.author === 'object' && rawData.author !== null
10
+ ? (rawData.author.name ?? rawData.author)
11
+ : rawData.author;
12
+ const repositoryUrl = (0, repository_ref_1.extractRepositoryUrl)(repository?.url || '');
13
+ const npmUrl = `https://www.npmjs.com/package/${encodeURIComponent(packageName)}`;
14
+ const issuesUrl = repositoryUrl ? `${repositoryUrl}/issues` : undefined;
15
+ const metadata = {
16
+ description: typeof rawData.description === 'string' && rawData.description
17
+ ? rawData.description
18
+ : 'No description available',
19
+ homepage: typeof rawData.homepage === 'string' ? rawData.homepage : undefined,
20
+ repository,
21
+ bugs,
22
+ keywords,
23
+ author: typeof author === 'string' ? author : undefined,
24
+ license: typeof rawData.license === 'string' ? rawData.license : undefined,
25
+ repositoryUrl,
26
+ npmUrl,
27
+ issuesUrl,
28
+ };
29
+ if (repositoryUrl) {
30
+ metadata.releaseNotes = `${repositoryUrl}/releases`;
31
+ }
32
+ return metadata;
33
+ }
34
+ //# sourceMappingURL=package-metadata.js.map