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();