├── test ├── test.js ├── test-sub.js └── alias.unit.js ├── .gitignore ├── .travis.yml ├── package.json ├── LICENSE ├── index.js └── README.md /test/test.js: -------------------------------------------------------------------------------- 1 | // DO NOT DELETE 2 | -------------------------------------------------------------------------------- /test/test-sub.js: -------------------------------------------------------------------------------- 1 | // DO NOT DELETE 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | node_modules/ 3 | npm-debug.log 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "4.1" 4 | - "4.0" 5 | - "0.12" 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-alias", 3 | "version": "1.0.4", 4 | "description": "Alias the long version of a command to the short version, with optional messaging.", 5 | "main": "index.js", 6 | "engines": { 7 | "node": ">=0.10" 8 | }, 9 | "scripts": { 10 | "test": "mocha" 11 | }, 12 | "repository": "justinhelmer/node-alias", 13 | "keywords": [ 14 | "node", 15 | "alias", 16 | "short", 17 | "command", 18 | "bin", 19 | "long" 20 | ], 21 | "author": "Justin Helmer ", 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/justinhelmer/node-alias/issues" 25 | }, 26 | "homepage": "https://github.com/justinhelmer/node-alias#readme", 27 | "dependencies": { 28 | "chalk": "^1.1.1", 29 | "lodash": "^4.2.0" 30 | }, 31 | "devDependencies": { 32 | "chai": "^3.5.0", 33 | "mocha": "^2.4.5", 34 | "require-subvert": "^0.1.0", 35 | "sinon": "^1.17.3", 36 | "sinon-chai": "^2.8.0" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Justin Helmer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file index.js 3 | * 4 | * Alias the long version of a command to the short version, with optional messaging. 5 | */ 6 | (function() { 7 | 'use strict'; 8 | 9 | var _ = require('lodash'); 10 | var chalk = require('chalk'); 11 | var path = require('path'); 12 | 13 | /** 14 | * Require the [short].js file, and optionally message the user. 15 | * 16 | * @param {string} short - The short name for the executable. Can include sub-commands, i.e. `var short = "[command] [foo]"`. If sub-commands 17 | * are used, kebab-case is the assumed format of the file. Sub-command functionality works well with `commander`. 18 | * @param {string} shortPath - The path where the `short` command file actually exists. Pass `__dirname` to use the same directory (i.e. when 19 | * using `Git style sub-commands` to pair with commander.js. 20 | * @param {object} [options] - Additional options to customize the behavior. 21 | * @param {mixed} [options.message] - Can be `true`, `false`, or a custom message. If set to `true`, displays a default message. Defaults to `true`. 22 | * @param {string} [options.color] - Specify a custom color. Comes from `chalk`. 23 | * 24 | * @see https://github.com/tj/commander.js 25 | * @see https://github.com/chalk/chalk 26 | */ 27 | function alias(short, shortPath, options) { 28 | if (!short) { 29 | throw new Error('Missing `short`'); 30 | } 31 | 32 | if (!shortPath) { 33 | throw new Error('Missing `shortPath`'); 34 | } 35 | 36 | if (_.get(options, 'message') !== false) { 37 | options = options || {}; 38 | var color = options.color || 'blue'; 39 | 40 | process.stdout.write(chalk.bold[color]('[INFO]:') + ' '); 41 | 42 | if (_.isString(options.message)) { 43 | process.stdout.write(options.message); 44 | } else { 45 | process.stdout.write('You can also use ' + chalk.bold[color](short) + ' as an alias'); 46 | } 47 | 48 | console.log(); 49 | } 50 | 51 | require(path.resolve(shortPath, _.kebabCase(short))); 52 | } 53 | 54 | module.exports = alias; 55 | })(); 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node-alias 2 | Alias the long version of a command to the short version, with optional messaging. 3 | 4 | [![npm package](https://badge.fury.io/js/node-alias.svg)](https://www.npmjs.com/package/node-alias) 5 | [![node version](https://img.shields.io/node/v/node-alias.svg?style=flat)](http://nodejs.org/download/) 6 | [![build status](https://travis-ci.org/justinhelmer/node-alias.svg?branch=master)](https://travis-ci.org/justinhelmer/node-alias) 7 | [![dependency status](https://david-dm.org/justinhelmer/node-alias.svg)](https://github.com/justinhelmer/node-alias) 8 | [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/justinhelmer/node-alias/issues) 9 | 10 | A very simple module for aliasing a command; works well with [commander.js](https://github.com/tj/commander.js) and [commander.js-error](https://github.com/justinhelmer/commander.js-error). 11 | 12 | To demonstrate, here is an example from [npm-publish-release](https://github.com/justinhelmer/npm-publish-release); in file `bin/npm-publish-release.js`: 13 | 14 | ```js 15 | require('node-alias')('npr', __dirname); 16 | ``` 17 | 18 | Produces: 19 | 20 | ```shell 21 | $ npm-publish-release 22 | [INFO]: You can also use 'npr' as an alias. 23 | ... # runs command 24 | ``` 25 | 26 | ## Git style sub-commands 27 | 28 | Also works with `git(1)` style sub-commands. Here is an example from [gh-release-manager](https://github.com/justinhelmer/gh-release-manager); in file `bin/gh-release-manager.js`: 29 | 30 | ```js 31 | require('node-alias')('grm jsdoc', __dirname); 32 | ``` 33 | 34 | Assumes a file by the same name, converted to `kebab-case`, exists in the same location (i.e. `bin/grm-jsdoc.js`). If needed, a separate location can be specified using the `path` [option](#options). 35 | 36 | ## alias(short, path, options) 37 | 38 | - **short** _{string}_ - The short command name. must be a file in **path** by the same name (as far as `require` is concerned). 39 | - **path** _{string}_ - The path where the `short` command file actually exists. Pass `__dirname` to use the same directory (i.e. when using 40 | [Git style sub-commands](#git-style-sub-commands) to pair with [commander.js](https://github.com/tj/commander.js/). 41 | - **options** _{object}_ - Additional [options](#options) to customize the behavior. 42 | 43 | ## Options 44 | 45 | - **message** _{mixed}_ - Can be `true`, `false`, or a custom message. If set to `true`, displays a default message. Defaults to `true`. 46 | - **color** _{string}_ - Specify a custom [chalk](https://github.com/chalk/chalk) color for the message. Ignored if `message` === `false`. 47 | 48 | ## Contributing 49 | 50 | [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/justinhelmer/node-alias/issues) 51 | 52 | ## License 53 | 54 | The MIT License (MIT) 55 | 56 | Copyright (c) 2016 Justin Helmer 57 | 58 | Permission is hereby granted, free of charge, to any person obtaining a copy 59 | of this software and associated documentation files (the "Software"), to deal 60 | in the Software without restriction, including without limitation the rights 61 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 62 | copies of the Software, and to permit persons to whom the Software is 63 | furnished to do so, subject to the following conditions: 64 | 65 | The above copyright notice and this permission notice shall be included in all 66 | copies or substantial portions of the Software. 67 | 68 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 69 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 70 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 71 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 72 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 73 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 74 | SOFTWARE. 75 | -------------------------------------------------------------------------------- /test/alias.unit.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | var CHALK_RESULT = '_CHALK_RESULT_'; 5 | 6 | var _ = require('lodash'); 7 | var chai = require('chai'); 8 | var sinon = require('sinon'); 9 | var sinonChai = require('sinon-chai'); 10 | var expect = chai.expect; 11 | var path = require('path'); 12 | var requireSubvert = require('require-subvert')(__dirname); 13 | 14 | chai.use(sinonChai); 15 | 16 | var sandbox = sinon.sandbox.create(); 17 | var short = 'test'; 18 | var shortWithSub = 'test sub'; 19 | 20 | 21 | var fullpath = path.resolve(__dirname); 22 | var stubs = {}; 23 | stubs[fullpath + '/' + short] = {}; 24 | stubs[fullpath + '/' + _.kebabCase(shortWithSub)] = {}; 25 | 26 | describe('alias (exported module)', function() { 27 | var alias, chalk; 28 | 29 | beforeEach(function() { 30 | chalk = { 31 | bold: { 32 | blue: sandbox.stub().returns(CHALK_RESULT), 33 | red: sandbox.stub().returns(CHALK_RESULT) 34 | } 35 | }; 36 | 37 | requireSubvert.subvert('chalk', chalk); 38 | requireSubvert.require('../index'); 39 | alias = require('../index'); 40 | }); 41 | 42 | afterEach(function() { 43 | sandbox.restore(); 44 | }); 45 | 46 | describe('when the input data is valid', function() { 47 | var _alias; 48 | 49 | beforeEach(function() { 50 | _alias = _.partial(alias, short, __dirname); 51 | 52 | sandbox.spy(process.stdout, 'write'); 53 | sandbox.spy(console, 'log'); 54 | }); 55 | 56 | it('if options.message is false should log nothing', function() { 57 | _alias({message: false}); 58 | expect(process.stdout.write).not.to.have.been.called; 59 | expect(console.log).not.to.have.been.called; 60 | }); 61 | 62 | describe('if options.message is not false', function() { 63 | it('should use the provided color if it exists', function() { 64 | var color = 'red'; 65 | 66 | quiet([ 67 | _.partial(_alias, {color: color}), 68 | _.partial(expectInfo, null, color) 69 | ]); 70 | }); 71 | 72 | it('should print the provided message if it is a string', function() { 73 | var message = '_MESSAGE_'; 74 | 75 | quiet([ 76 | _.partial(_alias, {message: message}), 77 | _.partial(expectInfo, message) 78 | ]); 79 | }); 80 | 81 | it('should print the default message if one is not provided', function() { 82 | quiet([_alias, expectInfo]); 83 | }); 84 | 85 | it('should print the default message options.message is `true`', function() { 86 | quiet([_.partial(_alias, {message: true}), expectInfo]); 87 | }); 88 | 89 | it('should print a blank line', function() { 90 | quiet([_alias]); 91 | expect(console.log).to.have.been.calledWith(); 92 | }); 93 | 94 | it('should support git style sub-commands', function() { 95 | var sub = _.partial(alias, shortWithSub, __dirname); 96 | quiet([sub]); 97 | expect(_.partial(quiet, [])).not.to.throw(); 98 | }); 99 | }); 100 | }); 101 | 102 | describe('when the input data is not valid', function() { 103 | it('should throw an error if `short` is not provided', function() { 104 | expect(alias).to.throw('Missing `short`'); 105 | }); 106 | 107 | it('should throw an error if `shortPath` is not provided', function() { 108 | expect(_.partial(alias, short)).to.throw('Missing `shortPath`'); 109 | }); 110 | }); 111 | 112 | // Make the expectations each time to validate they don't change when options change 113 | function expectInfo(message, color) { 114 | message = message || 'You can also use ' + CHALK_RESULT + ' as an alias'; 115 | color = color || 'blue'; 116 | 117 | expect(chalk.bold[color]).to.have.been.calledWith('[INFO]:'); 118 | expect(process.stdout.write).to.have.been.calledWith(CHALK_RESULT + ' '); 119 | expect(process.stdout.write).to.have.been.calledWith(message); 120 | } 121 | 122 | // needed because we have to be careful when to suppress stdout as to not suppress errors / test output 123 | function quiet(funcs) { 124 | var restore = process.stdout.write; 125 | process.stdout.write = sandbox.spy(); 126 | 127 | _.each(funcs, function(func) { 128 | func(); 129 | }); 130 | 131 | process.stdout.write = restore; 132 | } 133 | }); 134 | })(); 135 | --------------------------------------------------------------------------------