UNPKG

jsr

Version:

jsr.io package manager for node

183 lines 6.93 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.downloadDeno = exports.getDenoDownloadUrl = void 0; // Copyright 2024 the JSR authors. MIT license. const os = __importStar(require("node:os")); const fs = __importStar(require("node:fs")); const path = __importStar(require("node:path")); const util = __importStar(require("node:util")); const stream = __importStar(require("node:stream")); const kl = __importStar(require("kolorist")); const StreamZip = __importStar(require("node-stream-zip")); const streamFinished = util.promisify(stream.finished); const DENO_CANARY_INFO_URL = "https://dl.deno.land/canary-latest.txt"; const DENO_RELEASE_INFO_URL = "https://dl.deno.land/release-latest.txt"; // Example: https://github.com/denoland/deno/releases/download/v1.41.0/deno-aarch64-apple-darwin.zip // Example: https://dl.deno.land/canary/d722de886b85093eeef08d1e9fd6f3193405762d/deno-aarch64-apple-darwin.zip const FILENAMES = { "darwin arm64": "deno-aarch64-apple-darwin", "darwin x64": "deno-x86_64-apple-darwin", "linux arm64": "deno-aarch64-unknown-linux-gnu", "linux x64": "deno-x86_64-unknown-linux-gnu", "win32 x64": "deno-x86_64-pc-windows-msvc", }; async function getDenoDownloadUrl(canary) { const key = `${process.platform} ${os.arch()}`; if (!(key in FILENAMES)) { throw new Error(`Unsupported platform: ${key}`); } const name = FILENAMES[key]; const filename = name + ".zip"; const url = canary ? DENO_CANARY_INFO_URL : DENO_RELEASE_INFO_URL; const res = await fetch(url); if (!res.ok) { await res.body?.cancel(); throw new Error(`${res.status}: Unable to retrieve ${canary ? "canary" : "release"} version information from ${url}.`); } const version = (await res.text()).trim(); return { canary, url: canary ? `https://dl.deno.land/canary/${decodeURI(version)}/${filename}` : `https://dl.deno.land/release/${decodeURI(version)}/${filename}`, filename, version: version, }; } exports.getDenoDownloadUrl = getDenoDownloadUrl; async function downloadDeno(binPath, info) { const binFolder = path.dirname(binPath); await fs.promises.mkdir(binFolder, { recursive: true }); const res = await fetch(info.url); const contentLen = Number(res.headers.get("content-length") ?? Infinity); if (res.body == null) { throw new Error(`Unexpected empty body`); } console.log(`Downloading JSR ${info.canary ? "canary" : "release"} binary...`); await withProgressBar(async (tick) => { const tmpFile = path.join(binFolder, info.filename + ".part"); const writable = fs.createWriteStream(tmpFile, "utf-8"); for await (const chunk of streamToAsyncIterable(res.body)) { tick(chunk.length); writable.write(chunk); } writable.end(); await streamFinished(writable); const file = path.join(binFolder, info.filename); await fs.promises.rename(tmpFile, file); const zip = new StreamZip.async({ file }); await zip.extract(null, binFolder); await zip.close(); // Mark as executable await fs.promises.chmod(binPath, 493); // Delete downloaded file await fs.promises.rm(file); }, { max: contentLen }); } exports.downloadDeno = downloadDeno; async function withProgressBar(fn, options) { let current = 0; let start = Date.now(); let passed = 0; let logged = false; const printStatus = throttle(() => { passed = Date.now() - start; const minutes = String(Math.floor(passed / 1000 / 60)).padStart(2, "0"); const seconds = String(Math.floor(passed / 1000) % 60).padStart(2, "0"); const time = `[${minutes}:${seconds}]`; const stats = `${humanFileSize(current)}/${humanFileSize(options.max)}`; const width = process.stdout.columns; let s = time; if (width - time.length - stats.length + 4 > 10) { const barLength = Math.min(width, 50); const percent = Math.floor((100 / options.max) * current); const bar = "#".repeat((barLength / 100) * percent) + ">"; const remaining = kl.blue("-".repeat(Math.max(barLength - bar.length, 0))); s += ` [${kl.cyan(bar)}${remaining}] `; } s += kl.dim(stats); if (process.stdout.isTTY) { if (logged) { process.stdout.write("\r\x1b[K"); } logged = true; process.stdout.write(s); } }, 16); const tick = (n) => { current += n; printStatus(); }; const res = await fn(tick); if (process.stdout.isTTY) { process.stdout.write("\n"); } else { console.log("Download completed"); } return res; } async function* streamToAsyncIterable(stream) { const reader = stream.getReader(); try { while (true) { const { done, value } = await reader.read(); if (done) return; yield value; } } finally { reader.releaseLock(); } } function humanFileSize(bytes, digits = 1) { const thresh = 1024; if (Math.abs(bytes) < thresh) { return bytes + " B"; } const units = ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"]; let u = -1; const r = 10 ** digits; do { bytes /= thresh; ++u; } while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1); return `${bytes.toFixed(digits)} ${units[u]}`; } function throttle(fn, delay) { let timer = null; return () => { if (timer === null) { fn(); timer = setTimeout(() => { timer = null; }, delay); } }; } //# sourceMappingURL=download.js.map