Skip to content

Instantly share code, notes, and snippets.

@ThisIsMissEm
Created September 27, 2020 22:51
Show Gist options
  • Save ThisIsMissEm/9c853fd9282787dfa306552d323d168e to your computer and use it in GitHub Desktop.
Save ThisIsMissEm/9c853fd9282787dfa306552d323d168e to your computer and use it in GitHub Desktop.
entrypoint.js is the entrypoint for the CLI and lives in bin/ and is tied to a scripts entry. bootstrap.js figures out the conditions under which we are executing, and extracts the argv variables from the command run in the terminal, so you can pass them to your cli.js file.
import path from 'path';
const debug = require('debug')('cli:bootstrap');
debug({
npm_lifecycle_script: process.env.npm_lifecycle_script,
npm_config_argv: process.env.npm_config_argv,
npm_config_username: process.env.npm_config_username,
});
/*
A quick explanation of what all this code actually does:
We have a postinstall script, that we wish to run when you do a "general install",
i.e., run `$ yarn` or `$ npm install`, however, yarn isn't like npm in how it
executes the postinstall script, instead, yarn executes postinstall when adding
packages to your project, which means if you're working on the script, add a
dependency, and then try to install it with `$ yarn add --dev something`, then
your script will try to execute, typescript will fail to compile, and everything
goes tits up and your package doesn't end up installed because postinstall crashed.
So essentially all this code below tries to figure out if you're calling the CLI
directly, or from npm/yarn, if from a package manager, then it tries to figure out
if we're actually doing a general install and not trying to add or remove a package
from the project.
*/
interface BootstrapSuccess {
runner: string;
argv: string[];
}
interface BootstrapFailure {
reason: 'CI' | 'BY_PASS_POSTINSTALL';
}
type BootstrapResult = BootstrapSuccess | BootstrapFailure;
export default function bootstrap(): BootstrapResult {
let runner = path.relative(process.cwd(), process.argv[1]);
if (process.env.npm_lifecycle_script && process.env.npm_config_user_agent) {
runner = /yarn/.test(process.env.npm_config_user_agent) ? 'yarn' : 'npm';
}
let fromGeneralInstall = false;
let packageManagerArgs = [];
try {
packageManagerArgs = JSON.parse(process.env.npm_config_argv!);
} catch (err) {
// ignored
}
if (runner === 'yarn') {
// Only:
// $ yarn
// $ yarn install
// Not:
// $ yarn add
// $ yarn remove
// $ yarn install --production
// $ yarn --production
fromGeneralInstall =
// $ yarn
packageManagerArgs.cooked.length === 0 ||
// $ yarn install
(packageManagerArgs.cooked[0] === 'install' &&
packageManagerArgs.cooked.length === 1 &&
(packageManagerArgs.original.length === 0 ||
packageManagerArgs.original[0] === 'install'));
}
if (runner === 'npm') {
// only:
// $ npm install
// $ npm i
fromGeneralInstall =
(packageManagerArgs[0] === 'install' || packageManagerArgs[0] === 'i') &&
packageManagerArgs.length === 1;
}
debug({
fromGeneralInstall,
runner,
packageManagerArgs,
argv: process.argv,
});
// Short-circuit under certain conditions if doing --postinstall:
if (process.argv.includes('--postinstall')) {
if (!fromGeneralInstall) {
debug('Not running postinstall, not from general install');
return { reason: 'BY_PASS_POSTINSTALL' };
}
if (process.env.CI === 'true') {
debug('Not running postinstall on CI');
return { reason: 'CI' };
}
}
return {
runner,
argv: process.argv.slice(2),
};
}
#!/usr/bin/env node
const bootstrap = require('../dist/bootstrap.js').default;
const { reason, runner, argv } = bootstrap();
if (reason === 'CI' || reason === 'BY_PASS_POSTINSTALL') {
process.exit(0);
}
// dist/cli is just a module exporting a `run` function:
// export function run(runner: string, argv: string[]): Promise<void>
require('../dist/cli.js')
.run(runner, argv)
.then(
() => {
process.exit(0);
},
() => {
process.exit(1);
},
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment