/**
 * Resolves npm package versions at generation time.
 *
 * When a template specifies "latest" for a package, we fetch the actual
 * current version from the npm registry and pin it exactly, so generated
 * projects don't silently drift over time.
 */
const cache = new Map();
export async function resolveNpmVersion(pkg) {
    if (cache.has(pkg)) {
        return cache.get(pkg);
    }
    try {
        const res = await fetch(`https://registry.npmjs.org/${pkg}/latest`, {
            headers: { Accept: 'application/vnd.npm.install-v1+json' },
        });
        if (!res.ok)
            return null;
        const data = (await res.json());
        const version = data.version ?? null;
        if (version)
            cache.set(pkg, version);
        return version;
    }
    catch {
        return null;
    }
}
/**
 * Walk a deps object and resolve any "latest" values to pinned versions.
 * Non-"latest" values are left untouched.
 */
export async function resolveLatestVersions(deps) {
    const entries = Object.entries(deps);
    const resolved = await Promise.all(entries.map(async ([name, version]) => {
        if (version !== 'latest')
            return [name, version];
        const pinned = await resolveNpmVersion(name);
        return [name, pinned ?? 'latest'];
    }));
    return Object.fromEntries(resolved);
}
/**
 * Resolve all "latest" version specifiers in a package.json object's
 * dependencies and devDependencies in-place, returning a new object.
 */
export async function resolvePackageJSONLatest(packageJSON) {
    const result = { ...packageJSON };
    if (result.dependencies) {
        result.dependencies = await resolveLatestVersions(result.dependencies);
    }
    if (result.devDependencies) {
        result.devDependencies = await resolveLatestVersions(result.devDependencies);
    }
    return result;
}
