UNPKG

yalive-server

Version:
257 lines (253 loc) 9.55 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); // src/npm/node-platform.ts var fs = require("fs"); var os = require("os"); var path = require("path"); var YALIVE_BINARY_PATH = process.env.YALIVE_BINARY_PATH || YALIVE_BINARY_PATH; var knownWindowsPackages = { "win32 arm64 LE": "yalive-server-windows-arm64", // 'win32 ia32 LE': 'yalive-server-windows-32', "win32 x64 LE": "yalive-server-windows-64" }; var knownUnixlikePackages = { // 'android arm64 LE': 'yalive-server-android-arm64', "darwin arm64 LE": "yalive-server-darwin-arm64", "darwin x64 LE": "yalive-server-darwin-64", // 'freebsd arm64 LE': 'yalive-server-freebsd-arm64', // 'freebsd x64 LE': 'yalive-server-freebsd-64', // 'linux arm LE': 'yalive-server-linux-arm', "linux arm64 LE": "yalive-server-linux-arm64", // 'linux ia32 LE': 'yalive-server-linux-32', // 'linux mips64el LE': 'yalive-server-linux-mips64le', // 'linux ppc64 LE': 'yalive-server-linux-ppc64le', // 'linux s390x BE': 'yalive-server-linux-s390x', "linux x64 LE": "yalive-server-linux-64" // 'netbsd x64 LE': 'yalive-server-netbsd-64', // 'openbsd x64 LE': 'yalive-server-openbsd-64', // 'sunos x64 LE': 'yalive-server-sunos-64', }; function pkgAndSubpathForCurrentPlatform() { let pkg; let subpath; const platformKey = `${process.platform} ${os.arch()} ${os.endianness()}`; if (platformKey in knownWindowsPackages) { pkg = knownWindowsPackages[platformKey]; subpath = "bin/yalive-server.exe"; } else if (platformKey in knownUnixlikePackages) { pkg = knownUnixlikePackages[platformKey]; subpath = "bin/yalive-server"; } else { throw new Error(`Unsupported platform: ${platformKey}`); } return { pkg, subpath }; } function downloadedBinPath(pkg, subpath) { const libDir = path.dirname(require.resolve("yalive-server")); return path.join(libDir, `downloaded-${pkg}-${path.basename(subpath)}`); } // src/npm/node-install.ts var fs2 = require("fs"); var os2 = require("os"); var path2 = require("path"); var zlib = require("zlib"); var https = require("https"); var child_process = require("child_process"); var toFolder = path2.join(__dirname, "bin"); var toPath = path2.join(__dirname, "bin", "yalive-server"); var isToPathJS = true; function validateBinaryVersion(...command) { command.push("version"); const stdout = child_process.execFileSync(command.shift(), command, { // Without this, this install script strangely crashes with the error // "EACCES: permission denied, write" but only on Ubuntu Linux when node is // installed from the Snap Store. This is not a problem when you download // the official version of node. The problem appears to be that stderr // (i.e. file descriptor 2) isn't writable? // // More info: // - https://snapcraft.io/ (what the Snap Store is) // - https://nodejs.org/dist/ (download the official version of node) // - https://github.com/evanw/esbuild/issues/1711#issuecomment-1027554035 // stdio: "pipe" }).toString().trim(); if (stdout !== "0.3.1") { throw new Error(`Expected ${JSON.stringify("0.3.1")} but got ${JSON.stringify(stdout)}`); } } function isYarn() { const { npm_config_user_agent } = process.env; if (npm_config_user_agent) { return /\byarn\//.test(npm_config_user_agent); } return false; } function fetch(url) { return new Promise((resolve, reject) => { https.get(url, (res) => { if ((res.statusCode === 301 || res.statusCode === 302) && res.headers.location) return fetch(res.headers.location).then(resolve, reject); if (res.statusCode !== 200) return reject(new Error(`Server responded with ${res.statusCode}`)); const chunks = []; res.on("data", (chunk) => chunks.push(chunk)); res.on("end", () => resolve(Buffer.concat(chunks))); }).on("error", reject); }); } function extractFileFromTarGzip(buffer, subpath) { try { buffer = zlib.unzipSync(buffer); } catch (err) { throw new Error(`Invalid gzip data in archive: ${err?.message || err}`); } const str = (i, n) => String.fromCharCode(...buffer.subarray(i, i + n)).replace(/\0.*$/, ""); let offset = 0; subpath = `package/${subpath}`; while (offset < buffer.length) { const name = str(offset, 100); const size = parseInt(str(offset + 124, 12), 8); offset += 512; if (!isNaN(size)) { if (name === subpath) return buffer.subarray(offset, offset + size); offset += size + 511 & ~511; } } throw new Error(`Could not find ${JSON.stringify(subpath)} in archive`); } function removeRecursive(dir) { for (const entry of fs2.readdirSync(dir)) { const entryPath = path2.join(dir, entry); let stats; try { stats = fs2.lstatSync(entryPath); } catch { continue; } if (stats.isDirectory()) removeRecursive(entryPath); else fs2.unlinkSync(entryPath); } fs2.rmdirSync(dir); } function installUsingNPM(pkg, subpath, binPath) { const env = { ...process.env, npm_config_global: void 0 }; const yaliveLibDir = path2.dirname(require.resolve("yalive-server")); const installDir = path2.join(yaliveLibDir, "npm-install"); fs2.mkdirSync(installDir); try { fs2.writeFileSync(path2.join(installDir, "package.json"), "{}"); child_process.execSync( `npm install --loglevel=error --prefer-offline --no-audit --progress=false ${pkg}@${"0.3.1"}`, { cwd: installDir, stdio: "pipe", env } ); const installedBinPath = path2.join(installDir, "node_modules", pkg, subpath); fs2.renameSync(installedBinPath, binPath); } finally { try { removeRecursive(installDir); } catch { } } } function applyManualBinaryPathOverride(overridePath) { const pathString = JSON.stringify(overridePath); fs2.writeFileSync( toPath, `#!/usr/bin/env node require('child_process').execFileSync(${pathString}, process.argv.slice(2), { stdio: 'inherit' }); ` ); const libMain = path2.join(__dirname, "lib", "main.js"); const code = fs2.readFileSync(libMain, "utf8"); fs2.writeFileSync(libMain, `var YALIVE_BINARY_PATH = ${pathString}; ${code}`); } function maybeOptimizePackage(binPath) { if (os2.platform() !== "win32" && !isYarn()) { const tempPath = path2.join(__dirname, "bin-yalive-server"); try { fs2.linkSync(binPath, tempPath); if (!fs2.existsSync(toFolder)) { fs2.mkdirSync(toFolder); } fs2.renameSync(tempPath, toPath); isToPathJS = false; fs2.unlinkSync(tempPath); } catch { } } } async function downloadDirectlyFromNPM(pkg, subpath, binPath) { const url = `https://registry.npmjs.org/${pkg}/-/${pkg}-${"0.3.1"}.tgz`; console.error(`[yalive-server] Trying to download ${JSON.stringify(url)}`); try { fs2.writeFileSync(binPath, extractFileFromTarGzip(await fetch(url), subpath)); fs2.chmodSync(binPath, 493); } catch (e) { console.error(`[yalive-server] Failed to download ${JSON.stringify(url)}: ${e?.message || e}`); throw e; } } async function checkAndPreparePackage() { if (YALIVE_BINARY_PATH) { applyManualBinaryPathOverride(YALIVE_BINARY_PATH); return; } const { pkg, subpath } = pkgAndSubpathForCurrentPlatform(); let binPath; try { binPath = require.resolve(`${pkg}/${subpath}`); } catch (_e) { console.error(`[yalive-server] Failed to find package "${pkg}" on the file system This can happen if you use the "--no-optional" flag. The "optionalDependencies" package.json feature is used by yalive-server to install the correct binary executable for your current platform. This install script will now attempt to work around this. If that fails, you need to remove the "--no-optional" flag to use yalive-server. `); binPath = downloadedBinPath(pkg, subpath); try { console.error(`[yalive-server] Trying to install package "${pkg}" using npm`); installUsingNPM(pkg, subpath, binPath); } catch (e2) { console.error(`[yalive-server] Failed to install package "${pkg}" using npm: ${e2?.message || e2}`); try { await downloadDirectlyFromNPM(pkg, subpath, binPath); } catch (_e3) { throw new Error(`Failed to install package "${pkg}"`); } } } maybeOptimizePackage(binPath); } checkAndPreparePackage().then(() => { if (isToPathJS) { validateBinaryVersion("node", toPath); } else { validateBinaryVersion(toPath); } });