├── .gitignore ├── .npmrc ├── .travis.yml ├── README.md ├── bin └── with-package.js ├── package.json ├── renovate.json └── src ├── replace-vars-spec.js └── replace-vars.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | 3 | #IntelliJ 4 | .idea 5 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=http://registry.npmjs.org/ 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | cache: 3 | directories: 4 | - ~/.npm 5 | notifications: 6 | email: false 7 | node_js: 8 | - '8' 9 | after_success: 10 | - npm run travis-deploy-once "npm run semantic-release" 11 | branches: 12 | except: 13 | - /^v\d+\.\d+\.\d+$/ 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # with-package 2 | 3 | > Run any command with package.json properties exposed as environment variables 4 | 5 | [![NPM][with-package-icon]][with-package-url] 6 | 7 | [![Build status][ci-image]][ci-url] 8 | [![semantic-release][semantic-image] ][semantic-url] 9 | [![renovate-app badge][renovate-badge]][renovate-app] 10 | 11 | Imagine you want to use variables from the `package.json` in the script commands. 12 | Now you can. For example, let us say you want to commit and tag the git branch 13 | with the current `version` label. Install `with-package` and use it as first keyword 14 | in the command 15 | 16 | npm install --save-dev with-package 17 | 18 | ```json 19 | "scripts": { 20 | "release": "with-package git commit -am pkg.version && with-package git tag pkg.version" 21 | }, 22 | ``` 23 | 24 | Just refer to any primitive property of `package.json` as `pkg.`. Objects and 25 | arrays are not supported. If you need to debug the substitution, add `--debug` or `-d` flag 26 | to the command. 27 | 28 | with-package echo this is pkg.description --debug 29 | 30 | Note: some of the `package.json` variables are already exposed as environment variables, 31 | see [this doc](https://docs.npmjs.com/misc/scripts#package-json-vars). 32 | 33 | ## Small print 34 | 35 | Author: Gleb Bahmutov © 2015 36 | [@bahmutov](https://twitter.com/bahmutov) [glebbahmutov.com](http://glebbahmutov.com) 37 | [glebbahmutov.com/blog](http://glebbahmutov.com/blog) 38 | 39 | License: MIT - do anything with the code, but don't blame me if it does not work. 40 | 41 | Spread the word: tweet, star on github, etc. 42 | 43 | Support: if you find any problems with this module, email / tweet / open issue on Github 44 | 45 | [with-package-icon]: https://nodei.co/npm/with-package.svg?downloads=true 46 | [with-package-url]: https://npmjs.org/package/with-package 47 | [ci-image]: https://travis-ci.org/bahmutov/with-package.svg?branch=master 48 | [ci-url]: https://travis-ci.org/bahmutov/with-package 49 | [semantic-image]: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg 50 | [semantic-url]: https://github.com/semantic-release/semantic-release 51 | [renovate-badge]: https://img.shields.io/badge/renovate-app-blue.svg 52 | [renovate-app]: https://renovateapp.com/ 53 | -------------------------------------------------------------------------------- /bin/with-package.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | console.log('running with-package in', process.cwd()); 4 | var join = require('path').join; 5 | var fullPackagePath = join(process.cwd(), 'package.json'); 6 | var pkg = require(fullPackagePath); 7 | var quote = require('quote'); 8 | 9 | function noop() {}; 10 | function isDebug(args) { 11 | return args.some(function (arg) { 12 | return arg === '--debug' || arg === '-d'; 13 | }); 14 | } 15 | 16 | var log = isDebug(process.argv) ? console.log.bind(console) : noop; 17 | 18 | function isPrimitive(x) { 19 | return typeof x === 'string' || 20 | typeof x === 'number' || 21 | typeof x === 'boolean'; 22 | } 23 | console.assert(isPrimitive(true), 'true is primitive'); 24 | console.assert(isPrimitive(42), '42 is primitive'); 25 | console.assert(isPrimitive('foo'), '"foo" is primitive'); 26 | console.assert(!isPrimitive({}), '{} is NOT primitive'); 27 | console.assert(!isPrimitive([]), '[] is NOT primitive'); 28 | 29 | var primitives = Object.create(process.env); 30 | Object.keys(pkg).forEach(function (key) { 31 | var value = pkg[key]; 32 | if (isPrimitive(value)) { 33 | primitives[key] = value; 34 | } 35 | }); 36 | 37 | log(primitives); 38 | 39 | var args = process.argv.slice(2); 40 | if (!args.length) { 41 | return; 42 | } 43 | 44 | function escape(value) { 45 | if (typeof value === 'string' && value.length) { 46 | return quote(value); 47 | } 48 | } 49 | 50 | log('arguments', args); 51 | 52 | var replaceVars = require('../src/replace-vars'); 53 | var replacedArgs = replaceVars(primitives, args); 54 | 55 | log('replaced arguments', replacedArgs); 56 | 57 | var spawn = require('child_process').spawn; 58 | var proc = spawn(replacedArgs[0], replacedArgs.slice(1), { 59 | env: process.env 60 | }); 61 | 62 | proc.stdout.on('data', function (chunk) { 63 | process.stdout.write(chunk); 64 | }); 65 | 66 | proc.stderr.on('data', function (chunk) { 67 | process.stderr.write(chunk); 68 | }); 69 | 70 | proc.on('close', function (code) { 71 | log('child process exited with code ' + code); 72 | process.exitCode = code; 73 | }); 74 | 75 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "with-package", 3 | "version": "0.0.0-development", 4 | "description": "Run any command with package.json properties exposed as environment variables", 5 | "bin": { 6 | "with-package": "bin/with-package.js" 7 | }, 8 | "scripts": { 9 | "test": "mocha -R spec src/*-spec.js", 10 | "semantic-release": "semantic-release", 11 | "travis-deploy-once": "travis-deploy-once" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/bahmutov/with-package.git" 16 | }, 17 | "keywords": [ 18 | "npm", 19 | "script", 20 | "exec", 21 | "run", 22 | "command", 23 | "package", 24 | "variables", 25 | "environment", 26 | "variable" 27 | ], 28 | "author": "Gleb Bahmutov ", 29 | "license": "MIT", 30 | "bugs": { 31 | "url": "https://github.com/bahmutov/with-package/issues" 32 | }, 33 | "homepage": "https://github.com/bahmutov/with-package", 34 | "dependencies": { 35 | "check-more-types": "1.9.2", 36 | "lazy-ass": "0.6.0", 37 | "quote": "0.4.0" 38 | }, 39 | "devDependencies": { 40 | "mocha": "2.5.3", 41 | "pre-git": "0.8.2", 42 | "semantic-release": "15.14.0", 43 | "travis-deploy-once": "4.4.1" 44 | }, 45 | "pre-commit": [ 46 | "npm test", 47 | "npm version" 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["config:base"], 3 | "automerge": true, 4 | "major": { 5 | "automerge": false 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/replace-vars-spec.js: -------------------------------------------------------------------------------- 1 | require('lazy-ass'); 2 | var check = require('check-more-types'); 3 | 4 | describe('replace vars', function () { 5 | var replace = require('./replace-vars'); 6 | 7 | var pkg = { 8 | name: 'foo', 9 | version: '1.0.0', 10 | description: 'this is foo' 11 | }; 12 | 13 | it('replaces spaced arguments', function () { 14 | la(check.fn(replace)); 15 | var result = replace(pkg, ['something', 'pkg.name']); 16 | la(check.array(result)); 17 | la(result.length === 2); 18 | la(result[0] === 'something'); 19 | la(result[1] === 'foo'); 20 | }); 21 | 22 | it('replaces multiple spaced arguments', function () { 23 | var result = replace(pkg, ['pkg.name', 'pkg.version']); 24 | la(check.array(result)); 25 | la(result.length === 2); 26 | la(result[0] === 'foo'); 27 | la(result[1] === '1.0.0'); 28 | }); 29 | 30 | it('replaces combined arguments', function () { 31 | var result = replace(pkg, ['pkg.name@pkg.version']); 32 | la(check.array(result)); 33 | la(result.length === 1); 34 | la(result[0] === 'foo@1.0.0', 'replaced both parts', result[0]); 35 | }); 36 | 37 | }); 38 | -------------------------------------------------------------------------------- /src/replace-vars.js: -------------------------------------------------------------------------------- 1 | var propertyNameRegExp = /pkg\.([\w-]+)/; 2 | 3 | function isPackageProperty(x) { 4 | return propertyNameRegExp.test(x); 5 | } 6 | 7 | var prefix = 'pkg.'; 8 | 9 | function replaceVar(primitives, arg) { 10 | if (isPackageProperty(arg)) { 11 | var property = propertyNameRegExp.exec(arg)[1]; 12 | var originalText = prefix + property; 13 | var value = primitives[property] || ''; 14 | var updatedText = arg.replace(originalText, value); 15 | return replaceVar(primitives, updatedText); 16 | } else { 17 | return arg; 18 | } 19 | } 20 | 21 | function replaceVars(pkg, args) { 22 | var replaceArg = replaceVar.bind(null, pkg); 23 | var replacedArgs = args.map(replaceArg); 24 | return replacedArgs 25 | } 26 | 27 | 28 | module.exports = replaceVars; 29 | --------------------------------------------------------------------------------