110 lines
3.0 KiB
JavaScript
Executable File
110 lines
3.0 KiB
JavaScript
Executable File
import {fork} from 'child_process';
|
|
import {join, resolve, sep} from 'path';
|
|
|
|
import {Command} from 'commander';
|
|
import D from 'debug';
|
|
|
|
import Flecks from './server/flecks';
|
|
|
|
const {
|
|
FLECKS_ROOT = process.cwd(),
|
|
} = process.env;
|
|
|
|
const debug = D('@flecks/core/cli');
|
|
|
|
// Guarantee local node_modules path.
|
|
const defaultNodeModules = resolve(join(FLECKS_ROOT, 'node_modules'));
|
|
const nodePathSeparator = '/' === sep ? ':' : ';';
|
|
let updatedNodePath;
|
|
if (!process.env.NODE_PATH) {
|
|
updatedNodePath = defaultNodeModules;
|
|
}
|
|
else {
|
|
const parts = process.env.NODE_PATH.split(nodePathSeparator);
|
|
if (!parts.some((part) => resolve(part) === defaultNodeModules)) {
|
|
parts.push(defaultNodeModules);
|
|
updatedNodePath = parts.join(nodePathSeparator);
|
|
}
|
|
}
|
|
// Guarantee symlink preservation for linked flecks.
|
|
const updateSymlinkPreservation = !process.env.NODE_PRESERVE_SYMLINKS;
|
|
|
|
const environmentUpdates = (
|
|
updatedNodePath
|
|
|| updateSymlinkPreservation
|
|
)
|
|
? {
|
|
NODE_PATH: updatedNodePath,
|
|
NODE_PRESERVE_SYMLINKS: 1,
|
|
}
|
|
: undefined;
|
|
if (environmentUpdates) {
|
|
debug('updating environment, forking with %O...', environmentUpdates);
|
|
const forkOptions = {
|
|
env: {
|
|
...process.env,
|
|
...environmentUpdates,
|
|
DEBUG_COLORS: 'true',
|
|
},
|
|
stdio: 'inherit',
|
|
};
|
|
fork(__filename, process.argv.slice(2), forkOptions)
|
|
.on('exit', (code, signal) => {
|
|
process.exitCode = code;
|
|
process.exit(signal);
|
|
});
|
|
}
|
|
else {
|
|
// Asynchronous command process code forwarding.
|
|
const forwardProcessCode = (fn) => async (...args) => {
|
|
const child = await fn(...args);
|
|
if ('object' !== typeof child) {
|
|
debug('action returned code %d', child);
|
|
process.exitCode = child;
|
|
return;
|
|
}
|
|
const reject = (error) => {
|
|
// eslint-disable-next-line no-console
|
|
console.error(error);
|
|
process.exitCode = child.exitCode || 1;
|
|
};
|
|
child.on('error', reject);
|
|
child.on('exit', (code) => {
|
|
child.off('error', reject);
|
|
debug('action exited with code %d', code);
|
|
process.exitCode = code;
|
|
});
|
|
};
|
|
// Initialize Commander.
|
|
const program = new Command();
|
|
program.enablePositionalOptions();
|
|
// Bootstrap.
|
|
debug('bootstrapping flecks...');
|
|
const flecks = Flecks.bootstrap();
|
|
debug('bootstrapped');
|
|
// Register commands.
|
|
const commands = flecks.invokeReduce('@flecks/core/commands', undefined, undefined, program);
|
|
const keys = Object.keys(commands);
|
|
for (let i = 0; i < keys.length; ++i) {
|
|
const {
|
|
action,
|
|
args = [],
|
|
description,
|
|
name = keys[i],
|
|
options = [],
|
|
} = commands[keys[i]];
|
|
debug('adding command %s...', name);
|
|
const cmd = program.command(name);
|
|
cmd.description(description);
|
|
for (let i = 0; i < args.length; ++i) {
|
|
cmd.addArgument(args[i]);
|
|
}
|
|
for (let i = 0; i < options.length; ++i) {
|
|
cmd.option(...options[i]);
|
|
}
|
|
cmd.action(forwardProcessCode(action));
|
|
}
|
|
// Parse commandline.
|
|
program.parse(process.argv);
|
|
}
|