diff --git a/bin/now-deploy b/bin/now-deploy index 22174ff..483fa06 100755 --- a/bin/now-deploy +++ b/bin/now-deploy @@ -14,7 +14,7 @@ import ms from 'ms'; import { handleError, error } from '../lib/error'; const argv = minimist(process.argv.slice(2), { - boolean: ['help', 'version', 'debug', 'force', 'login', 'no-clipboard'], + boolean: ['help', 'version', 'debug', 'force', 'login', 'no-clipboard', 'forward-npm'], alias: { help: 'h', debug: 'd', @@ -22,7 +22,8 @@ const argv = minimist(process.argv.slice(2), { force: 'f', forceSync: 'F', login: 'L', - 'no-clipboard': 'C' + 'no-clipboard': 'C', + 'forward-npm': 'N' } }); @@ -47,6 +48,7 @@ const help = () => { -f, --force force a new deployment even if nothing has changed -L, --login configure login -C, --no-clipboard do not attempt to copy URL to clipboard + -N, --forward-npm Forward login information to install private NPM modules ${chalk.dim('Examples:')} @@ -93,6 +95,7 @@ const exit = (code) => { // options const debug = argv.debug; const clipboard = !argv['no-clipboard']; +const forwardNpm = argv['forward-npm']; const force = argv.force; const forceSync = argv.forceSync; const shouldLogin = argv.login; @@ -138,7 +141,7 @@ async function sync (token) { const now = new Now(apiUrl, token, { debug }); try { - await now.create(path, { forceNew: force, forceSync: forceSync }); + await now.create(path, { forceNew: force, forceSync: forceSync, forwardNpm }); } catch (err) { handleError(err); process.exit(1); diff --git a/lib/index.js b/lib/index.js index e0acd72..571fcbd 100644 --- a/lib/index.js +++ b/lib/index.js @@ -7,6 +7,8 @@ import retry from 'async-retry'; import Agent from './agent'; import EventEmitter from 'events'; import { basename, resolve as resolvePath } from 'path'; +import { homedir } from 'os'; +import { parse as parseIni } from 'ini'; import { stat, readFile } from 'fs-promise'; import resumer from 'resumer'; import splitArray from 'split-array'; @@ -28,7 +30,7 @@ export default class Now extends EventEmitter { this._onRetry = this._onRetry.bind(this); } - async create (path, { forceNew, forceSync }) { + async create (path, { forceNew, forceSync, forwardNpm }) { this._path = path; try { @@ -61,6 +63,33 @@ export default class Now extends EventEmitter { throw e; } + const nowProperties = pkg.now || {}; + + forwardNpm = forwardNpm || nowProperties['forward-npm']; + + // Read .npmrc + let npmrc = {}; + let authToken; + if (forwardNpm) { + try { + npmrc = await readFile(resolvePath(path, '.npmrc'), 'utf8'); + npmrc = parseIni(npmrc); + authToken = npmrc['//registry.npmjs.org/:_authToken']; + } catch (err) { + // Do nothing + } + + if (!authToken) { + try { + npmrc = await readFile(resolvePath(homedir(), '.npmrc'), 'utf8'); + npmrc = parseIni(npmrc); + authToken = npmrc['//registry.npmjs.org/:_authToken']; + } catch (err) { + // Do nothing + } + } + } + if (this._debug) console.time('> [debug] Getting files'); const files = await getFiles(path, pkg, { debug: this._debug }); if (this._debug) console.timeEnd('> [debug] Getting files'); @@ -71,7 +100,6 @@ export default class Now extends EventEmitter { this._files = hashes; - const nowProperties = pkg.now || {}; const engines = nowProperties.engines || pkg.engines; const deployment = await this.retry(async (bail) => { @@ -83,6 +111,7 @@ export default class Now extends EventEmitter { forceSync, name: pkg.name || basename(path), description: pkg.description, + registryAuthToken: authToken, // Flatten the array to contain files to sync where each nested input // array has a group of files with the same sha but different path files: Array.prototype.concat.apply([], Array.from(this._files).map(([sha, { data, names }]) => { diff --git a/package.json b/package.json index 5f64116..56895c5 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "email-validator": "1.0.4", "fs-promise": "0.5.0", "graceful-fs": "4.1.4", + "ini": "1.3.4", "minimatch": "3.0.0", "minimist": "1.2.0", "ms": "0.7.1",