stevekrouse-gitreleasenotes.web.val.run
Readme

Github Release Notes from package.json

Enter a raw github URL to a package.json,

https://raw.githubusercontent.com/username/repo/branch/package.json

and get a response of all release notes for all packages from current to latest.

Roadmap

  • GenAI summary
  • Weekly cron email reports
  • Other package managers like PyPi
  • Formatting/styling
  • Loading spinner
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/** @jsxImportSource npm:hono@3/jsx */
import { extractValInfo } from "https://esm.town/v/pomdtr/extractValInfo?v=29";
import { Hono } from "npm:hono";
import { marked } from "npm:marked";
interface PackageJson {
dependencies?: Record<string, string>;
devDependencies?: Record<string, string>;
}
interface GithubRelease {
tag_name: string;
name: string;
body: string;
published_at: string;
}
// Function to fetch package info from NPM registry
async function fetchPackageInfo(packageName: string) {
const url = `https://registry.npmjs.org/${packageName}`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to fetch package info for ${packageName}`);
}
return response.json();
}
// Function to extract GitHub repo URL from package info
function extractGitHubRepoUrl(packageInfo: any): string | null {
const repository = packageInfo.repository;
if (repository && repository.url) {
let repoUrl = repository.url;
// Convert git URL to HTTPS URL if necessary
repoUrl = repoUrl.replace(/^git\+/, "").replace(/\.git$/, "");
return repoUrl;
}
return null;
}
// Function to get the GitHub repository path (owner/repo) from the URL
function getGithubRepoPath(repoUrl: string): string | null {
const match = repoUrl.match(/github\.com\/([^\/]+\/[^\/]+)/);
return match ? match[1] : null;
}
async function getGithubReleases(repo: string): Promise<GithubRelease[]> {
const response = await fetch(`https://api.github.com/repos/${repo}/releases`);
if (!response.ok) {
throw new Error(`Failed to fetch releases from ${repo}`);
}
return response.json();
}
function compareVersions(version1: string, version2: string): number {
const v1 = version1.replace(/^v/, "").split(".").map(Number);
const v2 = version2.replace(/^v/, "").split(".").map(Number);
for (let i = 0; i < Math.max(v1.length, v2.length); i++) {
const diff = (v1[i] || 0) - (v2[i] || 0);
if (diff !== 0) return diff;
}
return 0;
}
async function getReleaseNotesBetweenVersions(repo: string, currentVersion: string): Promise<GithubRelease[]> {
const releases = await getGithubReleases(repo);
const filteredReleases = releases.filter(release => {
const version = release.tag_name.replace(/^v/, "");
return compareVersions(version, currentVersion) > 0;
});
return filteredReleases.sort((a, b) => compareVersions(a.tag_name, b.tag_name));
}
async function checkNpmUpdates(packageJsonUrl: string): Promise<string> {
try {
const response = await fetch(packageJsonUrl);
if (!response.ok) {
throw new Error(`Failed to fetch package.json from ${packageJsonUrl}`);
}
const packageJson: PackageJson = await response.json();
const dependencies = packageJson.dependencies ?? {};
const devDependencies = packageJson.devDependencies ?? {};
let result = "Checking dependencies for updates...\n";
for (const [name, version] of Object.entries(dependencies)) {
try {
const packageInfo = await fetchPackageInfo(name);
const repoUrl = extractGitHubRepoUrl(packageInfo);
if (!repoUrl) {
result += `No GitHub repository URL found for ${name}\n`;
continue;
}
const repoPath = getGithubRepoPath(repoUrl);
if (!repoPath) {
result += `Invalid GitHub repository URL for ${name}: ${repoUrl}\n`;
continue;
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Comments
Nobody has commented on this val yet: be the first!
July 22, 2024