Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/excaliburjs/create-excalibur. A repo bootstrapping tool to get you started making your first games!
Something went wrong. Try again.
2.6 kB · 72 lines
TypeScript
at main
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273import * as path from "node:path";import { getChalk } from "../console.ts";import { ownPackageJson } from "../pkg-info.ts";import { cacheRoot, readJsonSync, writeJsonAtomic } from "./cache.ts";
const CHECK_TTL_MS = 24 * 60 * 60 * 1000; // once a dayconst REGISTRY_URL = "https://registry.npmjs.org/create-excalibur/latest";
interface UpdateCheckState { checkedAt: string; latest: string;}
function checkStatePath(): string { return path.join(cacheRoot(), "update-check.json");}
export function currentVersion(): string | null { return ownPackageJson()?.version ?? null;}
/** True when `a` is a newer semver than `b`. Handles prerelease tags loosely. */export function isNewer(a: string | null | undefined, b: string | null | undefined): boolean { if (!a || !b) return false; const parse = (v: string) => { const [core, pre] = String(v).replace(/^v/, "").split("-", 2); return { nums: core.split(".").map((n) => Number.parseInt(n, 10) || 0), pre: pre ?? null }; }; const va = parse(a); const vb = parse(b); for (let i = 0; i < 3; i++) { const d = (va.nums[i] ?? 0) - (vb.nums[i] ?? 0); if (d !== 0) return d > 0; } // Same core: a release beats a prerelease; otherwise compare prerelease strings. if (va.pre === vb.pre) return false; if (va.pre === null) return true; if (vb.pre === null) return false; return va.pre.localeCompare(vb.pre, "en", { numeric: true }) > 0;}
/** * Print a one-line gray hint when a newer create-excalibur is on the registry. * Checks the registry at most once a day; never throws, never blocks longer than ~2s. */export async function maybeNotifyUpdate({ print = console.error }: { print?: (message: string) => void } = {}): Promise<void> { try { const installed = currentVersion(); if (!installed) return;
let state = readJsonSync<UpdateCheckState>(checkStatePath()); if (!state || Date.now() - Date.parse(state.checkedAt) > CHECK_TTL_MS) { const res = await fetch(REGISTRY_URL, { headers: { Accept: "application/json" }, signal: AbortSignal.timeout(2000), }); if (!res.ok) return; const latest = ((await res.json()) as { version?: string } | null)?.version; if (!latest) return; state = { checkedAt: new Date().toISOString(), latest }; await writeJsonAtomic(checkStatePath(), state); }
if (isNewer(state.latest, installed)) { print( getChalk().gray(`Update available: create-excalibur ${installed} → ${state.latest} (npm i -g create-excalibur)`) ); } } catch { /* offline / registry hiccup — stay quiet */ }}