UNPKG

3.22 kBJavaScriptView Raw
1"use strict";
2
3const path = require('path');
4
5const spawn = require('cross-spawn');
6
7const glob = require('glob');
8
9const [executor, ignoredBin, script] = process.argv;
10
11if (script) {
12 spawnScript();
13} else {
14 const scriptsPath = path.join(__dirname, 'scripts/');
15 const scriptsAvailable = glob.sync(path.join(__dirname, 'scripts', '*')); // `glob.sync` returns paths with unix style path separators even on Windows.
16 // So we normalize it before attempting to strip out the scripts path.
17
18 const scriptsAvailableMessage = scriptsAvailable.map(path.normalize).map(s => s.replace(scriptsPath, '').replace(/__tests__/, '').replace(/\.js$/, '')).filter(Boolean).join('\n ').trim();
19 const fullMessage = `
20Usage: ${ignoredBin} [script] [--flags]
21
22Available Scripts:
23 ${scriptsAvailableMessage}
24
25Options:
26 All options depend on the script. Docs will be improved eventually, but for most scripts you can assume that the args you pass will be forwarded to the respective tool that's being run under the hood.
27
28May the force be with you.
29 `.trim();
30 console.log(`\n${fullMessage}\n`);
31}
32
33function getEnv() {
34 // this is required to address an issue in cross-spawn
35 // https://github.com/kentcdodds/kcd-scripts/issues/4
36 return Object.keys(process.env).filter(key => process.env[key] !== undefined).reduce((envCopy, key) => {
37 envCopy[key] = process.env[key];
38 return envCopy;
39 }, {
40 [`SCRIPTS_${script.toUpperCase()}`]: true
41 });
42}
43
44function spawnScript() {
45 // get all the arguments of the script and find the position of our script commands
46 const args = process.argv.slice(2);
47 const scriptIndex = args.findIndex(x => x === 'format' || x === 'lint' || x === 'pre-commit' || x === 'test' || x === 'validate' || x === 'build'); // Extract the node arguments so we can pass them to node later on
48
49 const buildCommand = scriptIndex === -1 ? args[0] : args[scriptIndex];
50 const nodeArgs = scriptIndex > 0 ? args.slice(0, scriptIndex) : [];
51
52 if (!buildCommand) {
53 throw new Error(`Unknown script "${script}".`);
54 }
55
56 const relativeScriptPath = path.join(__dirname, './scripts', buildCommand);
57 const scriptPath = attemptResolve(relativeScriptPath);
58
59 if (!scriptPath) {
60 throw new Error(`Unknown script "${script}".`);
61 } // Attempt to strt the script with the passed node arguments
62
63
64 const result = spawn.sync(executor, nodeArgs.concat(scriptPath).concat(args.slice(scriptIndex + 1)), {
65 stdio: 'inherit',
66 env: getEnv()
67 });
68
69 if (result.signal) {
70 handleSignal(result);
71 } else {
72 process.exit(result.status);
73 }
74}
75
76function handleSignal(result) {
77 if (result.signal === 'SIGKILL') {
78 console.log(`The script "${script}" failed because the process exited too early. ` + 'This probably means the system ran out of memory or someone called ' + '`kill -9` on the process.');
79 } else if (result.signal === 'SIGTERM') {
80 console.log(`The script "${script}" failed because the process exited too early. ` + 'Someone might have called `kill` or `killall`, or the system could ' + 'be shutting down.');
81 }
82
83 process.exit(1);
84}
85
86function attemptResolve(...resolveArgs) {
87 try {
88 return require.resolve(...resolveArgs);
89 } catch (error) {
90 return null;
91 }
92}
\No newline at end of file