( pkg: string, timeoutMs: number = REGISTRY_TIMEOUT_MS, )
| 15 | |
| 16 | /** Hit the npm registry to learn what the latest published version is. */ |
| 17 | export async function fetchLatestNpmVersion( |
| 18 | pkg: string, |
| 19 | timeoutMs: number = REGISTRY_TIMEOUT_MS, |
| 20 | ): Promise<string | null> { |
| 21 | // encodeURIComponent turns "@matterailab/orbcode" into "@matterailab%2Forbcode", |
| 22 | // which is the form the registry URL expects for scoped packages. |
| 23 | const url = `https://registry.npmjs.org/${encodeURIComponent(pkg)}/latest`; |
| 24 | const controller = new AbortController(); |
| 25 | const timer = setTimeout(() => controller.abort(), timeoutMs); |
| 26 | try { |
| 27 | const res = await fetch(url, { |
| 28 | signal: controller.signal, |
| 29 | headers: { accept: "application/json" }, |
| 30 | }); |
| 31 | if (!res.ok) return null; |
| 32 | const data = (await res.json()) as { version?: unknown }; |
| 33 | return typeof data.version === "string" ? data.version : null; |
| 34 | } catch { |
| 35 | return null; |
| 36 | } finally { |
| 37 | clearTimeout(timer); |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | /** |
| 42 | * Compare two semver strings (X.Y.Z, optionally with a pre-release suffix). |
no test coverage detected