@mcptoolshop/registry-stats 1.2.0 → 1.2.2
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.
- package/dist/cli.js +45 -2
- package/dist/index.cjs +45 -2
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +45 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -25,8 +25,10 @@ var REGISTRY_DELAYS = {
|
|
|
25
25
|
// ~2.5 req/s — safe for 54+ scoped packages
|
|
26
26
|
pypi: 2200,
|
|
27
27
|
// 30 req/60s = 1 per 2s, with headroom
|
|
28
|
-
docker: 4e3
|
|
28
|
+
docker: 4e3,
|
|
29
29
|
// 10 req/3600s — very tight
|
|
30
|
+
ghcr: 200
|
|
31
|
+
// 5000 req/hr authenticated, 60/hr unauth
|
|
30
32
|
};
|
|
31
33
|
var DEFAULT_DELAY = 100;
|
|
32
34
|
function acquireSlot(registry) {
|
|
@@ -301,6 +303,46 @@ var docker = {
|
|
|
301
303
|
}
|
|
302
304
|
};
|
|
303
305
|
|
|
306
|
+
// src/providers/ghcr.ts
|
|
307
|
+
var API5 = "https://api.github.com";
|
|
308
|
+
var ghcr = {
|
|
309
|
+
name: "ghcr",
|
|
310
|
+
rateLimit: { maxRequests: 50, windowSeconds: 3600, authRaisesLimit: true },
|
|
311
|
+
async getStats(pkg, options) {
|
|
312
|
+
const slash = pkg.indexOf("/");
|
|
313
|
+
if (slash === -1) return null;
|
|
314
|
+
const owner = pkg.slice(0, slash);
|
|
315
|
+
const name = pkg.slice(slash + 1);
|
|
316
|
+
const headers = {
|
|
317
|
+
"Accept": "application/vnd.github+json",
|
|
318
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
319
|
+
};
|
|
320
|
+
if (options?.ghcrToken) {
|
|
321
|
+
headers["Authorization"] = `Bearer ${options.ghcrToken}`;
|
|
322
|
+
}
|
|
323
|
+
const versions = await fetchWithRetry(
|
|
324
|
+
`${API5}/orgs/${owner}/packages/container/${encodeURIComponent(name)}/versions?per_page=100`,
|
|
325
|
+
"ghcr",
|
|
326
|
+
{ headers }
|
|
327
|
+
);
|
|
328
|
+
if (!versions || !Array.isArray(versions)) return null;
|
|
329
|
+
const totalPulls = versions.reduce((sum, v) => sum + (v.download_count ?? 0), 0);
|
|
330
|
+
const tags = versions.flatMap((v) => v.metadata?.container?.tags ?? []);
|
|
331
|
+
return {
|
|
332
|
+
registry: "ghcr",
|
|
333
|
+
package: pkg,
|
|
334
|
+
downloads: {
|
|
335
|
+
total: totalPulls
|
|
336
|
+
},
|
|
337
|
+
extra: {
|
|
338
|
+
tags: tags.slice(0, 10),
|
|
339
|
+
versionCount: versions.length
|
|
340
|
+
},
|
|
341
|
+
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
|
|
304
346
|
// src/calc.ts
|
|
305
347
|
var calc = {
|
|
306
348
|
total(records) {
|
|
@@ -604,7 +646,8 @@ var providers = {
|
|
|
604
646
|
pypi,
|
|
605
647
|
nuget,
|
|
606
648
|
vscode,
|
|
607
|
-
docker
|
|
649
|
+
docker,
|
|
650
|
+
ghcr
|
|
608
651
|
};
|
|
609
652
|
var DEFAULT_TTL = 3e5;
|
|
610
653
|
async function stats(registry, pkg, options) {
|
package/dist/index.cjs
CHANGED
|
@@ -54,8 +54,10 @@ var REGISTRY_DELAYS = {
|
|
|
54
54
|
// ~2.5 req/s — safe for 54+ scoped packages
|
|
55
55
|
pypi: 2200,
|
|
56
56
|
// 30 req/60s = 1 per 2s, with headroom
|
|
57
|
-
docker: 4e3
|
|
57
|
+
docker: 4e3,
|
|
58
58
|
// 10 req/3600s — very tight
|
|
59
|
+
ghcr: 200
|
|
60
|
+
// 5000 req/hr authenticated, 60/hr unauth
|
|
59
61
|
};
|
|
60
62
|
var DEFAULT_DELAY = 100;
|
|
61
63
|
function acquireSlot(registry) {
|
|
@@ -330,6 +332,46 @@ var docker = {
|
|
|
330
332
|
}
|
|
331
333
|
};
|
|
332
334
|
|
|
335
|
+
// src/providers/ghcr.ts
|
|
336
|
+
var API5 = "https://api.github.com";
|
|
337
|
+
var ghcr = {
|
|
338
|
+
name: "ghcr",
|
|
339
|
+
rateLimit: { maxRequests: 50, windowSeconds: 3600, authRaisesLimit: true },
|
|
340
|
+
async getStats(pkg, options) {
|
|
341
|
+
const slash = pkg.indexOf("/");
|
|
342
|
+
if (slash === -1) return null;
|
|
343
|
+
const owner = pkg.slice(0, slash);
|
|
344
|
+
const name = pkg.slice(slash + 1);
|
|
345
|
+
const headers = {
|
|
346
|
+
"Accept": "application/vnd.github+json",
|
|
347
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
348
|
+
};
|
|
349
|
+
if (options?.ghcrToken) {
|
|
350
|
+
headers["Authorization"] = `Bearer ${options.ghcrToken}`;
|
|
351
|
+
}
|
|
352
|
+
const versions = await fetchWithRetry(
|
|
353
|
+
`${API5}/orgs/${owner}/packages/container/${encodeURIComponent(name)}/versions?per_page=100`,
|
|
354
|
+
"ghcr",
|
|
355
|
+
{ headers }
|
|
356
|
+
);
|
|
357
|
+
if (!versions || !Array.isArray(versions)) return null;
|
|
358
|
+
const totalPulls = versions.reduce((sum, v) => sum + (v.download_count ?? 0), 0);
|
|
359
|
+
const tags = versions.flatMap((v) => v.metadata?.container?.tags ?? []);
|
|
360
|
+
return {
|
|
361
|
+
registry: "ghcr",
|
|
362
|
+
package: pkg,
|
|
363
|
+
downloads: {
|
|
364
|
+
total: totalPulls
|
|
365
|
+
},
|
|
366
|
+
extra: {
|
|
367
|
+
tags: tags.slice(0, 10),
|
|
368
|
+
versionCount: versions.length
|
|
369
|
+
},
|
|
370
|
+
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
|
|
333
375
|
// src/calc.ts
|
|
334
376
|
var calc = {
|
|
335
377
|
total(records) {
|
|
@@ -642,7 +684,8 @@ var providers = {
|
|
|
642
684
|
pypi,
|
|
643
685
|
nuget,
|
|
644
686
|
vscode,
|
|
645
|
-
docker
|
|
687
|
+
docker,
|
|
688
|
+
ghcr
|
|
646
689
|
};
|
|
647
690
|
function registerProvider(provider) {
|
|
648
691
|
providers[provider.name] = provider;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as node_http from 'node:http';
|
|
2
2
|
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
3
3
|
|
|
4
|
-
type RegistryName = 'npm' | 'pypi' | 'nuget' | 'vscode' | 'docker';
|
|
4
|
+
type RegistryName = 'npm' | 'pypi' | 'nuget' | 'vscode' | 'docker' | 'ghcr';
|
|
5
5
|
interface PackageStats {
|
|
6
6
|
registry: RegistryName;
|
|
7
7
|
package: string;
|
|
@@ -38,6 +38,8 @@ interface StatsCache {
|
|
|
38
38
|
}
|
|
39
39
|
interface StatsOptions {
|
|
40
40
|
dockerToken?: string;
|
|
41
|
+
/** GitHub token for GHCR (GitHub Container Registry) — read:packages scope */
|
|
42
|
+
ghcrToken?: string;
|
|
41
43
|
/** Max concurrent requests for bulk operations (default: 5) */
|
|
42
44
|
concurrency?: number;
|
|
43
45
|
/** Cache instance — use createCache() for built-in TTL cache */
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as node_http from 'node:http';
|
|
2
2
|
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
3
3
|
|
|
4
|
-
type RegistryName = 'npm' | 'pypi' | 'nuget' | 'vscode' | 'docker';
|
|
4
|
+
type RegistryName = 'npm' | 'pypi' | 'nuget' | 'vscode' | 'docker' | 'ghcr';
|
|
5
5
|
interface PackageStats {
|
|
6
6
|
registry: RegistryName;
|
|
7
7
|
package: string;
|
|
@@ -38,6 +38,8 @@ interface StatsCache {
|
|
|
38
38
|
}
|
|
39
39
|
interface StatsOptions {
|
|
40
40
|
dockerToken?: string;
|
|
41
|
+
/** GitHub token for GHCR (GitHub Container Registry) — read:packages scope */
|
|
42
|
+
ghcrToken?: string;
|
|
41
43
|
/** Max concurrent requests for bulk operations (default: 5) */
|
|
42
44
|
concurrency?: number;
|
|
43
45
|
/** Cache instance — use createCache() for built-in TTL cache */
|
package/dist/index.js
CHANGED
|
@@ -19,8 +19,10 @@ var REGISTRY_DELAYS = {
|
|
|
19
19
|
// ~2.5 req/s — safe for 54+ scoped packages
|
|
20
20
|
pypi: 2200,
|
|
21
21
|
// 30 req/60s = 1 per 2s, with headroom
|
|
22
|
-
docker: 4e3
|
|
22
|
+
docker: 4e3,
|
|
23
23
|
// 10 req/3600s — very tight
|
|
24
|
+
ghcr: 200
|
|
25
|
+
// 5000 req/hr authenticated, 60/hr unauth
|
|
24
26
|
};
|
|
25
27
|
var DEFAULT_DELAY = 100;
|
|
26
28
|
function acquireSlot(registry) {
|
|
@@ -295,6 +297,46 @@ var docker = {
|
|
|
295
297
|
}
|
|
296
298
|
};
|
|
297
299
|
|
|
300
|
+
// src/providers/ghcr.ts
|
|
301
|
+
var API5 = "https://api.github.com";
|
|
302
|
+
var ghcr = {
|
|
303
|
+
name: "ghcr",
|
|
304
|
+
rateLimit: { maxRequests: 50, windowSeconds: 3600, authRaisesLimit: true },
|
|
305
|
+
async getStats(pkg, options) {
|
|
306
|
+
const slash = pkg.indexOf("/");
|
|
307
|
+
if (slash === -1) return null;
|
|
308
|
+
const owner = pkg.slice(0, slash);
|
|
309
|
+
const name = pkg.slice(slash + 1);
|
|
310
|
+
const headers = {
|
|
311
|
+
"Accept": "application/vnd.github+json",
|
|
312
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
313
|
+
};
|
|
314
|
+
if (options?.ghcrToken) {
|
|
315
|
+
headers["Authorization"] = `Bearer ${options.ghcrToken}`;
|
|
316
|
+
}
|
|
317
|
+
const versions = await fetchWithRetry(
|
|
318
|
+
`${API5}/orgs/${owner}/packages/container/${encodeURIComponent(name)}/versions?per_page=100`,
|
|
319
|
+
"ghcr",
|
|
320
|
+
{ headers }
|
|
321
|
+
);
|
|
322
|
+
if (!versions || !Array.isArray(versions)) return null;
|
|
323
|
+
const totalPulls = versions.reduce((sum, v) => sum + (v.download_count ?? 0), 0);
|
|
324
|
+
const tags = versions.flatMap((v) => v.metadata?.container?.tags ?? []);
|
|
325
|
+
return {
|
|
326
|
+
registry: "ghcr",
|
|
327
|
+
package: pkg,
|
|
328
|
+
downloads: {
|
|
329
|
+
total: totalPulls
|
|
330
|
+
},
|
|
331
|
+
extra: {
|
|
332
|
+
tags: tags.slice(0, 10),
|
|
333
|
+
versionCount: versions.length
|
|
334
|
+
},
|
|
335
|
+
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
|
|
298
340
|
// src/calc.ts
|
|
299
341
|
var calc = {
|
|
300
342
|
total(records) {
|
|
@@ -607,7 +649,8 @@ var providers = {
|
|
|
607
649
|
pypi,
|
|
608
650
|
nuget,
|
|
609
651
|
vscode,
|
|
610
|
-
docker
|
|
652
|
+
docker,
|
|
653
|
+
ghcr
|
|
611
654
|
};
|
|
612
655
|
function registerProvider(provider) {
|
|
613
656
|
providers[provider.name] = provider;
|
package/package.json
CHANGED