1 | "use strict";
|
2 |
|
3 | const path = require('path');
|
4 |
|
5 | const spawn = require('cross-spawn');
|
6 |
|
7 | const glob = require('glob');
|
8 |
|
9 | const [executor, ignoredBin, script] = process.argv;
|
10 |
|
11 | if (script) {
|
12 | spawnScript();
|
13 | } else {
|
14 | const scriptsPath = path.join(__dirname, 'scripts/');
|
15 | const scriptsAvailable = glob.sync(path.join(__dirname, 'scripts', '*'));
|
16 |
|
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 = `
|
20 | Usage: ${ignoredBin} [script] [--flags]
|
21 |
|
22 | Available Scripts:
|
23 | ${scriptsAvailableMessage}
|
24 |
|
25 | Options:
|
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 |
|
28 | May the force be with you.
|
29 | `.trim();
|
30 | console.log(`\n${fullMessage}\n`);
|
31 | }
|
32 |
|
33 | function getEnv() {
|
34 |
|
35 |
|
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 |
|
44 | function spawnScript() {
|
45 |
|
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');
|
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 | }
|
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 |
|
76 | function 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 |
|
86 | function attemptResolve(...resolveArgs) {
|
87 | try {
|
88 | return require.resolve(...resolveArgs);
|
89 | } catch (error) {
|
90 | return null;
|
91 | }
|
92 | } |
\ | No newline at end of file |