pkg-stats 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ ## PKG Stats
2
+
3
+ Beautiful package download stats.
package/dist/bin.js ADDED
@@ -0,0 +1,82 @@
1
+ import { renderChart } from "./chart.js";
2
+ import { parseVersion, versionCompare } from "./version.js";
3
+ const PACKAGE_NAME = process.argv[2];
4
+ const NPM_STATS_URL = `https://api.npmjs.org/versions/${encodeURIComponent(PACKAGE_NAME)}/last-week`;
5
+ export async function bin() {
6
+ const response = await fetch(NPM_STATS_URL);
7
+ const data = await response.json();
8
+ const rawStats = Object.keys(data.downloads)
9
+ .map((versionString) => {
10
+ const version = parseVersion(versionString);
11
+ return {
12
+ ...version,
13
+ downloads: data.downloads[versionString],
14
+ };
15
+ })
16
+ .sort(versionCompare);
17
+ const groupedStats = sumByMajor(rawStats);
18
+ const totalDownloads = Object.values(groupedStats).reduce((sum, version) => sum + version.downloads, 0);
19
+ console.log(`${PACKAGE_NAME} weekly downloads\n`);
20
+ console.log(`Total: ${totalDownloads.toLocaleString()}.\n`);
21
+ console.log("By version:\n");
22
+ const maxDownloads = Math.max(...groupedStats.map((v) => v.downloads));
23
+ for (const item of groupedStats) {
24
+ console.log(`${item.versionString.padStart(6)} ${renderChart(item.downloads / maxDownloads)} ${formatDownloads(item.downloads, maxDownloads).padStart(6)}`);
25
+ }
26
+ console.log(`\nGenerated on ${new Date().toISOString().slice(0, 10)} by npm-stats.`);
27
+ }
28
+ function sumByMajor(stats) {
29
+ const result = {};
30
+ for (const versionStats of stats) {
31
+ const key = `${versionStats.major}`;
32
+ const entry = result[key] ?? {
33
+ version: { major: versionStats.major },
34
+ versionString: key,
35
+ downloads: 0,
36
+ };
37
+ result[key] = entry;
38
+ entry.downloads += versionStats.downloads;
39
+ }
40
+ return Object.values(result).sort((a, b) => versionCompare(a.version, b.version));
41
+ }
42
+ function sumByMinor(stats) {
43
+ const result = {};
44
+ for (const versionStats of stats) {
45
+ const key = `${versionStats.major}.${versionStats.minor}`;
46
+ const entry = result[key] ?? {
47
+ version: { major: versionStats.major, minor: versionStats.minor },
48
+ versionString: key,
49
+ downloads: 0,
50
+ };
51
+ result[key] = entry;
52
+ entry.downloads += versionStats.downloads;
53
+ }
54
+ return Object.values(result).sort((a, b) => versionCompare(a.version, b.version));
55
+ }
56
+ function sumByPatch(stats) {
57
+ const result = {};
58
+ for (const versionStats of stats) {
59
+ const key = `${versionStats.major}.${versionStats.minor}.${versionStats.patch}`;
60
+ const entry = result[key] ?? {
61
+ version: {
62
+ major: versionStats.major,
63
+ minor: versionStats.minor,
64
+ patch: versionStats.patch,
65
+ },
66
+ versionString: key,
67
+ downloads: 0,
68
+ };
69
+ result[key] = entry;
70
+ entry.downloads += versionStats.downloads;
71
+ }
72
+ return Object.values(result).sort((a, b) => versionCompare(a.version, b.version));
73
+ }
74
+ function formatDownloads(downloads, maxDownloads) {
75
+ if (maxDownloads > 1000000) {
76
+ return `${(downloads / 1000000).toFixed(1)}M`;
77
+ }
78
+ if (maxDownloads > 1000) {
79
+ return `${(downloads / 1000).toFixed(1)}K`;
80
+ }
81
+ return downloads.toString();
82
+ }
package/dist/chart.js ADDED
@@ -0,0 +1,5 @@
1
+ export function renderChart(value, { length = 50 } = {}) {
2
+ const filledChars = Math.round(value * length);
3
+ const emptyChars = length - filledChars;
4
+ return "█".repeat(filledChars) + " ".repeat(emptyChars);
5
+ }
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import { bin } from "./bin.js";
2
+ bin();
@@ -0,0 +1,25 @@
1
+ export function parseVersion(version) {
2
+ const [versionCore, preRelease] = version.split("-");
3
+ const [major, minor, patch] = versionCore.split(".");
4
+ return {
5
+ major: Number(major),
6
+ minor: Number(minor),
7
+ patch: Number(patch),
8
+ preRelease,
9
+ };
10
+ }
11
+ export function versionCompare(a, b) {
12
+ if (a.major !== b.major) {
13
+ return b.major - a.major;
14
+ }
15
+ if (a.minor !== undefined && b.minor !== undefined && a.minor !== b.minor) {
16
+ return b.minor - a.minor;
17
+ }
18
+ if (a.patch !== undefined && b.patch !== undefined && a.patch !== b.patch) {
19
+ return b.patch - a.patch;
20
+ }
21
+ if (a.preRelease !== undefined && b.preRelease !== undefined) {
22
+ return a.preRelease.localeCompare(b.preRelease);
23
+ }
24
+ return 0;
25
+ }
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "pkg-stats",
3
+ "version": "0.0.1",
4
+ "description": "Beautiful package download stats",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "scripts": {
11
+ "build": "tsc"
12
+ },
13
+ "keywords": [],
14
+ "author": "",
15
+ "license": "MIT",
16
+ "packageManager": "pnpm@9.15.0+sha512.76e2379760a4328ec4415815bcd6628dee727af3779aaa4c914e3944156c4299921a89f976381ee107d41f12cfa4b66681ca9c718f0668fa0831ed4c6d8ba56c",
17
+ "devDependencies": {
18
+ "@types/node": "^22.10.5",
19
+ "typescript": "^5.7.3"
20
+ }
21
+ }