├── .babelrc ├── .gitignore ├── LICENSE ├── README.md ├── index.js ├── package.json └── src └── index.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ "es2015", "stage-0" ] 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Elijah Manor 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `cross-var` 2 | 3 | [![NPM](https://nodei.co/npm/cross-var.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/cross-var/) 4 | [![NPM](https://nodei.co/npm-dl/cross-var.png?months=9&height=3)](https://nodei.co/npm/cross-var/) 5 | 6 | [![npm version](https://img.shields.io/npm/v/cross-var.svg)](https://www.npmjs.com/package/cross-var) 7 | [![npm license](https://img.shields.io/npm/l/cross-var.svg)](https://www.npmjs.com/package/cross-var) 8 | [![npm download](https://img.shields.io/npm/dm/cross-var.svg)](https://www.npmjs.com/package/cross-var) 9 | [![npm download](https://img.shields.io/npm/dt/cross-var.svg)](https://www.npmjs.com/package/cross-var) 10 | [![Package Quality](http://npm.packagequality.com/shield/cross-var.svg)](http://packagequality.com/#?package=cross-var) 11 | [![Inline docs](http://inch-ci.org/github/elijahmanor/cross-var.svg?branch=master)](http://inch-ci.org/github/elijahmanor/cross-var) 12 | [![star this repo](http://githubbadges.com/star.svg?user=HansHammel&repo=cross-var&style=flat&color=fff&background=007ec6)](https://github.com/elijahmanor/cross-var) 13 | [![fork this repo](http://githubbadges.com/fork.svg?user=HansHammel&repo=cross-var&style=flat&color=fff&background=007ec6)](https://github.com/elijahmanor/cross-var/fork) 14 | 15 | [![david dependency](https://img.shields.io/david/elijahmanor/cross-var.svg)](https://david-dm.org/elijahmanor/cross-var) 16 | [![david devDependency](https://img.shields.io/david/dev/elijahmanor/cross-var.svg)](https://david-dm.org/elijahmanor/cross-var) 17 | [![david optionalDependency](https://img.shields.io/david/optional/elijahmanor/cross-var.svg)](https://david-dm.org/elijahmanor/cross-var) 18 | [![david peerDependency](https://img.shields.io/david/peer/elijahmanor/cross-var.svg)](https://david-dm.org/elijahmanor/cross-var) 19 | [![npms score](https://badges.npms.io/cross-var.svg)](https://www.npmjs.com/package/cross-var) 20 | [![Known Vulnerabilities](https://snyk.io/test/github/elijahmanor/cross-var/badge.svg)](https://snyk.io/test/github/elijahmanor/cross-var) 21 | 22 | ## Overview 23 | 24 | When using `npm scripts` it creates a lot of environment variables that are available for you to leverage when executing scripts. 25 | 26 | If you'd like to take a look at all of the variables then you can run `npm run env` in your terminal. 27 | 28 | ``` 29 | > npm run env 30 | 31 | npm_package_name=cross-var 32 | npm_package_author_name=Elijah Manor 33 | npm_package_version=1.0.0 34 | ... lots more ... 35 | ``` 36 | 37 | Now you can use those environment variables in your `npm scripts` by referencing them like the following 38 | 39 | ``` 40 | { 41 | "name": "World", 42 | "scripts": { 43 | "//": "The following only works on Mac OS X/Linux (bash)", 44 | "bash-script": "echo Hello $npm_package_name" 45 | "//": "The following only works on a Windows machine", 46 | "win-script": "echo Hello %npm_package_name%" 47 | } 48 | } 49 | ``` 50 | 51 | ``` 52 | > npm run bash-script 53 | 54 | Hello World 55 | ``` 56 | However, this won't work on Windows... because it expects the variables to be surrounded by percent signs, so we can change our script just slightly. 57 | 58 | ### `cross-var` to the Rescue! 59 | 60 | The goal of `cross-var` is to let you use one script syntax to work either on a **Mac OS X/Linux (bash)** or **Windows**. Reference the [Usage]() documention below on how to use `cross-var` in your scripts. 61 | 62 | ## Usage 63 | 64 | ### Simple Commands 65 | 66 | ``` 67 | { 68 | "version": "1.0.0", 69 | "config": { 70 | "port": "1337" 71 | }, 72 | "scripts": { 73 | "prebuild": "cross-var rimraf public/$npm_package_version", 74 | "build:html": "cross-var jade --obj data.json src/index.jade --out public/$npm_package_version/", 75 | "server:create": "cross-var http-server public/$npm_package_version -p $npm_package_config_port", 76 | "server:launch": "cross-var opn http://localhost:$npm_package_config_port" 77 | } 78 | } 79 | ``` 80 | 81 | ### Complex Commands 82 | 83 | ``` 84 | { 85 | "version": "1.0.0", 86 | "scripts": { 87 | "build:css": "cross-var \"node-sass src/index.scss | postcss -c .postcssrc.json | cssmin > public/$npm_package_version/index.min.css\"", 88 | "build:js": "cross-var \"mustache data.json src/index.mustache.js | uglifyjs > public/$npm_package_version/index.min.js\"", 89 | } 90 | } 91 | ``` 92 | 93 | ## But What About!?! 94 | 95 | > Click on one of the following questions to reveal a detailed answer 96 | 97 |
98 | Why don't you use `cross-env`? 99 | `cross-env` is great for scripts that need a particular environment variable 100 | set, but isn't intended to fix cross-environment issues when using variables 101 | inside an `npm script` 102 |
103 | 104 |
105 | Why don't you use an external node file? 106 | That is a fine solution to this problem, but if you would rather stick to 107 | straight up `npm scripts`, then this is a good solution 108 |
109 | 110 |
111 | Why don't you just use Windows 10 Ubuntu-based Bash shell? 112 | Yes, if you can do that... then great! Windows 10’s version 1607 update, dubbed the “Anniversary Update”, has [intergrated a great bash shell](https://msdn.microsoft.com/en-us/commandline/wsl/about) that should allow you to run Linux software directly on Windows without any changes. 113 | 114 | However, if you want to support older Windows versions, then you might consider using `cross-env` or another approach to leverage environment variables in your scripts. 115 |
116 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require( "babel-register" )( { 4 | ignore: false, 5 | only: /src/ 6 | } ); 7 | require( "./src/index.js" ); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cross-var", 3 | "version": "1.1.0", 4 | "description": "", 5 | "main": "index.js", 6 | "bin": { 7 | "cross-var": "./index.js" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 0" 11 | }, 12 | "author": "Elijah Manor", 13 | "license": "MIT", 14 | "publishConfig": { 15 | "registry": "https://registry.npmjs.org/" 16 | }, 17 | "keywords": [ 18 | "npm-scripts" 19 | ], 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/elijahmanor/cross-var" 23 | }, 24 | "bugs": { 25 | "url": "https://github.com/elijahmanor/cross-var/issues" 26 | }, 27 | "dependencies": { 28 | "babel-preset-es2015": "^6.18.0", 29 | "babel-preset-stage-0": "^6.16.0", 30 | "babel-register": "^6.18.0", 31 | "cross-spawn": "^5.0.1", 32 | "exit": "^0.1.2" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node --harmony 2 | 3 | import spawn from "cross-spawn"; 4 | import os from "os"; 5 | import { exec } from "child_process"; 6 | import exit from 'exit'; 7 | 8 | function normalize( args, isWindows ) { 9 | return args.map( arg => { 10 | Object.keys( process.env ) 11 | .sort( ( x, y ) => x.length < y.length ) // sort by descending length to prevent partial replacement 12 | .forEach( key => { 13 | const regex = new RegExp( `\\$${ key }|%${ key }%`, "ig" ); 14 | arg = arg.replace( regex, process.env[ key ] ); 15 | } ); 16 | return arg; 17 | } ) 18 | } 19 | 20 | let args = process.argv.slice( 2 ); 21 | if ( args.length === 1 ) { 22 | const [ command ] = normalize( args ); 23 | const proc = exec( command, ( error, stdout, stderr ) => { 24 | if ( error ) { 25 | console.error( `exec error: ${ error }` ); 26 | return; 27 | } 28 | process.stdout.write( stdout ); 29 | process.stderr.write( stderr ); 30 | exit(proc.code); 31 | }); 32 | } else { 33 | args = normalize( args ); 34 | const command = args.shift(); 35 | const proc = spawn.sync( command, args, { stdio: "inherit" } ); 36 | exit(proc.status); 37 | } 38 | --------------------------------------------------------------------------------