nexe
Version:
Create a single executable out of your Node.js application
245 lines (237 loc) • 9.7 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.help = exports.normalizeOptions = exports.argv = exports.resolveEntry = exports.version = void 0;
const minimist_1 = __importDefault(require("minimist"));
const compiler_1 = require("./compiler");
const util_1 = require("./util");
const path_1 = require("path");
const target_1 = require("./target");
const os_1 = require("os");
const chalk_1 = __importDefault(require("chalk"));
const resolve_dependencies_1 = require("resolve-dependencies");
const caw = require('caw');
const c = process.platform === 'win32' ? chalk_1.default.constructor({ enabled: false }) : chalk_1.default;
exports.version = "5.0.0-beta.4";
const defaults = {
flags: [],
cwd: process.cwd(),
fs: true,
configure: [],
mangle: true,
make: [],
targets: [],
vcBuild: util_1.isWindows ? ['nosign', 'release'] : [],
enableNodeCli: false,
build: false,
bundle: true,
patches: [],
plugins: [],
remote: 'https://github.com/nexe/nexe/releases/download/v3.3.3/',
};
const alias = {
i: 'input',
o: 'output',
v: 'version',
a: 'asset',
t: 'target',
b: 'build',
n: 'name',
r: 'resource',
p: 'python',
f: 'flag',
c: 'configure',
m: 'make',
h: 'help',
l: 'loglevel',
'fake-argv': 'fakeArgv',
'gh-token': 'ghToken',
};
const argv = (0, minimist_1.default)(process.argv, { alias, default: Object.assign({}, defaults) });
exports.argv = argv;
let help = `
${c.bold('nexe <entry-file> [options]')}
${c.underline.bold('Options:')}
-i --input -- application entry point
-o --output -- path to output file
-t --target -- node version description
-n --name -- main app module name
-r --resource -- *embed files (glob) within the binary
--remote -- alternate location (URL) to download pre-built base (nexe) binaries from
--plugin -- extend nexe runtime behavior
${c.underline.bold('Building from source:')}
-b --build -- build from source
-p --python -- python3 (as python) executable path
-f --flag -- *v8 flags to include during compilation
-c --configure -- *arguments to the configure step
-m --make -- *arguments to the make/build step
--patch -- module with middleware default export for adding a build patch
--no-mangle -- used when generating base binaries, or when patching _third_party_main manually
--snapshot -- path to a warmup snapshot
--ico -- file name for alternate icon file (windows)
--rc-* -- populate rc file options (windows)
--sourceUrl -- pass an alternate source (node.tar.gz) url
--enableNodeCli -- enable node cli enforcement (blocks app cli)
${c.underline.bold('Other options:')}
--bundle -- custom bundling module with 'createBundle' export
--temp -- temp file storage default '~/.nexe'
--cwd -- set the current working directory for the command
--fake-argv -- fake argv[1] with entry file
--clean -- force download of sources
--silent -- disable logging
--verbose -- set logging to verbose
-* variable key name * option can be used more than once`.trim();
exports.help = help;
exports.help = help = os_1.EOL + help + os_1.EOL;
function flatten(...args) {
return [].concat(...args).filter((x) => x);
}
/**
* Extract keys such as { "rc-CompanyName": "Node.js" } to
* { CompanyName: "Node.js" }
* @param {*} match
* @param {*} options
*/
function extractCliMap(match, options) {
return Object.keys(options)
.filter((x) => match.test(x))
.reduce((map, option) => {
const key = option.split('-')[1];
map[key] = options[option];
delete options[option];
return map;
}, {});
}
function extractLogLevel(options) {
if (options.loglevel)
return options.loglevel;
if (options.silent)
return 'silent';
if (options.verbose)
return 'verbose';
return 'info';
}
function isName(name) {
return name && name !== 'index' && name !== util_1.STDIN_FLAG;
}
function extractName(options) {
let name = options.name;
//try and use the input filename as the output filename if its not index
if (!isName(name) && typeof options.input === 'string') {
name = (0, path_1.basename)(options.input).replace((0, path_1.extname)(options.input), '');
}
//try and use the directory as the filename
if (!isName(name) && (0, path_1.basename)(options.cwd)) {
name = (0, path_1.basename)(options.cwd);
}
return name.replace(/\.exe$/, '');
}
function padRelative(input) {
let prefix = '';
if (!input.startsWith('.')) {
prefix = './';
}
return prefix + input;
}
function isEntryFile(filename) {
return Boolean(filename && !(0, path_1.isAbsolute)(filename));
}
function resolveEntry(input, cwd, maybeEntry, bundle) {
let result = null;
if (input === '-' || maybeEntry === '-') {
return util_1.STDIN_FLAG;
}
if (input && (0, path_1.isAbsolute)(input)) {
return input;
}
if (input) {
const inputPath = padRelative(input);
result = (0, resolve_dependencies_1.resolveSync)(cwd, inputPath);
}
if (isEntryFile(maybeEntry) && (!result || !result.absPath)) {
const inputPath = padRelative(maybeEntry);
result = (0, resolve_dependencies_1.resolveSync)(cwd, inputPath);
}
if (!process.stdin.isTTY && (!result || !result.absPath) && bundle === defaults.bundle) {
return util_1.STDIN_FLAG;
}
if (!result || !result.absPath) {
result = (0, resolve_dependencies_1.resolveSync)(cwd, '.');
}
if (!result.absPath) {
throw new compiler_1.NexeError(`Entry file "${input || ''}" not found!`);
}
return result.absPath;
}
exports.resolveEntry = resolveEntry;
function isCli(options) {
return argv === options;
}
function normalizeOptions(input) {
const options = Object.assign({}, defaults, input);
const opts = options;
const cwd = (options.cwd = (0, path_1.resolve)(options.cwd));
options.temp = options.temp
? (0, path_1.resolve)(cwd, options.temp)
: process.env.NEXE_TEMP || (0, path_1.join)((0, os_1.homedir)(), '.nexe');
const maybeEntry = isCli(input) ? argv._[argv._.length - 1] : undefined;
options.input = resolveEntry(options.input, cwd, maybeEntry, options.bundle);
options.enableStdIn = isCli(input) && options.input === util_1.STDIN_FLAG;
options.name = extractName(options);
options.loglevel = extractLogLevel(options);
options.flags = flatten(opts.flag, options.flags);
options.targets = flatten(opts.target, options.targets).map(target_1.getTarget);
if (!options.targets.length) {
options.targets.push((0, target_1.getTarget)());
}
options.ghToken = options.ghToken || process.env.GITHUB_TOKEN || '';
options.make = flatten(util_1.isWindows ? options.vcBuild : options.make);
options.configure = flatten(options.configure);
options.resources = flatten(opts.resource, options.resources);
if (!options.remote.endsWith('/')) {
options.remote += '/';
}
options.downloadOptions = options.downloadOptions || {};
options.downloadOptions.headers = options.downloadOptions.headers || {};
options.downloadOptions.headers['User-Agent'] = 'nexe (https://www.npmjs.com/package/nexe)';
options.downloadOptions.agent = process.env.HTTPS_PROXY
? caw(process.env.HTTPS_PROXY, { protocol: 'https' })
: options.downloadOptions.agent || require('https').globalAgent;
options.downloadOptions.rejectUnauthorized = process.env.NODE_TLS_REJECT_UNAUTHORIZED
? false
: true;
options.rc = options.rc || extractCliMap(/^rc-.*/, options);
options.output =
options.targets[0].platform === 'windows'
? `${(options.output || options.name).replace(/\.exe$/, '')}.exe`
: `${options.output || options.name}`;
options.output = (0, path_1.resolve)(cwd, options.output);
const requireDefault = (x) => {
if (typeof x === 'string') {
return require(x).default;
}
return x;
};
options.mangle = 'mangle' in opts ? opts.mangle : true;
options.plugins = flatten(opts.plugin, options.plugins).map(requireDefault);
options.patches = flatten(opts.patch, options.patches).map(requireDefault);
if ((!options.mangle && !options.bundle) || options.patches.length) {
options.build = true;
}
if (options.build) {
const { arch } = options.targets[0];
if (util_1.isWindows) {
options.make = Array.from(new Set(options.make.concat(arch)));
}
else {
options.configure = Array.from(new Set(options.configure.concat([`--dest-cpu=${arch}`])));
}
}
Object.keys(alias)
.filter((k) => k !== 'rc')
.forEach((x) => delete opts[x]);
return options;
}
exports.normalizeOptions = normalizeOptions;
;