github.com/Redstoneguy129/cli@v0.0.0-20230211220159-15dca4e91917/scripts/postinstall.js (about)

     1  #!/usr/bin/env node
     2  
     3  // Ref 1: https://github.com/sanathkr/go-npm
     4  // Ref 2: https://blog.xendit.engineer/how-we-repurposed-npm-to-publish-and-distribute-our-go-binaries-for-internal-cli-23981b80911b
     5  "use strict";
     6  
     7  import binLinks from "bin-links";
     8  import fs from "fs";
     9  import fetch from "node-fetch";
    10  import path from "path";
    11  import tar from "tar";
    12  import zlib from "zlib";
    13  
    14  // Mapping from Node's `process.arch` to Golang's `$GOARCH`
    15  const ARCH_MAPPING = {
    16    x64: "amd64",
    17    arm64: "arm64",
    18  };
    19  
    20  // Mapping between Node's `process.platform` to Golang's
    21  const PLATFORM_MAPPING = {
    22    darwin: "darwin",
    23    linux: "linux",
    24    win32: "windows",
    25  };
    26  
    27  // TODO: import pkg from "../package.json" assert { type: "json" };
    28  const readPackageJson = async () => {
    29    const packageJsonPath = path.join(".", "package.json");
    30    const contents = await fs.promises.readFile(packageJsonPath);
    31    return JSON.parse(contents);
    32  };
    33  
    34  const parsePackageJson = (packageJson) => {
    35    const arch = ARCH_MAPPING[process.arch];
    36    if (!arch) {
    37      throw Error(
    38        "Installation is not supported for this architecture: " + process.arch
    39      );
    40    }
    41  
    42    const platform = PLATFORM_MAPPING[process.platform];
    43    if (!platform) {
    44      throw Error(
    45        "Installation is not supported for this platform: " + process.platform
    46      );
    47    }
    48  
    49    // Build the download url from package.json
    50    const pkgName = packageJson.name;
    51    const version = packageJson.version;
    52    const repo = packageJson.repository;
    53    const url = `https://github.com/${repo}/releases/download/v${version}/${pkgName}_${platform}_${arch}.tar.gz`;
    54  
    55    let binPath = path.join("bin", "supabase");
    56    if (platform == "windows") {
    57      binPath += ".exe";
    58    }
    59  
    60    return { binPath, url };
    61  };
    62  
    63  const errGlobal = `Installing Supabase CLI as a global module is not supported.
    64  Please use one of the supported package managers: https://github.com/Redstoneguy129/cli#install-the-cli
    65  `;
    66  
    67  /**
    68   * Reads the configuration from application's package.json,
    69   * downloads the binary from package url and stores at
    70   * ./bin in the package's root.
    71   *
    72   *  See: https://docs.npmjs.com/files/package.json#bin
    73   */
    74  async function main() {
    75    const yarnGlobal = JSON.parse(
    76      process.env.npm_config_argv || "{}"
    77    ).original?.includes("global");
    78    if (process.env.npm_config_global || yarnGlobal) {
    79      throw errGlobal;
    80    }
    81  
    82    const pkg = await readPackageJson();
    83    const { binPath, url } = parsePackageJson(pkg);
    84    const binDir = path.dirname(binPath);
    85    await fs.promises.mkdir(binDir, { recursive: true });
    86  
    87    // First we will Un-GZip, then we will untar.
    88    const ungz = zlib.createGunzip();
    89    const binName = path.basename(binPath);
    90    const untar = tar.x({ cwd: binDir }, [binName]);
    91  
    92    console.info("Downloading", url);
    93    const resp = await fetch(url);
    94    resp.body.pipe(ungz).pipe(untar);
    95    await new Promise((resolve, reject) => {
    96      untar.on("error", reject);
    97      untar.on("end", () => resolve());
    98    });
    99  
   100    // Link the binaries in postinstall to support yarn
   101    await binLinks({
   102      path: path.resolve("."),
   103      pkg: { ...pkg, bin: { [pkg.name]: binPath } },
   104    });
   105  
   106    // TODO: verify checksums
   107    console.info("Installed Supabase CLI successfully");
   108  }
   109  
   110  await main();