X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=preinstall.js;h=d53bca25827bca92282f3b542604d15237edfe04;hb=715fe0113813acb9e0cca251719c6394d4c3ab94;hp=1b859fc42ec98503bbb03a94e0983105c3355cb8;hpb=a4e6dec5fcffa5d51a96722a07668bab02336d5f;p=github%2Ffretlink%2Fnode-dhall-json-bin.git diff --git a/preinstall.js b/preinstall.js index 1b859fc..d53bca2 100644 --- a/preinstall.js +++ b/preinstall.js @@ -1,23 +1,100 @@ "use strict"; +const fs = require("fs"); +const path = require("path"); + const { https } = require("follow-redirects"); +const semver = require("semver"); const tar = require("tar"); const unbz2 = require("unbzip2-stream"); +const unzipper = require("unzipper"); const pkg = require("./package.json"); +const bindir = path.join(__dirname, "bin"); + +const formatVersionKey = name => + `${name}-version`; +const toSnakeCase = name => + name.replace(/-/g, '_'); +const formatNpmCfgVar = name => + toSnakeCase(name.toLowerCase()); +const formatEnvVar = name => + toSnakeCase(name.toUpperCase()); +const prefixNpmCfgKey = key => + `${pkg.name}:${key}`; + +const readVersionWith = (lookup, discard = () => {}) => name => { + const key = formatVersionKey(name); + const version = lookup(key); + return version ? { + get version() { return String(version).trim() }, + discard() { discard(key, version) }, + orElse(alt) { alt.discard(); return this } + } : { + get version() { + throw new Error(`Missing \`${name}\` version! You can provide it as a \`${prefixNpmCfgKey(key)}\` npm configuration parameter or as a \`${formatEnvVar(key)}\` environment variable.`); + }, + discard() {}, + orElse(alt) { return alt } + }; +}; -const trim = str => str && String(str).trim(); +const readPkgVersion = readVersionWith(key => pkg[key]); +const readCfgVersion = readVersionWith(key => { + return process.env[`npm_config_${formatNpmCfgVar(pkg.name)}_${formatNpmCfgVar(key)}`]; +}, (key, version) => { + console.warn(`Ignoring \`${prefixNpmCfgKey(key)}\` npm configuration parameter (${version}).`); +}); +const readEnvVersion = readVersionWith(key => { + return process.env[formatEnvVar(key)]; +}, (key, version) => { + console.warn(`Ignoring \`${formatEnvVar(key)}\` environment variable (${version}).`); +}); -const dhallVersion = trim(pkg["dhall-version"] || process.env.DHALL_VERSION); -if (!dhallVersion) throw new Error("Missing DHALL_VERSION environment variable."); +const readVersion = name => + readPkgVersion(name) + .orElse(readEnvVersion(name)) + .orElse(readCfgVersion(name)) + .version; -const dhallJsonVersion = trim(pkg["dhall-json-version"] || process.env.DHALL_JSON_VERSION); -if (!dhallJsonVersion) throw new Error("Missing DHALL_JSON_VERSION environment variable."); +const dhallVersion = readVersion("dhall"); +const dhallJsonVersion = readVersion("dhall-json"); + +const isLowerThan = (version, upperBound) => + semver.valid(version) && semver.lt(version, upperBound); + +if (isLowerThan(dhallJsonVersion, "1.2.8")) { + throw new Error(`This release of the \`${pkg.name}\` npm package installs \`json-to-dhall\`, which isn’t provided by \`dhall-json@<1.2.8\`.`); +} +if (isLowerThan(dhallJsonVersion, "1.3.0")) { + throw new Error(`This release of the \`${pkg.name}\` npm package installs \`yaml-to-dhall\`, which isn’t provided by \`dhall-json@<1.3.0\`.`); +} const release = `https://github.com/dhall-lang/dhall-haskell/releases/download/${dhallVersion}/dhall-json-${dhallJsonVersion}`; -const url = `${release}-x86_64-linux.tar.bz2`; -https.get(url, res => { - if (res.statusCode >= 400) throw new Error(`Error fetching ${url}: ${res.statusMessage}`); - res.pipe(unbz2()).pipe(tar.x({ C: __dirname })); -}); +const get = (archive, callback) => { + const url = `${release}-${archive}`; + return https.get(url, res => { + if (res.statusCode >= 400) throw new Error(`Error fetching ${url}: ${res.statusMessage}`); + return callback(res); + }); +}; + +if (process.platform === "win32") { + get("x86_64-windows.zip", res => + res.pipe(unzipper.Extract({ path: bindir })) + ); +} else { + get("x86_64-linux.tar.bz2", res => + res.pipe(unbz2()).pipe(tar.x({ C: __dirname }).on("finish", () => { + fs.readdir(bindir, (err, names) => { + if (err) throw err; + for (const name of names) { + fs.rename(path.join(bindir, name), path.join(bindir, name + ".exe"), err => { + if (err) throw err; + }); + } + }); + })) + ); +}