Skip to content

Commit

Permalink
Feat(bin): allow ntr binary to be downloaded from releases via npm
Browse files Browse the repository at this point in the history
  • Loading branch information
Ziothh committed Nov 15, 2023
1 parent 6ec1c74 commit 9fa9fba
Show file tree
Hide file tree
Showing 11 changed files with 357 additions and 84 deletions.
1 change: 1 addition & 0 deletions lib/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npm
1 change: 1 addition & 0 deletions lib/.npmignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
*
!npm/
!package.json
125 changes: 125 additions & 0 deletions lib/bin/binary.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import childProcess from 'child_process';
import fs from 'fs';
import path from 'path';

// const axios = require("axios");
import tar from 'tar';
// const rimraf = require("rimraf");

function error(msg: string, cause?: Error) {
console.error(msg, ...(cause ? [cause] : []));
process.exit(1);
};

export default class Binary {
private readonly installDirectory: string;
private readonly binaryPath: string;

constructor(
public readonly name: string,
public readonly url: string | URL,
config?: {
installDirectory: string
}
) {
try {
new URL(url);
} catch (e: any) {
error(`The given URL "${e}" is not valid`, e);
}

this.url = url;
this.name = name;
this.installDirectory =
config?.installDirectory || path.join(__dirname, "node_modules", ".bin");

if (!fs.existsSync(this.installDirectory)) {
fs.mkdirSync(this.installDirectory, { recursive: true });
}

this.binaryPath = path.join(this.installDirectory, this.name);
}

private exists() {
return fs.existsSync(this.binaryPath);
}

public async install(suppressLogs = false) {
if (this.exists()) {
if (!suppressLogs) {
console.error(
`${this.name} is already installed, skipping installation.`
);
}
return Promise.resolve();
}

if (fs.existsSync(this.installDirectory)) {
childProcess.execSync(`rm -rf ${this.installDirectory}`);
}

fs.mkdirSync(this.installDirectory, { recursive: true });

if (!suppressLogs) {
console.error(`Downloading release from ${this.url}`);
}

const tarFileLocation = path.resolve(this.installDirectory, this.url.toString().split('/').pop() ?? 'download.tar.gz');
return await fetch(this.url)
.then(res => res.arrayBuffer())
.then(blob => {
// const file = new File([blob], tarFileLocation)

fs.appendFileSync(tarFileLocation, new Uint8Array(blob));
// console.log('Wrote tar file to ', tarFileLocation);




return new Promise((res, rej) => {
const stream = fs.createReadStream(tarFileLocation).pipe(
tar.x({
// strip: 1,
C: this.installDirectory, // alias for cwd:'some-dir', also ok
})
);

// console.log('Doing stream things');

stream.on('finish', res);
stream.on('error', rej);
})
.then(() => {
childProcess.spawnSync(`chmod +x ${this.binaryPath}`);
fs.unlinkSync(tarFileLocation);
// console.log('Delete tar file');
});
});
}

public run() {
const promise = !this.exists()
? this.install(true)
: Promise.resolve();

promise
.then(() => {
const [, , ...args] = process.argv;

const result = childProcess.spawnSync(this.binaryPath, args, {
cwd: process.cwd(),
stdio: 'inherit'
});

if (result.error) {
error(result.error as any);
}

process.exit(result.status ?? 0);
})
.catch(e => {
error(e.message);
process.exit(1);
});
}
}
41 changes: 0 additions & 41 deletions lib/bin/index.ts

This file was deleted.

8 changes: 8 additions & 0 deletions lib/bin/install.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { getBinary } from "./shared.mjs";

const install = () => {
const binary = getBinary();
binary.install().then(() => {});
};

install();
9 changes: 9 additions & 0 deletions lib/bin/run.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env node
import { getBinary } from "./shared.mjs";

const run = () => {
const binary = getBinary();
binary.run();
};

run();
70 changes: 36 additions & 34 deletions lib/bin/shared.cts → lib/bin/shared.mts
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
const { Binary } = require("binary-install") as typeof import('binary-install');
const os = require("os") as typeof import('os');
const path = require("path") as typeof import('path');
const cTable = require("console.table") as typeof import('console')['table'];
const PACKAGE_JSON = require("./package.json") as typeof import('../package.json');
// @ts-ignore
import Binary from './binary.mjs';
// import { Binary } from 'binary-install';
import path from 'path';
import os from 'os';
import fs from 'fs';
import { fileURLToPath } from 'url';

function error(msg: string): never {
console.error(msg);
process.exit(1);
};

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const PACKAGE_JSON: typeof import('../package.json') = JSON.parse(
fs.readFileSync(path.resolve(__dirname, '../../package.json'), {
encoding: 'utf8'
})
);


