diff --git a/Jenkinsfile b/Jenkinsfile index 972dea47..57ff0be7 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -6,6 +6,11 @@ pipeline { sh 'npm install --verbose' } } + stage('Build') { + steps { + sh 'npm run build' // Running build first, since "bin" requires reference to the "dist" folder + } + } stage('Run lint') { steps { ansiColor('xterm') { @@ -13,11 +18,6 @@ pipeline { } } } - stage('Build') { - steps { - sh 'npm run build' - } - } stage('Run tests') { steps { ansiColor('xterm') { diff --git a/bin/.eslintrc.json b/bin/.eslintrc.json deleted file mode 100644 index 93bba791..00000000 --- a/bin/.eslintrc.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "env": { - "es6": false - }, - "rules": { - "no-var": "off" - } -} diff --git a/bin/lisky b/bin/lisky index 62606f04..74f455ed 100755 --- a/bin/lisky +++ b/bin/lisky @@ -1,4 +1,28 @@ #!/usr/bin/env node +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _os = require('os'); + +var _os2 = _interopRequireDefault(_os); + +var _lockfile = require('lockfile'); + +var _lockfile2 = _interopRequireDefault(_lockfile); + +var _semver = require('semver'); + +var _semver2 = _interopRequireDefault(_semver); + +var _package = require('../package.json'); + +var _package2 = _interopRequireDefault(_package); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + /* * LiskHQ/lisky * Copyright © 2017 Lisk Foundation @@ -14,69 +38,96 @@ * Removal or modification of this copyright notice is prohibited. * */ -var os = require('os'); -var lockfile = require('lockfile'); -var semver = require('semver'); - -var packageJSON = require('../package.json'); - -var configLockfilePath; -var lisky; -var execFile; -var firstCommandWords; var nonInteractiveLiskyArg = process.argv[1]; var nonInteractiveCommandArg = process.argv[2]; -var nonInteractiveOptions; -var commandArgIsFilePath = false; - -process.env.LISKY_CONFIG_DIR = process.env.LISKY_CONFIG_DIR || `${os.homedir()}/.lisky`; -configLockfilePath = `${process.env.LISKY_CONFIG_DIR}/config.lock`; - -process.env.NON_INTERACTIVE_MODE = !(nonInteractiveLiskyArg.endsWith('lisky') && process.argv.length === 2); - -function exit(code) { - process.exit(code || 0); -} - -if (!semver.satisfies(process.version, packageJSON.engines.node)) { - console.error('\x1b[31m', `ERROR: Requires Node.js version ${semver.clean(packageJSON.engines.node)}, but was started with version ${semver.clean(process.version)}.`, '\x1b[0m'); - exit(); -} - -// eslint-disable-next-line default-case -switch (process.argv[2]) { -case 'clean': - console.warn('\x1b[33m', 'WARNING: Attempting to remove configuration lockfile. I hope you know what you’re doing.', '\x1b[0m'); - lockfile.unlockSync(configLockfilePath); - exit(); - break; -case '--version': -case '-v': - console.info(packageJSON.version); - exit(); - break; -default: - // continue... -} - -lisky = require('../dist').default; -execFile = require('../dist/exec_file').default; - -// eslint-disable-next-line no-underscore-dangle -firstCommandWords = lisky.commands.map(c => c._name.split(' ')[0]); - -if (firstCommandWords.indexOf(nonInteractiveCommandArg) === -1) { - commandArgIsFilePath = true; +var nonInteractiveOptions = process.argv.slice(3); + +var exit = function exit(code) { + return process.exit(code || 0); +}; + +var printWarning = function printWarning(message) { + return console.warn('\x1b[33m', message, '\x1b[0m'); +}; +var printError = function printError(message) { + return console.error('\x1b[31m', message, '\x1b[0m'); +}; +var printVersion = function printVersion(version) { + return console.info(version); +}; + +var execClean = function execClean(path) { + printWarning('WARNING: Attempting to remove configuration lockfile. I hope you know what you’re doing.'); + _lockfile2.default.unlockSync(path); +}; + +var isUnknownCommand = function isUnknownCommand(liskyInstance, command) { + // eslint-disable-next-line no-underscore-dangle + var firstCommandWords = liskyInstance.commands.map(function (c) { + return c._name.split(' ')[0]; + }); + return firstCommandWords.indexOf(command) === -1; +}; + +var setEnvironment = function setEnvironment() { + process.env.LISKY_CONFIG_DIR = process.env.LISKY_CONFIG_DIR || _os2.default.homedir() + '/.lisky'; + + process.env.NON_INTERACTIVE_MODE = !(nonInteractiveLiskyArg.endsWith('lisky') && process.argv.length === 2); +}; + +var checkNodeVersion = function checkNodeVersion(expected, actual) { + if (!_semver2.default.satisfies(actual, expected)) { + throw new Error('ERROR: Requires Node.js version ' + _semver2.default.clean(expected) + ', but was started with version ' + _semver2.default.clean(actual) + '.'); + } +}; + +var handleBasicCommands = function handleBasicCommands(command, lockFilePath, version) { + switch (command) { + case 'clean': + execClean(lockFilePath); + return true; + case '--version': + case '-v': + printVersion(version); + return true; + default: + return false; + } +}; + +var getLiskyInstanceByMode = function getLiskyInstanceByMode(liskyInstance, nonInteractiveMode) { + return nonInteractiveMode ? liskyInstance.parse(process.argv) : liskyInstance; +}; + +var run = function run() { + setEnvironment(); try { - nonInteractiveOptions = process.argv.slice(3); - execFile(lisky, nonInteractiveCommandArg, nonInteractiveOptions, exit); + checkNodeVersion(_package2.default.engines.node, process.version); } catch (error) { - commandArgIsFilePath = false; + printError(error.message); + exit(); + } + + if (handleBasicCommands(nonInteractiveCommandArg, process.env.LISKY_CONFIG_DIR + '/config.lock', _package2.default.version)) { + exit(); } -} -if (!commandArgIsFilePath) { - module.exports = process.env.NON_INTERACTIVE_MODE === 'true' - ? (lisky.parse(process.argv)) - : lisky; -} + // Dynamically required, otherwise it starts the CLI before handling above codes + // eslint-disable-next-line global-require + var lisky = require('../dist').default; + // eslint-disable-next-line global-require + var execFile = require('../dist/exec_file').default; + if (isUnknownCommand(lisky, nonInteractiveCommandArg)) { + try { + // "execFile" throws error when it "nonInteractiveCommandArg" is not a filepath + return execFile(lisky, nonInteractiveCommandArg, nonInteractiveOptions, exit); + } catch (error) { + return getLiskyInstanceByMode(lisky, process.env.NON_INTERACTIVE_MODE === 'true'); + } + } + return getLiskyInstanceByMode(lisky, process.env.NON_INTERACTIVE_MODE === 'true'); +}; + +run(); + +exports.default = run; diff --git a/bin/lisky.js b/bin/lisky.js new file mode 100644 index 00000000..f79e2cb8 --- /dev/null +++ b/bin/lisky.js @@ -0,0 +1,131 @@ +#!/usr/bin/env node +/* + * LiskHQ/lisky + * Copyright © 2017 Lisk Foundation + * + * See the LICENSE file at the top-level directory of this distribution + * for licensing information. + * + * Unless otherwise agreed in a custom licensing agreement with the Lisk Foundation, + * no part of this software, including this file, may be copied, modified, + * propagated, or distributed except according to the terms contained in the + * LICENSE file. + * + * Removal or modification of this copyright notice is prohibited. + * + */ +import os from 'os'; +import lockfile from 'lockfile'; +import semver from 'semver'; +import packageJSON from '../package.json'; + +const nonInteractiveLiskyArg = process.argv[1]; +const nonInteractiveCommandArg = process.argv[2]; +const nonInteractiveOptions = process.argv.slice(3); + +const exit = code => process.exit(code || 0); + +const printWarning = message => console.warn('\x1b[33m', message, '\x1b[0m'); +const printError = message => console.error('\x1b[31m', message, '\x1b[0m'); +const printVersion = version => console.info(version); + +const execClean = path => { + printWarning( + 'WARNING: Attempting to remove configuration lockfile. I hope you know what you’re doing.', + ); + lockfile.unlockSync(path); +}; + +const isUnknownCommand = (liskyInstance, command) => { + const firstCommandWords = liskyInstance.commands.map( + // eslint-disable-next-line no-underscore-dangle + c => c._name.split(' ')[0], + ); + return firstCommandWords.indexOf(command) === -1; +}; + +const setEnvironment = () => { + process.env.LISKY_CONFIG_DIR = + process.env.LISKY_CONFIG_DIR || `${os.homedir()}/.lisky`; + + process.env.NON_INTERACTIVE_MODE = !( + nonInteractiveLiskyArg.endsWith('lisky') && process.argv.length === 2 + ); +}; + +const checkNodeVersion = (expected, actual) => { + if (!semver.satisfies(actual, expected)) { + throw new Error( + `ERROR: Requires Node.js version ${semver.clean( + expected, + )}, but was started with version ${semver.clean(actual)}.`, + ); + } +}; + +const handleBasicCommands = (command, lockFilePath, version) => { + switch (command) { + case 'clean': + execClean(lockFilePath); + return true; + case '--version': + case '-v': + printVersion(version); + return true; + default: + return false; + } +}; + +const getLiskyInstanceByMode = (liskyInstance, nonInteractiveMode) => + nonInteractiveMode ? liskyInstance.parse(process.argv) : liskyInstance; + +const run = () => { + setEnvironment(); + try { + checkNodeVersion(packageJSON.engines.node, process.version); + } catch (error) { + printError(error.message); + exit(); + } + + if ( + handleBasicCommands( + nonInteractiveCommandArg, + `${process.env.LISKY_CONFIG_DIR}/config.lock`, + packageJSON.version, + ) + ) { + exit(); + } + + // Dynamically required, otherwise it starts the CLI before handling above codes + // eslint-disable-next-line global-require + const lisky = require('../dist').default; + // eslint-disable-next-line global-require + const execFile = require('../dist/exec_file').default; + if (isUnknownCommand(lisky, nonInteractiveCommandArg)) { + try { + // "execFile" throws error when it "nonInteractiveCommandArg" is not a filepath + return execFile( + lisky, + nonInteractiveCommandArg, + nonInteractiveOptions, + exit, + ); + } catch (error) { + return getLiskyInstanceByMode( + lisky, + process.env.NON_INTERACTIVE_MODE === 'true', + ); + } + } + return getLiskyInstanceByMode( + lisky, + process.env.NON_INTERACTIVE_MODE === 'true', + ); +}; + +run(); + +export default run; diff --git a/package.json b/package.json index be1aa1f7..2539c094 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "scripts": { "start": "babel-node src/index.js", "format": - "prettier --write \"./*.{js,json,md}\" \"{docs,src,test}{,/**}/*.{js,json,md}\"", + "prettier --write \"./*.{js,json,md}\" \"{bin,docs,src,test}{,/**}/*.{js,json,md}\"", "lint": "eslint .", "lint:fix": "npm run lint -- --fix", "test": @@ -44,7 +44,7 @@ "cover:test": "NODE_ENV=test nyc --include \"test/**\" --exclude \"**/node_modules/** coverage/**\" mocha test/specs", "prebuild": "if test -d dist; then rm -r dist; fi", - "build": "babel src -d dist", + "build": "babel src -d dist && babel bin/lisky.js -o bin/lisky", "precommit": "lint-staged && npm run lint", "prepush": "npm run lint && npm test", "prepublishOnly":