aboutsummaryrefslogblamecommitdiffhomepage
path: root/preinstall.js
blob: 292b73b961ff8d518baac93cfd48de5f6e11e2c9 (plain) (tree)
1
2
3
4
5
6
7
8
9

             


                             
                                              
                                 

                                        
                                     

                                      
                                           
 









                                  
 














                                                                                                                                                                                             
 



















                                                                                                 
 
                                             
                                                          

                                                          
 
                                              

                                                                                                                                                  

                                                                                                                                                         
 


                                                                                                                               












                                                                                              

                                                 
                                                            



                                                                                         











                                                                                       
"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 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 readVersion = name =>
  readPkgVersion(name)
    .orElse(readEnvVersion(name))
    .orElse(readCfgVersion(name))
    .version;

const dhallVersion = readVersion("dhall");
const dhallJsonVersion = readVersion("dhall-json");

const isLesserThan = (version, upperBound) =>
  semver.valid(version) && semver.lt(version, upperBound);
const isGreaterThan = (version, lowerBound) =>
  semver.valid(version) && semver.gt(version, lowerBound);

if (isLesserThan(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 (isLesserThan(dhallJsonVersion, "1.3.0") || isGreaterThan(dhallJsonVersion, "1.5.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 >1.5.0\`.`);
}

const release = `https://github.com/dhall-lang/dhall-haskell/releases/download/${dhallVersion}/dhall-json-${dhallJsonVersion}`;

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 {
  const isDarwin = process.platform === 'darwin';

  if (isDarwin && isLesserThan(dhallJsonVersion, "1.4.0")) {
    throw new Error(`Static macOS binaries aren’t provided by \`dhall-json@<1.4.0\`.`);
  }

  get(`x86_64-${isDarwin ? 'macos' : '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;
          });
        }
      });
    }))
  );
}