1- import type { Packument } from '#shared/types'
1+ import type { FastNpmMetaResponse , Packument } from '#shared/types'
22import { maxSatisfying , prerelease } from 'semver'
33
44const NPM_REGISTRY = 'https://registry.npmjs.org'
5+ const FAST_NPM_META_API = 'https://npm.antfu.dev'
56
67function encodePackageName ( name : string ) : string {
78 if ( name . startsWith ( '@' ) ) {
@@ -23,6 +24,53 @@ export const fetchNpmPackage = defineCachedFunction(
2324 } ,
2425)
2526
27+ /**
28+ * Fetch lightweight package metadata from fast-npm-meta API.
29+ * Much smaller payload than full packument - ideal for just getting latest version.
30+ *
31+ * @param name Package name
32+ * @param specifier Optional version specifier (tag like "alpha", or range like "^2.1.0")
33+ * @returns Resolved version info
34+ * @see https://github.com/antfu/fast-npm-meta
35+ */
36+ export const fetchFastNpmMeta = defineCachedFunction (
37+ async ( name : string , specifier ?: string ) : Promise < FastNpmMetaResponse > => {
38+ const encodedName = encodePackageName ( name )
39+ const url = specifier
40+ ? `${ FAST_NPM_META_API } /${ encodedName } @${ encodeURIComponent ( specifier ) } `
41+ : `${ FAST_NPM_META_API } /${ encodedName } `
42+ return await $fetch < FastNpmMetaResponse > ( url )
43+ } ,
44+ {
45+ maxAge : 60 * 5 ,
46+ swr : true ,
47+ name : 'fast-npm-meta' ,
48+ getKey : ( name : string , specifier ?: string ) => ( specifier ? `${ name } @${ specifier } ` : name ) ,
49+ } ,
50+ )
51+
52+ /**
53+ * Get the latest version of a package using fast-npm-meta API.
54+ * Falls back to full packument if fast-npm-meta fails.
55+ *
56+ * @param name Package name
57+ * @returns Latest version string or null if not found
58+ */
59+ export async function fetchLatestVersion ( name : string ) : Promise < string | null > {
60+ try {
61+ const meta = await fetchFastNpmMeta ( name )
62+ return meta . version
63+ } catch {
64+ // Fallback to full packument
65+ try {
66+ const packument = await fetchNpmPackage ( name )
67+ return packument [ 'dist-tags' ] ?. latest ?? null
68+ } catch {
69+ return null
70+ }
71+ }
72+ }
73+
2674/**
2775 * Check if a version constraint explicitly includes a prerelease tag.
2876 * e.g., "^1.0.0-alpha" or ">=2.0.0-beta.1" include prereleases
0 commit comments