UNPKG

@reliverse/rse

Version:

@reliverse/rse is your all-in-one companion for bootstrapping and improving any kind of projects (especially web apps built with frameworks like Next.js) — whether you're kicking off something new or upgrading an existing app. It is also a little AI-power

177 lines (176 loc) 5.66 kB
import { dirname, join } from "@reliverse/pathkit"; import { ensuredir } from "@reliverse/relifso"; import fs from "@reliverse/relifso"; import { relinka } from "@reliverse/relinka"; import { installDependencies } from "nypm"; import { ofetch } from "ofetch"; import pLimit from "p-limit"; import semver from "semver"; import { glob } from "tinyglobby"; import { fileURLToPath } from "url"; const verbose = false; const BASE_URL = "https://jsr.io"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); async function fetchJson(url) { try { return await ofetch(url, { headers: { Accept: "application/json" } }); } catch (error) { throw new Error(`Failed to fetch JSON from "${url}" (error: ${error})`); } } async function getPackageMeta(scope, packageName) { const url = `${BASE_URL}/@${scope}/${packageName}/meta.json`; return fetchJson(url); } function pickVersionFromMeta(meta, userVersion) { if (userVersion) { const info = meta.versions[userVersion]; if (!info) { throw new Error( `Version "${userVersion}" not found in package metadata.` ); } if (info.yanked) { throw new Error( `Version "${userVersion}" is yanked and cannot be downloaded.` ); } return userVersion; } const versions = Object.keys(meta.versions).filter((v) => { const versionInfo = meta.versions[v]; return versionInfo && !versionInfo.yanked && semver.valid(v); }); if (versions.length === 0) { throw new Error( "No valid (non-yanked, semver) versions found for this package." ); } versions.sort((a, b) => semver.rcompare(a, b)); return versions[0]; } async function getVersionMeta(scope, packageName, version) { const url = `${BASE_URL}/@${scope}/${packageName}/${version}_meta.json`; return fetchJson(url); } async function downloadFile(scope, packageName, version, filePath, outputDir, useSinglePath) { const trimmedFilePath = filePath.replace(/^\//, ""); const url = `${BASE_URL}/@${scope}/${packageName}/${version}/${trimmedFilePath}`; const buffer = Buffer.from( await ofetch(url, { headers: { Accept: "*/*" }, responseType: "arrayBuffer" }) ); const targetFilePath = useSinglePath ? join(outputDir, trimmedFilePath) : join(outputDir, scope, packageName, version, trimmedFilePath); await ensuredir(dirname(targetFilePath)); await fs.writeFile(targetFilePath, buffer); relinka("verbose", `Downloaded: ${url} -> ${targetFilePath}`); } async function isPackageDownloaded(filePaths, outputDir, useSinglePath, scope, packageName, version) { try { for (const filePath of filePaths) { const trimmedFilePath = filePath.replace(/^\//, ""); const targetFilePath = useSinglePath ? join(outputDir, trimmedFilePath) : join(outputDir, scope, packageName, version, trimmedFilePath); if (!await fs.pathExists(targetFilePath)) { return false; } } return true; } catch { return false; } } async function renameTxtToTsx(dir) { try { const files = await glob("**/*-tsx.txt", { cwd: dir, absolute: true }); for (const filePath of files) { const newPath = filePath.replace(/-tsx\.txt$/, ".tsx"); await fs.rename(filePath, newPath); if (verbose) { relinka("verbose", `Renamed: ${filePath} -> ${newPath}`); } } } catch (error) { relinka( "error", "Error renaming -tsx.txt files:", error instanceof Error ? error.message : String(error) ); } } export async function downloadJsrDist(scope, packageName, version, outputDir = join(__dirname, "output"), useSinglePath = true, concurrency = 5, pkgIsCLI = true, msgDownloadStarted, revertTsxFiles = false, cliInstallDeps = true) { try { const meta = await getPackageMeta(scope, packageName); const resolvedVersion = version || pickVersionFromMeta(meta); const versionMeta = await getVersionMeta( scope, packageName, resolvedVersion ); const filePaths = Object.keys(versionMeta.manifest); const isDownloaded = await isPackageDownloaded( filePaths, outputDir, useSinglePath, scope, packageName, resolvedVersion ); if (isDownloaded) { relinka( "success", `@${scope}/${packageName}@${resolvedVersion} is already downloaded.`, pkgIsCLI ? `Use "bun ${outputDir}/bin/mod.ts" to run it (short command coming soon).` : void 0 ); return; } relinka( "info", msgDownloadStarted ?? `Downloading ${scope}/${packageName}@${resolvedVersion} from JSR...` ); const limit = pLimit(concurrency); const tasks = filePaths.map( (filePath) => limit( () => downloadFile( scope, packageName, resolvedVersion, filePath, outputDir, useSinglePath ) ) ); await Promise.all(tasks); if (pkgIsCLI && revertTsxFiles) { relinka("verbose", "Reverting .tsx files..."); await renameTxtToTsx(outputDir); } if (pkgIsCLI && cliInstallDeps) { relinka("info", "Installing dependencies..."); await installDependencies({ cwd: outputDir, silent: false }); } relinka( "success", `All files for @${scope}/${packageName} downloaded successfully.`, pkgIsCLI ? `Use "bun ${outputDir}/bin/mod.ts" to run it (short command coming soon).` : void 0 ); } catch (error) { relinka( "error", `Something went wrong while downloading ${scope}/${packageName}:`, `${error}` ); throw error; } }