Files
wehub-resource-sync 9b395f5cc3
E2E Headed Chrome / e2e-headed (macos-15) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (ubuntu-latest) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (windows-latest) (push) Has been cancelled
CI / build (macos-latest) (push) Has been cancelled
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
CI / unit-test (push) Has been cancelled
CI / bun-test (push) Has been cancelled
CI / adapter-test (push) Has been cancelled
CI / smoke-test (macos-latest) (push) Has been cancelled
CI / smoke-test (ubuntu-latest) (push) Has been cancelled
Security Audit / audit (push) Has been cancelled
Build Chrome Extension / build (push) Has been cancelled
Trigger Website Rebuild (Docs Updated) / dispatch (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:39:48 +08:00

63 lines
3.0 KiB
JavaScript

// crates crate — fetch a single crate's metadata.
//
// Hits `https://crates.io/api/v1/crates/<name>`. Returns the agent-useful
// projection: name, latest version, description, total + recent downloads,
// homepage / docs / repo, license (from latest version row), version count,
// created / updated timestamps.
import { cli, Strategy } from '@jackwener/opencli/registry';
import { EmptyResultError } from '@jackwener/opencli/errors';
import { CRATES_BASE, cratesFetch, requireCrateName } from './utils.js';
cli({
site: 'crates',
name: 'crate',
access: 'read',
description: 'Single crates.io crate metadata (latest version, downloads, license, repo)',
domain: 'crates.io',
strategy: Strategy.PUBLIC,
browser: false,
args: [
{ name: 'name', positional: true, required: true, help: 'crates.io crate name (e.g. "serde", "tokio")' },
],
columns: [
'name', 'latestVersion', 'description', 'downloads', 'recentDownloads', 'versions',
'license', 'homepage', 'documentation', 'repository', 'keywords', 'categories', 'created', 'updated', 'url',
],
func: async (args) => {
const name = requireCrateName(args.name);
const body = await cratesFetch(`${CRATES_BASE}/api/v1/crates/${encodeURIComponent(name)}`, `crates crate ${name}`);
const c = body?.crate;
if (!c || !c.id) {
throw new EmptyResultError('crates crate', `crates.io returned no metadata for "${name}".`);
}
const versions = Array.isArray(body.versions) ? body.versions : [];
const latestRow = versions.find((v) => v.num === c.newest_version)
|| versions.find((v) => v.num === c.max_stable_version)
|| versions[0]
|| {};
const keywords = Array.isArray(body.keywords)
? body.keywords.map((k) => k?.keyword || k?.id || '').filter(Boolean).join(', ')
: '';
const categories = Array.isArray(body.categories)
? body.categories.map((cat) => cat?.category || cat?.slug || '').filter(Boolean).join(', ')
: '';
return [{
name: String(c.name ?? c.id),
latestVersion: String(c.newest_version ?? c.max_stable_version ?? c.max_version ?? ''),
description: String(c.description ?? '').trim(),
downloads: c.downloads != null ? Number(c.downloads) : null,
recentDownloads: c.recent_downloads != null ? Number(c.recent_downloads) : null,
versions: c.num_versions != null ? Number(c.num_versions) : versions.length,
license: String(latestRow.license ?? ''),
homepage: String(c.homepage ?? ''),
documentation: String(c.documentation ?? ''),
repository: String(c.repository ?? ''),
keywords,
categories,
created: String(c.created_at ?? '').slice(0, 10),
updated: String(c.updated_at ?? '').slice(0, 10),
url: `https://crates.io/crates/${c.name ?? c.id}`,
}];
},
});