// type Architecture = 'x64' | 'arm64'

// - build: linux gnu x64
Expand Down Expand Up @@ -66,43 +77,34 @@ const getPlatformMetadata = () => {
const type = os.type();
const architecture = os.arch();

for (let supportedPlatform of supportedPlatforms) {
if (
type === supportedPlatform.TYPE &&
architecture === supportedPlatform.ARCHITECTURE
) {
return supportedPlatform;
}
}
const platform = supportedPlatforms.find(x => type === x.TYPE && architecture === x.ARCHITECTURE) ?? null;

error(
`Platform with type "${type}" and architecture "${architecture}" is not supported by ${name}.\nYour system must be one of the following:\n\n${cTable.getTable(
supportedPlatforms
)}`
if (platform === null) return error(
`Platform with type "${type}" and architecture "${architecture}" is not supported by ${PACKAGE_JSON.name}.\nYour system must be one of the following:\n\n${JSON.stringify(supportedPlatforms, null, 2)}`
);

return platform
};

const getBinary = () => {
export const getBinary = () => {
const platformMetadata = getPlatformMetadata();
// the url for this binary is constructed from values in `package.json`
// https://github.com/EverlastingBugstopper/binary-install/releases/download/v1.0.0/binary-install-example-v1.0.0-x86_64-apple-darwin.tar.gz
const url = `${repository.url}/releases/download/rust_v${version}/${name}-v${version}-${platformMetadata.RUST_TARGET}.tar.gz`;
return new Binary(platformMetadata.BINARY_NAME, url, version, {
installDirectory: join(__dirname, "node_modules", ".bin")
});
};
const url = `${PACKAGE_JSON.repository.url}/releases/download/v${PACKAGE_JSON.version}/${'ntr'}-${platformMetadata.RUST_TARGET}.tar.gz`;
// const url = `https://github.com/Ziothh/ntr/releases/download/v0.0.0/ntr-x86_64-unknown-linux-musl.tar.gz`;
const installDirectory = path.join(__dirname, "../../node_modules", ".bin");

const run = () => {
const binary = getBinary();
binary.run();
};
// console.log('Binary dir: ', ))
// console.log('\n\n\n\n');
// console.log(`Fetching from "${url}"`);
// console.log(`installDirectory: "${installDirectory}"`);
// console.log("wgwefewfewfweF: ", __dirname);
// console.log('\n\n\n\n');

const install = () => {
const binary = getBinary();
binary.install();
return new Binary(platformMetadata.BINARY_NAME, url, {
// installDirectory: path.join(process.cwd(), "node_modules", ".bin")
// installDirectory: path.join(__dirname, ".bin")
installDirectory,
});
};

module.exports = {
install,
run
};
8 changes: 8 additions & 0 deletions lib/bin/uninstall.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { getBinary } from "./shared.mjs";

const uninstall = () => {
const binary = getBinary();
// binary.uninstall();
};

uninstall();
14 changes: 11 additions & 3 deletions lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,29 @@
"files": [
"./npm"
],
"bin": "./npm/bin/index.js",
"bin": {
"ntr": "npm/bin/run.mjs"
},
"scripts": {
"postinstall": "node npm/bin/install.cjs",
"postuninstall": "node npm/bin/uninstall.cjs"
"build": "tsc && (rm -rf npm/package.json || '')",
"postinstall": "node npm/bin/install.mjs",
"postuninstall": "node npm/bin/uninstall.mjs"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@types/node": "20",
"@types/react": "^18.2.20",
"@types/react-dom": "^18.2.7",
"@types/tar": "^6.1.9",
"@types/tar-stream": "^3.1.3",
"binary-install": "^1.1.0",
"next": "^13.4.13",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"tar": "^6.2.0",
"tar-stream": "^3.1.6",
"typescript": "^5.2.2"
},
"peerDependencies": {
Expand Down
12 changes: 6 additions & 6 deletions lib/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"outDir": "dist",
"outDir": "npm",
"target": "ESNext",
"lib": [
"dom",
Expand All @@ -12,7 +12,8 @@
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"noEmit": false,
"declaration": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
Expand All @@ -23,10 +24,9 @@
"noUncheckedIndexedAccess": true
},
"include": [
"**/*.ts",
"bin/*.{ts, cts, mts}",
"**/*.tsx",
"../playground/generated/routes.ts"
"./**/*.ts",
"./bin/*.mts",
"./**/*.tsx"
],
"exclude": [
"node_modules",
Expand Down
Loading

0 comments on commit 9fa9fba

Please sign in to comment.