UNPKG

starknet-devnet

Version:
133 lines (132 loc) 5.68 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.VersionHandler = void 0; const axios_1 = __importDefault(require("axios")); const path_1 = __importDefault(require("path")); const fs_1 = __importDefault(require("fs")); const os_1 = __importDefault(require("os")); const constants_1 = require("./constants"); const types_1 = require("./types"); const decompress_1 = __importDefault(require("decompress")); // eslint-disable-next-line @typescript-eslint/no-var-requires const decompressTargz = require("decompress-targz"); class VersionHandler { static getVersionDir(version) { return path_1.default.join(this.localStoragePath, version); } static getExecutablePath(versionDir) { return path_1.default.join(versionDir, "starknet-devnet"); } /** * Ensure that the command corresponding to the provided `version` exists. * @param version semver string with a prepended "v"; * should be available in https://github.com/0xSpaceShard/starknet-devnet/releases * @returns the path to the executable corresponding to the version */ static async getExecutable(version) { const versionDir = this.getVersionDir(version); const executable = this.getExecutablePath(versionDir); if (fs_1.default.existsSync(executable)) { return executable; } const executableUrl = await this.getArchivedExecutableUrl(version); const archivePath = await this.fetchArchivedExecutable(executableUrl, versionDir); await this.extract(archivePath, versionDir); return executable; } static getCompatibleArch() { switch (process.arch) { case "arm64": return "aarch64"; case "x64": return "x86_64"; default: throw new types_1.DevnetError(`Incompatible architecture: ${process.platform}`); } } static getCompatiblePlatform() { switch (process.platform) { case "linux": return "unknown-linux-gnu"; case "darwin": return "apple-darwin"; default: throw new types_1.DevnetError(`Incompatible platform: ${process.platform}`); } } static async getArchivedExecutableUrl(version) { const releasesUrl = "https://api.github.com/repos/0xSpaceShard/starknet-devnet/releases"; const releasesResp = await this.httpProvider.get(releasesUrl); if (releasesResp.status !== axios_1.default.HttpStatusCode.Ok) { throw new types_1.GithubError(releasesResp.statusText); } if (!Array.isArray(releasesResp.data)) { throw new types_1.GithubError(`Invalid response: ${JSON.stringify(releasesResp.data)}`); } let versionPresent = false; for (const release of releasesResp.data) { if (release.name === version) { versionPresent = true; break; } } if (!versionPresent) { throw new types_1.GithubError(`Version not found. If specifying an exact version, make sure you prepended the 'v' and that the version really exists in ${releasesUrl}.`); } const arch = this.getCompatibleArch(); const platform = this.getCompatiblePlatform(); return `https://github.com/0xSpaceShard/starknet-devnet/releases/download/${version}/starknet-devnet-${arch}-${platform}.tar.gz`; } /** * @param url the url of the archived executable * @param versionDir the path to the directory where the archive will be written and extracted * @returns the path where the archive was stored */ static async fetchArchivedExecutable(url, versionDir) { const resp = await this.httpProvider.get(url, { responseType: "stream" }); if (resp.status === axios_1.default.HttpStatusCode.NotFound) { throw new types_1.GithubError(`Not found: ${url}`); } else if (resp.status !== axios_1.default.HttpStatusCode.Ok) { throw new types_1.GithubError(resp.statusText); } if (!fs_1.default.existsSync(versionDir)) { fs_1.default.mkdirSync(versionDir, { recursive: true }); } const archivedExecutablePath = path_1.default.join(versionDir, "archive.tar.gz"); const writer = fs_1.default.createWriteStream(archivedExecutablePath); return new Promise((resolve, reject) => { resp.data.pipe(writer); let error; writer.on("error", (e) => { error = e; writer.close(); reject(error); }); writer.on("close", () => { if (!error) { resolve(archivedExecutablePath); } // no need to call `reject` here, as it will have been called in the // "error" stream; }); }); } /** * Extract the content of the archive. * @param archivePath the local path of the archive */ static async extract(archivePath, targetDir) { await (0, decompress_1.default)(archivePath, targetDir, { plugins: [decompressTargz()], }); } } exports.VersionHandler = VersionHandler; VersionHandler.httpProvider = axios_1.default.create({ timeout: constants_1.DEFAULT_HTTP_TIMEOUT, }); VersionHandler.localStoragePath = path_1.default.join(os_1.default.tmpdir(), "devnet-versions");